browser[SEVERE] webpack: A component is changing an uncontrolled input of type %s to be controlled (#55323)

* browser[SEVERE] webpack: A component is changing an uncontrolled input of type %s to be controlled.

Closes: #41017

* fix PR comments

* fix PR comment
This commit is contained in:
Alexey Antonov 2020-01-23 12:21:50 +03:00 committed by GitHub
parent 111d0db7e3
commit 4a8542f859
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 282 additions and 311 deletions

View file

@ -22,14 +22,13 @@ import React from 'react';
import { last } from 'lodash';
import { AddDeleteButtons } from '../add_delete_buttons';
import { EuiIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { injectI18n } from '@kbn/i18n/react';
import { SeriesDragHandler } from '../series_drag_handler';
import { i18n } from '@kbn/i18n';
function AggRowUi(props) {
export function AggRow(props) {
let iconType = 'eyeClosed';
let iconColor = 'subdued';
const lastSibling = last(props.siblings);
const { intl } = props;
if (lastSibling.id === props.model.id) {
iconType = 'eye';
@ -57,12 +56,10 @@ function AggRowUi(props) {
<EuiFlexItem grow={false}>
<AddDeleteButtons
testSubj="addMetric"
addTooltip={intl.formatMessage({
id: 'visTypeTimeseries.aggRow.addMetricButtonTooltip',
addTooltip={i18n.translate('visTypeTimeseries.aggRow.addMetricButtonTooltip', {
defaultMessage: 'Add Metric',
})}
deleteTooltip={intl.formatMessage({
id: 'visTypeTimeseries.aggRow.deleteMetricButtonTooltip',
deleteTooltip={i18n.translate('visTypeTimeseries.aggRow.deleteMetricButtonTooltip', {
defaultMessage: 'Delete Metric',
})}
onAdd={props.onAdd}
@ -75,7 +72,7 @@ function AggRowUi(props) {
);
}
AggRowUi.propTypes = {
AggRow.propTypes = {
disableDelete: PropTypes.bool,
model: PropTypes.object,
onAdd: PropTypes.func,
@ -83,5 +80,3 @@ AggRowUi.propTypes = {
siblings: PropTypes.array,
dragHandleProps: PropTypes.object,
};
export const AggRow = injectI18n(AggRowUi);

View file

@ -226,7 +226,7 @@ function filterByPanelType(panelType) {
}
function AggSelectUi(props) {
const { siblings, panelType, value, onChange, intl, uiRestrictions, ...rest } = props;
const { siblings, panelType, value, onChange, uiRestrictions, ...rest } = props;
const selectedOptions = allAggOptions.filter(option => {
return value === option.value && isMetricEnabled(option.value, uiRestrictions);
@ -247,8 +247,7 @@ function AggSelectUi(props) {
options = [
{
label: intl.formatMessage({
id: 'visTypeTimeseries.aggSelect.aggGroups.metricAggLabel',
label: i18n.translate('visTypeTimeseries.aggSelect.aggGroups.metricAggLabel', {
defaultMessage: 'Metric Aggregations',
}),
options: metricAggs.map(agg => ({
@ -257,22 +256,19 @@ function AggSelectUi(props) {
})),
},
{
label: intl.formatMessage({
id: 'visTypeTimeseries.aggSelect.aggGroups.parentPipelineAggLabel',
label: i18n.translate('visTypeTimeseries.aggSelect.aggGroups.parentPipelineAggLabel', {
defaultMessage: 'Parent Pipeline Aggregations',
}),
options: pipelineAggs.filter(filterByPanelType(panelType)).map(disableSiblingAggs),
},
{
label: intl.formatMessage({
id: 'visTypeTimeseries.aggSelect.aggGroups.siblingPipelineAggLabel',
label: i18n.translate('visTypeTimeseries.aggSelect.aggGroups.siblingPipelineAggLabel', {
defaultMessage: 'Sibling Pipeline Aggregations',
}),
options: siblingAggs.map(disableSiblingAggs),
},
{
label: intl.formatMessage({
id: 'visTypeTimeseries.aggSelect.aggGroups.specialAggLabel',
label: i18n.translate('visTypeTimeseries.aggSelect.aggGroups.specialAggLabel', {
defaultMessage: 'Special Aggregations',
}),
options: specialAggs.map(disableSiblingAggs),
@ -289,8 +285,7 @@ function AggSelectUi(props) {
<div data-test-subj="aggSelector">
<EuiComboBox
isClearable={false}
placeholder={intl.formatMessage({
id: 'visTypeTimeseries.aggSelect.selectAggPlaceholder',
placeholder={i18n.translate('visTypeTimeseries.aggSelect.selectAggPlaceholder', {
defaultMessage: 'Select aggregation',
})}
options={options}

View file

@ -18,16 +18,14 @@
*/
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import _ from 'lodash';
import uuid from 'uuid';
import React, { useEffect } from 'react';
import { AggRow } from './agg_row';
import { AggSelect } from './agg_select';
import { createChangeHandler } from '../lib/create_change_handler';
import { createSelectHandler } from '../lib/create_select_handler';
import { createTextHandler } from '../lib/create_text_handler';
import { CalculationVars } from './vars';
import { CalculationVars, newVariable } from './vars';
import { FormattedMessage } from '@kbn/i18n/react';
import {
@ -41,105 +39,100 @@ import {
EuiSpacer,
} from '@elastic/eui';
export class CalculationAgg extends Component {
UNSAFE_componentWillMount() {
if (!this.props.model.variables) {
this.props.onChange(
_.assign({}, this.props.model, {
variables: [{ id: uuid.v1() }],
})
);
const checkModel = model => Array.isArray(model.variables) && model.script !== undefined;
export function CalculationAgg(props) {
const htmlId = htmlIdGenerator();
const { siblings, model } = props;
const handleChange = createChangeHandler(props.onChange, model);
const handleSelectChange = createSelectHandler(handleChange);
const handleTextChange = createTextHandler(handleChange);
useEffect(() => {
if (!checkModel(model)) {
handleChange({
variables: [newVariable()],
script: '',
});
}
}
}, [handleChange, model]);
render() {
const { siblings } = this.props;
const defaults = { script: '' };
const model = { ...defaults, ...this.props.model };
const handleChange = createChangeHandler(this.props.onChange, model);
const handleSelectChange = createSelectHandler(handleChange);
const handleTextChange = createTextHandler(handleChange);
const htmlId = htmlIdGenerator();
return (
<AggRow
disableDelete={this.props.disableDelete}
model={this.props.model}
onAdd={this.props.onAdd}
onDelete={this.props.onDelete}
siblings={this.props.siblings}
dragHandleProps={this.props.dragHandleProps}
>
<EuiFlexGroup direction="column" gutterSize="l">
<EuiFlexItem>
<EuiFormLabel htmlFor={htmlId('aggregation')}>
<FormattedMessage
id="visTypeTimeseries.calculation.aggregationLabel"
defaultMessage="Aggregation"
/>
</EuiFormLabel>
<EuiSpacer size="xs" />
<AggSelect
id={htmlId('aggregation')}
panelType={this.props.panel.type}
siblings={this.props.siblings}
value={model.type}
onChange={handleSelectChange('type')}
return (
<AggRow
disableDelete={props.disableDelete}
model={props.model}
onAdd={props.onAdd}
onDelete={props.onDelete}
siblings={props.siblings}
dragHandleProps={props.dragHandleProps}
>
<EuiFlexGroup direction="column" gutterSize="l">
<EuiFlexItem>
<EuiFormLabel htmlFor={htmlId('aggregation')}>
<FormattedMessage
id="visTypeTimeseries.calculation.aggregationLabel"
defaultMessage="Aggregation"
/>
</EuiFlexItem>
</EuiFormLabel>
<EuiSpacer size="xs" />
<AggSelect
id={htmlId('aggregation')}
panelType={props.panel.type}
siblings={props.siblings}
value={model.type}
onChange={handleSelectChange('type')}
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormLabel htmlFor={htmlId('variables')}>
<FormattedMessage
id="visTypeTimeseries.calculation.variablesLabel"
defaultMessage="Variables"
/>
</EuiFormLabel>
<EuiSpacer size="xs" />
<CalculationVars
id={htmlId('variables')}
metrics={siblings}
onChange={handleChange}
name="variables"
model={model}
<EuiFlexItem>
<EuiFormLabel htmlFor={htmlId('variables')}>
<FormattedMessage
id="visTypeTimeseries.calculation.variablesLabel"
defaultMessage="Variables"
/>
</EuiFlexItem>
</EuiFormLabel>
<EuiSpacer size="xs" />
<CalculationVars
id={htmlId('variables')}
metrics={siblings}
onChange={handleChange}
name="variables"
model={model}
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow
id={htmlId('painless')}
label={
<EuiFlexItem>
<EuiFormRow
id={htmlId('painless')}
label={
<FormattedMessage
id="visTypeTimeseries.calculation.painlessScriptLabel"
defaultMessage="Painless Script"
/>
}
fullWidth
helpText={
<div>
<FormattedMessage
id="visTypeTimeseries.calculation.painlessScriptLabel"
defaultMessage="Painless Script"
/>
}
fullWidth
helpText={
<div>
<FormattedMessage
id="visTypeTimeseries.calculation.painlessScriptDescription"
defaultMessage="Variables are keys on the {params} object, i.e. {paramsName}. To access the bucket
id="visTypeTimeseries.calculation.painlessScriptDescription"
defaultMessage="Variables are keys on the {params} object, i.e. {paramsName}. To access the bucket
interval (in milliseconds) use {paramsInterval}."
values={{
params: <EuiCode>params</EuiCode>,
paramsName: <EuiCode>params.&lt;name&gt;</EuiCode>,
paramsInterval: <EuiCode>params._interval</EuiCode>,
}}
/>
</div>
}
>
<EuiTextArea onChange={handleTextChange('script')} value={model.script} fullWidth />
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</AggRow>
);
}
values={{
params: <EuiCode>params</EuiCode>,
paramsName: <EuiCode>params.&lt;name&gt;</EuiCode>,
paramsInterval: <EuiCode>params._interval</EuiCode>,
}}
/>
</div>
}
>
<EuiTextArea onChange={handleTextChange('script')} value={model.script} fullWidth />
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</AggRow>
);
}
CalculationAgg.propTypes = {

View file

@ -17,17 +17,15 @@
* under the License.
*/
import React, { Component } from 'react';
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import uuid from 'uuid';
import { AggRow } from './agg_row';
import { AggSelect } from './agg_select';
import { createChangeHandler } from '../lib/create_change_handler';
import { createSelectHandler } from '../lib/create_select_handler';
import { createTextHandler } from '../lib/create_text_handler';
import { CalculationVars } from './vars';
import { CalculationVars, newVariable } from './vars';
import {
htmlIdGenerator,
EuiFlexGroup,
@ -41,125 +39,121 @@ import {
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
export class MathAgg extends Component {
UNSAFE_componentWillMount() {
if (!this.props.model.variables) {
this.props.onChange(
_.assign({}, this.props.model, {
variables: [{ id: uuid.v1() }],
})
);
const checkModel = model => Array.isArray(model.variables) && model.script !== undefined;
export function MathAgg(props) {
const { siblings, model } = props;
const htmlId = htmlIdGenerator();
const handleChange = createChangeHandler(props.onChange, model);
const handleSelectChange = createSelectHandler(handleChange);
const handleTextChange = createTextHandler(handleChange);
useEffect(() => {
if (!checkModel(model)) {
handleChange({
variables: [newVariable()],
script: '',
});
}
}
}, [handleChange, model]);
render() {
const { siblings } = this.props;
const htmlId = htmlIdGenerator();
const defaults = { script: '' };
const model = { ...defaults, ...this.props.model };
const handleChange = createChangeHandler(this.props.onChange, model);
const handleSelectChange = createSelectHandler(handleChange);
const handleTextChange = createTextHandler(handleChange);
return (
<AggRow
disableDelete={this.props.disableDelete}
model={this.props.model}
onAdd={this.props.onAdd}
onDelete={this.props.onDelete}
siblings={this.props.siblings}
dragHandleProps={this.props.dragHandleProps}
>
<EuiFlexGroup direction="column" gutterSize="l">
<EuiFlexItem>
<EuiFormLabel htmlFor={htmlId('aggregation')}>
<FormattedMessage
id="visTypeTimeseries.math.aggregationLabel"
defaultMessage="Aggregation"
/>
</EuiFormLabel>
<EuiSpacer size="xs" />
<AggSelect
id={htmlId('aggregation')}
siblings={this.props.siblings}
value={model.type}
onChange={handleSelectChange('type')}
return (
<AggRow
disableDelete={props.disableDelete}
model={props.model}
onAdd={props.onAdd}
onDelete={props.onDelete}
siblings={props.siblings}
dragHandleProps={props.dragHandleProps}
>
<EuiFlexGroup direction="column" gutterSize="l">
<EuiFlexItem>
<EuiFormLabel htmlFor={htmlId('aggregation')}>
<FormattedMessage
id="visTypeTimeseries.math.aggregationLabel"
defaultMessage="Aggregation"
/>
</EuiFlexItem>
</EuiFormLabel>
<EuiSpacer size="xs" />
<AggSelect
id={htmlId('aggregation')}
siblings={props.siblings}
value={model.type}
onChange={handleSelectChange('type')}
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormLabel htmlFor={htmlId('variables')}>
<FormattedMessage
id="visTypeTimeseries.math.variablesLabel"
defaultMessage="Variables"
/>
</EuiFormLabel>
<EuiSpacer size="xs" />
<CalculationVars
id={htmlId('variables')}
metrics={siblings}
onChange={handleChange}
name="variables"
model={model}
includeSiblings={true}
<EuiFlexItem>
<EuiFormLabel htmlFor={htmlId('variables')}>
<FormattedMessage
id="visTypeTimeseries.math.variablesLabel"
defaultMessage="Variables"
/>
</EuiFlexItem>
</EuiFormLabel>
<EuiSpacer size="xs" />
<CalculationVars
id={htmlId('variables')}
metrics={siblings}
onChange={handleChange}
name="variables"
model={model}
includeSiblings={true}
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow
id="mathExpressionInput"
label={
<FormattedMessage
id="visTypeTimeseries.math.expressionLabel"
defaultMessage="Expression"
/>
}
fullWidth
helpText={
<FormattedMessage
id="visTypeTimeseries.math.expressionDescription"
defaultMessage="This field uses basic math expressions (see {link}) - Variables are keys on the {params} object,
<EuiFlexItem>
<EuiFormRow
id="mathExpressionInput"
label={
<FormattedMessage
id="visTypeTimeseries.math.expressionLabel"
defaultMessage="Expression"
/>
}
fullWidth
helpText={
<FormattedMessage
id="visTypeTimeseries.math.expressionDescription"
defaultMessage="This field uses basic math expressions (see {link}) - Variables are keys on the {params} object,
i.e. {paramsName} To access all the data use {paramsValues} for an array of the values and {paramsTimestamps} for
an array of the timestamps. {paramsTimestamp} is available for the current bucket's timestamp,
{paramsIndex} is available for the current bucket's index, and {paramsInterval}s available for
the interval in milliseconds."
values={{
link: (
<EuiLink
href="https://github.com/elastic/tinymath/blob/master/docs/functions.md"
target="_blank"
>
<FormattedMessage
id="visTypeTimeseries.math.expressionDescription.tinyMathLinkText"
defaultMessage="TinyMath"
/>
</EuiLink>
),
params: <EuiCode>params</EuiCode>,
paramsName: <EuiCode>params.&lt;name&gt;</EuiCode>,
paramsValues: <EuiCode>params._all.&lt;name&gt;.values</EuiCode>,
paramsTimestamps: <EuiCode>params._all.&lt;name&gt;.timestamps</EuiCode>,
paramsTimestamp: <EuiCode>params._timestamp</EuiCode>,
paramsIndex: <EuiCode>params._index</EuiCode>,
paramsInterval: <EuiCode>params._interval</EuiCode>,
}}
/>
}
>
<EuiTextArea
data-test-subj="mathExpression"
onChange={handleTextChange('script')}
fullWidth
value={model.script}
values={{
link: (
<EuiLink
href="https://github.com/elastic/tinymath/blob/master/docs/functions.md"
target="_blank"
>
<FormattedMessage
id="visTypeTimeseries.math.expressionDescription.tinyMathLinkText"
defaultMessage="TinyMath"
/>
</EuiLink>
),
params: <EuiCode>params</EuiCode>,
paramsName: <EuiCode>params.&lt;name&gt;</EuiCode>,
paramsValues: <EuiCode>params._all.&lt;name&gt;.values</EuiCode>,
paramsTimestamps: <EuiCode>params._all.&lt;name&gt;.timestamps</EuiCode>,
paramsTimestamp: <EuiCode>params._timestamp</EuiCode>,
paramsIndex: <EuiCode>params._index</EuiCode>,
paramsInterval: <EuiCode>params._interval</EuiCode>,
}}
/>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</AggRow>
);
}
}
>
<EuiTextArea
data-test-subj="mathExpression"
onChange={handleTextChange('script')}
fullWidth
value={model.script}
/>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</AggRow>
);
}
MathAgg.propTypes = {

View file

@ -18,8 +18,7 @@
*/
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import _ from 'lodash';
import React, { useEffect } from 'react';
import { AggSelect } from './agg_select';
import { FieldSelect } from './field_select';
import { AggRow } from './agg_row';
@ -39,82 +38,78 @@ import { Percentiles, newPercentile } from './percentile_ui';
const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER];
export class PercentileAgg extends Component {
// eslint-disable-line react/no-multi-comp
const checkModel = model => Array.isArray(model.percentiles);
UNSAFE_componentWillMount() {
if (!this.props.model.percentiles) {
this.props.onChange(
_.assign({}, this.props.model, {
percentiles: [newPercentile({ value: 50 })],
})
);
export function PercentileAgg(props) {
const { series, model, panel, fields } = props;
const htmlId = htmlIdGenerator();
const handleChange = createChangeHandler(props.onChange, model);
const handleSelectChange = createSelectHandler(handleChange);
const indexPattern =
(series.override_index_pattern && series.series_index_pattern) || panel.index_pattern;
useEffect(() => {
if (!checkModel(model)) {
handleChange({
percentiles: [newPercentile({ value: 50 })],
});
}
}
}, [handleChange, model]);
render() {
const { series, model, panel, fields } = this.props;
const handleChange = createChangeHandler(this.props.onChange, model);
const handleSelectChange = createSelectHandler(handleChange);
const indexPattern =
(series.override_index_pattern && series.series_index_pattern) || panel.index_pattern;
const htmlId = htmlIdGenerator();
return (
<AggRow
disableDelete={this.props.disableDelete}
model={this.props.model}
onAdd={this.props.onAdd}
onDelete={this.props.onDelete}
siblings={this.props.siblings}
dragHandleProps={this.props.dragHandleProps}
>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem>
<EuiFormLabel htmlFor={htmlId('aggregation')}>
<FormattedMessage
id="visTypeTimeseries.percentile.aggregationLabel"
defaultMessage="Aggregation"
/>
</EuiFormLabel>
<EuiSpacer size="xs" />
<AggSelect
id={htmlId('aggregation')}
panelType={this.props.panel.type}
siblings={this.props.siblings}
value={model.type}
onChange={handleSelectChange('type')}
return (
<AggRow
disableDelete={props.disableDelete}
model={props.model}
onAdd={props.onAdd}
onDelete={props.onDelete}
siblings={props.siblings}
dragHandleProps={props.dragHandleProps}
>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem>
<EuiFormLabel htmlFor={htmlId('aggregation')}>
<FormattedMessage
id="visTypeTimeseries.percentile.aggregationLabel"
defaultMessage="Aggregation"
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow
id={htmlId('field')}
label={
<FormattedMessage
id="visTypeTimeseries.percentile.fieldLabel"
defaultMessage="Field"
/>
}
>
<FieldSelect
fields={fields}
type={model.type}
restrict={RESTRICT_FIELDS}
indexPattern={indexPattern}
value={model.field}
onChange={handleSelectChange('field')}
</EuiFormLabel>
<EuiSpacer size="xs" />
<AggSelect
id={htmlId('aggregation')}
panelType={props.panel.type}
siblings={props.siblings}
value={model.type}
onChange={handleSelectChange('type')}
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow
id={htmlId('field')}
label={
<FormattedMessage
id="visTypeTimeseries.percentile.fieldLabel"
defaultMessage="Field"
/>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
}
>
<FieldSelect
fields={fields}
type={model.type}
restrict={RESTRICT_FIELDS}
indexPattern={indexPattern}
value={model.field}
onChange={handleSelectChange('field')}
/>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
<EuiSpacer size="m" />
<Percentiles onChange={handleChange} name="percentiles" model={model} panel={panel} />
</AggRow>
);
}
<Percentiles onChange={handleChange} name="percentiles" model={model} panel={panel} />
</AggRow>
);
}
PercentileAgg.propTypes = {

View file

@ -19,14 +19,17 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import uuid from 'uuid';
import { i18n } from '@kbn/i18n';
import _ from 'lodash';
import { AddDeleteButtons } from '../add_delete_buttons';
import { collectionActions } from '../lib/collection_actions';
import { MetricSelect } from './metric_select';
import { EuiFlexGroup, EuiFlexItem, EuiFieldText } from '@elastic/eui';
import { injectI18n } from '@kbn/i18n/react';
class CalculationVarsUi extends Component {
export const newVariable = opts => ({ id: uuid.v1(), name: '', field: '', ...opts });
export class CalculationVars extends Component {
constructor(props) {
super(props);
this.renderRow = this.renderRow.bind(this);
@ -42,21 +45,19 @@ class CalculationVarsUi extends Component {
}
renderRow(row, i, items) {
const handleAdd = collectionActions.handleAdd.bind(null, this.props);
const handleAdd = collectionActions.handleAdd.bind(null, this.props, newVariable);
const handleDelete = collectionActions.handleDelete.bind(null, this.props, row);
const { intl } = this.props;
return (
<EuiFlexItem key={row.id} data-test-subj="varRow">
<EuiFlexGroup alignItems="center" responsive={false} gutterSize="s">
<EuiFlexItem>
<EuiFieldText
className="tvbAggs__varName"
aria-label={intl.formatMessage({
id: 'visTypeTimeseries.vars.variableNameAriaLabel',
aria-label={i18n.translate('visTypeTimeseries.vars.variableNameAriaLabel', {
defaultMessage: 'Variable name',
})}
placeholder={intl.formatMessage({
id: 'visTypeTimeseries.vars.variableNamePlaceholder',
placeholder={i18n.translate('visTypeTimeseries.vars.variableNamePlaceholder', {
defaultMessage: 'Variable name',
})}
onChange={this.handleChange(row, 'name')}
@ -97,17 +98,15 @@ class CalculationVarsUi extends Component {
}
}
CalculationVarsUi.defaultProps = {
CalculationVars.defaultProps = {
name: 'variables',
includeSiblings: false,
};
CalculationVarsUi.propTypes = {
CalculationVars.propTypes = {
metrics: PropTypes.array,
model: PropTypes.object,
name: PropTypes.string,
onChange: PropTypes.func,
includeSiblings: PropTypes.bool,
};
export const CalculationVars = injectI18n(CalculationVarsUi);