Skip to content

Commit

Permalink
[TSVB] Apply dateHistogramInterval utility (elastic#39665)
Browse files Browse the repository at this point in the history
* [TSVB] Apply dateHistogramInterval utility

* isModelValid -> isModelInvalid
  • Loading branch information
alexwizp committed Jul 5, 2019
1 parent f9fe126 commit f5be987
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 31 deletions.
42 changes: 34 additions & 8 deletions src/legacy/core_plugins/metrics/public/components/index_pattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@
*/

import PropTypes from 'prop-types';
import React from 'react';
import { FieldSelect } from './aggs/field_select';
import { createSelectHandler } from './lib/create_select_handler';
import { createTextHandler } from './lib/create_text_handler';
import { YesNo } from './yes_no';
import React, { useContext } from 'react';
import {
htmlIdGenerator,
EuiFieldText,
Expand All @@ -33,10 +29,33 @@ import {
EuiSpacer,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';

import { FieldSelect } from './aggs/field_select';
import { createSelectHandler } from './lib/create_select_handler';
import { createTextHandler } from './lib/create_text_handler';
import { YesNo } from './yes_no';
import { ES_TYPES } from '../../common/es_types';
import { FormValidationContext } from '../contexts/form_validation_context';
import {
isGteInterval,
validateReInterval,
isAutoInterval,
AUTO_INTERVAL,
} from './lib/get_interval';

const RESTRICT_FIELDS = [ES_TYPES.DATE];

const validateIntervalValue = intervalValue => {
const isAutoOrGteInterval = isGteInterval(intervalValue) || isAutoInterval(intervalValue);

if (isAutoOrGteInterval) {
return {
isValid: true,
};
}
return validateReInterval(intervalValue);
};

export const IndexPattern = props => {
const { fields, prefix } = props;
const handleSelectChange = createSelectHandler(props.onChange);
Expand All @@ -45,17 +64,21 @@ export const IndexPattern = props => {
const indexPatternName = `${prefix}index_pattern`;
const intervalName = `${prefix}interval`;
const dropBucketName = `${prefix}drop_last_bucket`;
const updateControlValidity = useContext(FormValidationContext);

const defaults = {
default_index_pattern: '',
[indexPatternName]: '*',
[intervalName]: 'auto',
[intervalName]: AUTO_INTERVAL,
[dropBucketName]: 1,
};

const htmlId = htmlIdGenerator();
const model = { ...defaults, ...props.model };
const isDefaultIndexPatternUsed = model.default_index_pattern && !model[indexPatternName];
const intervalValidation = validateIntervalValue(model[intervalName]);

updateControlValidity(intervalName, intervalValidation.isValid);

return (
<div className={props.className}>
Expand Down Expand Up @@ -107,6 +130,8 @@ export const IndexPattern = props => {
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFormRow
isInvalid={!intervalValidation.isValid}
error={intervalValidation.errorMessage}
id={htmlId('interval')}
label={
<FormattedMessage id="tsvb.indexPattern.intervalLabel" defaultMessage="Interval" />
Expand All @@ -120,10 +145,11 @@ export const IndexPattern = props => {
}
>
<EuiFieldText
isInvalid={!intervalValidation.isValid}
disabled={props.disabled}
onChange={handleTextChange(intervalName, 'auto')}
onChange={handleTextChange(intervalName, AUTO_INTERVAL)}
value={model[intervalName]}
placeholder={'auto'}
placeholder={AUTO_INTERVAL}
/>
</EuiFormRow>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
*/
import moment from 'moment';
import { i18n } from '@kbn/i18n';
import { pluck, get, clone, isString } from 'lodash';
import { pluck, get, clone } from 'lodash';
import { relativeOptions } from '../../../../../ui/public/timepicker/relative_options';

import { GTE_INTERVAL_RE, INTERVAL_STRING_RE } from '../../../common/interval_regexp';
import { GTE_INTERVAL_RE } from '../../../common/interval_regexp';
import { parseEsInterval } from '../../../../data/common/parse_es_interval';

export const AUTO_INTERVAL = 'auto';

Expand Down Expand Up @@ -50,13 +51,22 @@ export const convertIntervalIntoUnit = (interval, hasTranslateUnitString = true)
}
}
};

export const isGteInterval = interval => GTE_INTERVAL_RE.test(interval);
export const isAutoInterval = interval => !interval || interval === AUTO_INTERVAL;

export const validateReInterval = intervalValue => {
const validationResult = {};

try {
parseEsInterval(intervalValue);
} catch ({ message }) {
validationResult.errorMessage = message;
} finally {
validationResult.isValid = !validationResult.errorMessage;
}

export const isIntervalValid = interval => {
return (
isString(interval) &&
(interval === AUTO_INTERVAL || INTERVAL_STRING_RE.test(interval) || isGteInterval(interval))
);
return validationResult;
};

export const getInterval = (visData, model) => {
Expand Down
28 changes: 23 additions & 5 deletions src/legacy/core_plugins/metrics/public/components/panel_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/

import PropTypes from 'prop-types';
import React from 'react';
import React, { useState, useEffect } from 'react';
import { TimeseriesPanelConfig as timeseries } from './panel_config/timeseries';
import { MetricPanelConfig as metric } from './panel_config/metric';
import { TopNPanelConfig as topN } from './panel_config/top_n';
import { TablePanelConfig as table } from './panel_config/table';
import { GaugePanelConfig as gauge } from './panel_config/gauge';
import { MarkdownPanelConfig as markdown } from './panel_config/markdown';
import { FormattedMessage } from '@kbn/i18n/react';
import { FormValidationContext } from '../contexts/form_validation_context';

const types = {
timeseries,
Expand All @@ -36,12 +36,30 @@ const types = {
markdown,
};

const checkModelValidity = validationResults =>
Boolean(Object.values(validationResults).every(isValid => isValid));

export function PanelConfig(props) {
const { model } = props;
const component = types[model.type];
if (component) {
return React.createElement(component, props);
const Component = types[model.type];
const [formValidationResults] = useState({});

useEffect(() => {
model.isModelInvalid = !checkModelValidity(formValidationResults);
});

const updateControlValidity = (controlKey, isControlValid) => {
formValidationResults[controlKey] = isControlValid;
};

if (Component) {
return (
<FormValidationContext.Provider value={updateControlValidity}>
<Component {...props} />
</FormValidationContext.Provider>
);
}

return (
<div>
<FormattedMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import {
getInterval,
convertIntervalIntoUnit,
isIntervalValid,
isAutoInterval,
isGteInterval,
AUTO_INTERVAL,
} from './lib/get_interval';
Expand Down Expand Up @@ -126,7 +126,7 @@ class VisEditorVisualizationUI extends Component {
PANEL_TYPES.MARKDOWN,
PANEL_TYPES.TABLE,
].includes(type) &&
(interval === AUTO_INTERVAL || isGteInterval(interval) || !isIntervalValid(interval))
(isAutoInterval(interval) || isGteInterval(interval))
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import React from 'react';

export const FormValidationContext = React.createContext({});
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const MetricsRequestHandlerProvider = function(Private, config) {
const scaledDataFormat = config.get('dateFormat:scaled');
const dateFormat = config.get('dateFormat');

if (visParams && visParams.id) {
if (visParams && visParams.id && !visParams.isModelInvalid) {
try {
const maxBuckets = config.get('metrics:max_buckets');

Expand Down Expand Up @@ -65,6 +65,8 @@ const MetricsRequestHandlerProvider = function(Private, config) {
return Promise.reject(error);
}
}

return Promise.resolve({});
},
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

import _ from 'lodash';
import { dateHistogramInterval } from '../../../../../../data/common';
import { getBucketSize } from '../../helpers/get_bucket_size';
import { getTimerange } from '../../helpers/get_timerange';

Expand All @@ -37,13 +38,13 @@ export function dateHistogram(

_.set(doc, `aggs.${annotation.id}.date_histogram`, {
field: timeField,
interval: intervalString,
min_doc_count: 0,
time_zone: timezone,
extended_bounds: {
min: from.valueOf(),
max: to.valueOf() - bucketSize * 1000,
},
...dateHistogramInterval(intervalString),
});
return next(doc);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe('dateHistogram(req, panel, series)', () => {
timeseries: {
date_histogram: {
field: '@timestamp',
interval: '10s',
fixed_interval: '10s',
min_doc_count: 0,
time_zone: 'UTC',
extended_bounds: {
Expand Down Expand Up @@ -106,7 +106,7 @@ describe('dateHistogram(req, panel, series)', () => {
timeseries: {
date_histogram: {
field: '@timestamp',
interval: '10s',
fixed_interval: '10s',
min_doc_count: 0,
time_zone: 'UTC',
extended_bounds: {
Expand Down Expand Up @@ -143,7 +143,7 @@ describe('dateHistogram(req, panel, series)', () => {
timeseries: {
date_histogram: {
field: 'timestamp',
interval: '20s',
fixed_interval: '20s',
min_doc_count: 0,
time_zone: 'UTC',
extended_bounds: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
* under the License.
*/

import { set } from 'lodash';
import { dateHistogramInterval } from '../../../../../../data/common';
import { getBucketSize } from '../../helpers/get_bucket_size';
import { offsetTime } from '../../offset_time';
import { getIntervalAndTimefield } from '../../get_interval_and_timefield';
import { set } from 'lodash';

export function dateHistogram(req, panel, series, esQueryConfig, indexPatternObject, capabilities) {
return next => doc => {
Expand All @@ -31,20 +32,21 @@ export function dateHistogram(req, panel, series, esQueryConfig, indexPatternObj

set(doc, `aggs.${series.id}.aggs.timeseries.date_histogram`, {
field: timeField,
interval: intervalString,
min_doc_count: 0,
time_zone: timezone,
extended_bounds: {
min: from.valueOf(),
max: to.valueOf(),
},
...dateHistogramInterval(intervalString),
});
set(doc, `aggs.${series.id}.meta`, {
timeField,
intervalString,
bucketSize,
seriesId: series.id,
});

return next(doc);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

import { set } from 'lodash';
import { dateHistogramInterval } from '../../../../../../data/common';
import { getBucketSize } from '../../helpers/get_bucket_size';
import { getIntervalAndTimefield } from '../../get_interval_and_timefield';
import { getTimerange } from '../../helpers/get_timerange';
Expand All @@ -34,14 +35,15 @@ export function dateHistogram(req, panel, esQueryConfig, indexPatternObject, cap
const aggRoot = calculateAggRoot(doc, column);
set(doc, `${aggRoot}.timeseries.date_histogram`, {
field: timeField,
interval: intervalString,
min_doc_count: 0,
time_zone: timezone,
extended_bounds: {
min: from.valueOf(),
max: to.valueOf(),
},
...dateHistogramInterval(intervalString),
});

set(doc, aggRoot.replace(/\.aggs$/, '.meta'), {
timeField,
intervalString,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ describe('buildRequestBody(req)', () => {
min: 1485463055881,
},
field: '@timestamp',
interval: '10s',
fixed_interval: '10s',
min_doc_count: 0,
time_zone: 'UTC',
},
Expand Down

0 comments on commit f5be987

Please sign in to comment.