From 6dfc89590c4d246b25762353844a44fe2f9e3d98 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Mon, 24 May 2021 17:08:22 +0300 Subject: [PATCH] Updated code, based on nits and fixed reasons of pipeline errors. --- .../common/last_value_utils.test.ts | 25 ++------ .../common/last_value_utils.ts | 4 +- .../application/components/color_rules.tsx | 32 +++++----- .../components/lib/convert_series_to_vars.js | 4 +- .../components/vis_types/gauge/vis.js | 4 +- .../components/vis_types/metric/vis.js | 4 +- .../components/vis_types/top_n/vis.js | 6 +- .../application/visualizations/views/gauge.js | 4 +- .../visualizations/views/metric.js | 6 +- .../application/visualizations/views/top_n.js | 6 +- .../lib/vis_data/table/process_bucket.js | 4 +- .../saved_objects/visualization_migrations.ts | 58 +++++++------------ 12 files changed, 61 insertions(+), 96 deletions(-) diff --git a/src/plugins/vis_type_timeseries/common/last_value_utils.test.ts b/src/plugins/vis_type_timeseries/common/last_value_utils.test.ts index 4d747701daabde..34e1265b9a6a26 100644 --- a/src/plugins/vis_type_timeseries/common/last_value_utils.test.ts +++ b/src/plugins/vis_type_timeseries/common/last_value_utils.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { getLastValue, getLastValueOrEmpty, isEmptyValue, EMPTY_VALUE } from './last_value_utils'; +import { getLastValue, isEmptyValue, EMPTY_VALUE } from './last_value_utils'; import { clone } from 'lodash'; describe('getLastValue(data)', () => { @@ -28,37 +28,20 @@ describe('getLastValue(data)', () => { expect(getLastValue([[0, 0]])).toBe(0); }); - test("should return null, if second array is empty or it's last element is null/undefined (default)", () => { + test("should return empty value (null), if second array is empty or it's last element is null/undefined (default)", () => { expect( getLastValue([ [1, null], [2, null], ]) - ).toBeNull(); + ).toBe(EMPTY_VALUE); expect( getLastValue([ [1, null], [2, undefined], ]) - ).toBeNull(); - }); -}); - -describe('getLastValueOrEmpty(data)', () => { - test('should return empty array', () => { - expect(getLastValueOrEmpty()).toBe(EMPTY_VALUE); - }); - - test('should return the last value', () => { - const lastValue = 10; - const data = [[1, lastValue]]; - expect(getLastValueOrEmpty(data)).toBe(lastValue); - }); - - test(`should return empty array, if second array is empty or it's last element is null/undefined (default)`, () => { - const data = [[1, null]]; - expect(getLastValueOrEmpty(data)).toBe(EMPTY_VALUE); + ).toBe(EMPTY_VALUE); }); }); diff --git a/src/plugins/vis_type_timeseries/common/last_value_utils.ts b/src/plugins/vis_type_timeseries/common/last_value_utils.ts index a3e39245decd89..a51a04962a8918 100644 --- a/src/plugins/vis_type_timeseries/common/last_value_utils.ts +++ b/src/plugins/vis_type_timeseries/common/last_value_utils.ts @@ -11,7 +11,7 @@ import { isArray, last, isEqual } from 'lodash'; export const EMPTY_VALUE = null; export const DISPLAY_EMPTY_VALUE = '-'; -const extractValue = (data: unknown[] | void) => (data && data[1]) ?? null; +const extractValue = (data: unknown[] | void) => (data && data[1]) ?? EMPTY_VALUE; export const getLastValue = (data: unknown) => { if (!isArray(data)) { @@ -21,6 +21,4 @@ export const getLastValue = (data: unknown) => { return extractValue(last(data)); }; -export const getLastValueOrEmpty = (data: unknown) => getLastValue(data) ?? EMPTY_VALUE; - export const isEmptyValue = (value: unknown) => isEqual(value, EMPTY_VALUE); diff --git a/src/plugins/vis_type_timeseries/public/application/components/color_rules.tsx b/src/plugins/vis_type_timeseries/public/application/components/color_rules.tsx index 41298b9c6e6aa8..9671c2aa90e9d7 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/color_rules.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/color_rules.tsx @@ -45,8 +45,7 @@ interface ColorRule { } export interface ColorRulesOperator { - translateNameId: string; - defaultName: string; + label: string; method: string; value?: unknown; isValueConstant?: boolean; @@ -64,37 +63,40 @@ const defaultPrimaryName = i18n.translate('visTypeTimeseries.colorRules.defaultP export const colorRulesOperatorsList: ColorRulesOperator[] = [ { - translateNameId: 'visTypeTimeseries.colorRules.greaterThanLabel', - defaultName: '> greater than', + label: i18n.translate('visTypeTimeseries.colorRules.greaterThanLabel', { + defaultMessage: '> greater than', + }), method: 'gt', }, { - translateNameId: 'visTypeTimeseries.colorRules.greaterThanOrEqualLabel', - defaultName: '>= greater than or equal', + label: i18n.translate('visTypeTimeseries.colorRules.greaterThanOrEqualLabel', { + defaultMessage: '>= greater than or equal', + }), method: 'gte', }, { - translateNameId: 'visTypeTimeseries.colorRules.lessThanLabel', - defaultName: '< less than', + label: i18n.translate('visTypeTimeseries.colorRules.lessThanLabel', { + defaultMessage: '< less than', + }), method: 'lt', }, { - translateNameId: 'visTypeTimeseries.colorRules.lessThanOrEqualLabel', - defaultName: '<= less than or equal', + label: i18n.translate('visTypeTimeseries.colorRules.lessThanOrEqualLabel', { + defaultMessage: '<= less than or equal', + }), method: 'lte', }, { - translateNameId: 'visTypeTimeseries.colorRules.emptyLabel', - defaultName: 'empty', + label: i18n.translate('visTypeTimeseries.colorRules.emptyLabel', { + defaultMessage: 'empty', + }), method: 'empty', isValueConstant: true, }, ]; const operatorOptions = colorRulesOperatorsList.map((operator) => ({ - label: i18n.translate(operator.translateNameId, { - defaultMessage: operator.defaultName, - }), + label: operator.label, value: operator.method, })); diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/convert_series_to_vars.js b/src/plugins/vis_type_timeseries/public/application/components/lib/convert_series_to_vars.js index f76721a3281e6c..3616a8c8b348d7 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/convert_series_to_vars.js +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/convert_series_to_vars.js @@ -8,7 +8,7 @@ import { set } from '@elastic/safer-lodash-set'; import _ from 'lodash'; -import { getLastValueOrEmpty } from '../../../../common/last_value_utils'; +import { getLastValue } from '../../../../common/last_value_utils'; import { emptyLabel } from '../../../../common/empty_label'; import { createTickFormatter } from './tick_formatter'; import { labelDateFormatter } from './label_date_formatter'; @@ -28,7 +28,7 @@ export const convertSeriesToVars = (series, model, dateFormat = 'lll', getConfig seriesModel.value_template, getConfig ); - const lastValue = getLastValueOrEmpty(row.data); + const lastValue = getLastValue(row.data); const data = { last: { diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/gauge/vis.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/gauge/vis.js index ce13d35de5b2f7..8426a275196b27 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/gauge/vis.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/gauge/vis.js @@ -12,7 +12,7 @@ import { visWithSplits } from '../../vis_with_splits'; import { createTickFormatter } from '../../lib/tick_formatter'; import { get, isUndefined, assign, includes, gt, gte, lt, lte, isNull } from 'lodash'; import { Gauge } from '../../../visualizations/views/gauge'; -import { getLastValueOrEmpty } from '../../../../../common/last_value_utils'; +import { getLastValue } from '../../../../../common/last_value_utils'; const OPERATORS = { gt, gte, lt, lte, empty: isNull }; const OPERATORS_ALLOW_NULL = { empty: true, @@ -26,7 +26,7 @@ function getColors(props) { if (model.gauge_color_rules) { model.gauge_color_rules.forEach((rule) => { if (rule.operator) { - const value = getLastValueOrEmpty(series[0]?.data); + const value = getLastValue(series[0]?.data); // This check is necessary for preventing from comparing null values with numeric rules. const shouldOperate = (isNull(rule.value) && OPERATORS_ALLOW_NULL[rule.operator]) || diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/metric/vis.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/metric/vis.js index 8198d22fbe54d6..ceaecad63ff539 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/metric/vis.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/metric/vis.js @@ -12,7 +12,7 @@ import { visWithSplits } from '../../vis_with_splits'; import { createTickFormatter } from '../../lib/tick_formatter'; import { get, isUndefined, assign, includes, pick, gt, gte, lt, lte, isNull } from 'lodash'; import { Metric } from '../../../visualizations/views/metric'; -import { getLastValueOrEmpty } from '../../../../../common/last_value_utils'; +import { getLastValue } from '../../../../../common/last_value_utils'; import { isBackgroundInverted } from '../../../lib/set_is_reversed'; const OPERATORS = { gt, gte, lt, lte, empty: isNull }; const OPERATORS_ALLOW_NULL = { @@ -27,7 +27,7 @@ function getColors(props) { if (model.background_color_rules) { model.background_color_rules.forEach((rule) => { if (rule.operator) { - const value = getLastValueOrEmpty(series[0]?.data); + const value = getLastValue(series[0]?.data); // This check is necessary for preventing from comparing null values with numeric rules. const shouldOperate = (isNull(rule.value) && OPERATORS_ALLOW_NULL[rule.operator]) || diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/top_n/vis.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/top_n/vis.js index 794eebc2237da3..ca0c54610c7d2f 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/top_n/vis.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/top_n/vis.js @@ -9,7 +9,7 @@ import { getCoreStart } from '../../../../services'; import { createTickFormatter } from '../../lib/tick_formatter'; import { TopN } from '../../../visualizations/views/top_n'; -import { getLastValueOrEmpty } from '../../../../../common/last_value_utils'; +import { getLastValue } from '../../../../../common/last_value_utils'; import { isBackgroundInverted } from '../../../lib/set_is_reversed'; import { replaceVars } from '../../lib/replace_vars'; import PropTypes from 'prop-types'; @@ -36,7 +36,7 @@ function sortSeries(visData, model) { }); const direction = item.terms_direction || 'desc'; if (item.terms_order_by === '_key') return acc.concat(itemSeries); - return acc.concat(sortByDirection(itemSeries, direction, (s) => getLastValueOrEmpty(s.data))); + return acc.concat(sortByDirection(itemSeries, direction, (s) => getLastValue(s.data))); }, []); } @@ -52,7 +52,7 @@ function TopNVisualization(props) { seriesConfig.value_template, props.getConfig ); - const value = getLastValueOrEmpty(item.data); + const value = getLastValue(item.data); let color = item.color || seriesConfig.color; if (model.bar_color_rules) { model.bar_color_rules.forEach((rule) => { diff --git a/src/plugins/vis_type_timeseries/public/application/visualizations/views/gauge.js b/src/plugins/vis_type_timeseries/public/application/visualizations/views/gauge.js index 5c6f64fc1b988b..000701c3a0764a 100644 --- a/src/plugins/vis_type_timeseries/public/application/visualizations/views/gauge.js +++ b/src/plugins/vis_type_timeseries/public/application/visualizations/views/gauge.js @@ -11,7 +11,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import classNames from 'classnames'; import { isBackgroundInverted, isBackgroundDark } from '../../lib/set_is_reversed'; -import { getLastValueOrEmpty } from '../../../../common/last_value_utils'; +import { getLastValue } from '../../../../common/last_value_utils'; import { getValueBy } from '../lib/get_value_by'; import { GaugeVis } from './gauge_vis'; import reactcss from 'reactcss'; @@ -61,7 +61,7 @@ export class Gauge extends Component { render() { const { metric, type } = this.props; const { scale, translateX, translateY } = this.state; - const value = getLastValueOrEmpty(metric?.data); + const value = getLastValue(metric?.data); const max = (metric && getValueBy('max', metric.data)) || 1; const formatter = (metric && (metric.tickFormatter || metric.formatter)) || diff --git a/src/plugins/vis_type_timeseries/public/application/visualizations/views/metric.js b/src/plugins/vis_type_timeseries/public/application/visualizations/views/metric.js index 282047a40e4d1b..bc4230d0a15efe 100644 --- a/src/plugins/vis_type_timeseries/public/application/visualizations/views/metric.js +++ b/src/plugins/vis_type_timeseries/public/application/visualizations/views/metric.js @@ -11,7 +11,7 @@ import React, { Component } from 'react'; import _ from 'lodash'; import reactcss from 'reactcss'; -import { getLastValueOrEmpty } from '../../../../common/last_value_utils'; +import { getLastValue } from '../../../../common/last_value_utils'; import { calculateCoordinates } from '../lib/calculate_coordinates'; export class Metric extends Component { @@ -58,7 +58,7 @@ export class Metric extends Component { const { metric, secondary } = this.props; const { scale, translateX, translateY } = this.state; const primaryFormatter = (metric && (metric.tickFormatter || metric.formatter)) || ((n) => n); - const primaryValue = primaryFormatter(getLastValueOrEmpty(metric?.data)); + const primaryValue = primaryFormatter(getLastValue(metric?.data)); const styles = reactcss( { @@ -91,7 +91,7 @@ export class Metric extends Component { let secondarySnippet; if (secondary) { const secondaryFormatter = secondary.formatter || ((n) => n); - const secondaryValue = secondaryFormatter(getLastValueOrEmpty(secondary.data)); + const secondaryValue = secondaryFormatter(getLastValue(secondary.data)); if (secondary.color) styles.secondary_value.color = secondary.color; let secondaryLabel; if (secondary.label) { diff --git a/src/plugins/vis_type_timeseries/public/application/visualizations/views/top_n.js b/src/plugins/vis_type_timeseries/public/application/visualizations/views/top_n.js index 0972cecfd47bf8..0c43ab157fbbba 100644 --- a/src/plugins/vis_type_timeseries/public/application/visualizations/views/top_n.js +++ b/src/plugins/vis_type_timeseries/public/application/visualizations/views/top_n.js @@ -8,7 +8,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import { getLastValueOrEmpty, isEmptyValue } from '../../../../common/last_value_utils'; +import { getLastValue, isEmptyValue } from '../../../../common/last_value_utils'; import { labelDateFormatter } from '../../components/lib/label_date_formatter'; import { emptyLabel } from '../../../../common/empty_label'; import reactcss from 'reactcss'; @@ -96,7 +96,7 @@ export class TopN extends Component { return (item) => { const renderMode = TopN.getRenderMode(min, max); const key = `${item.id || item.label}`; - const lastValue = getLastValueOrEmpty(item.data); + const lastValue = getLastValue(item.data); // if result is empty, all bar need to be colored. const lastValueFormatted = isEmptyValue(lastValue) ? 1 : lastValue; const formatter = item.tickFormatter || this.props.tickFormatter; @@ -151,7 +151,7 @@ export class TopN extends Component { const intervalSettings = this.props.series.reduce( (acc, series, index) => { - const value = getLastValueOrEmpty(series.data) ?? 1; + const value = getLastValue(series.data) ?? 1; return { min: !index || value < acc.min ? value : acc.min, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.js index e9e894326b4e00..88b06d7f7ffaa4 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.js @@ -8,7 +8,7 @@ import { buildProcessorFunction } from '../build_processor_function'; import { processors } from '../response_processors/table'; -import { getLastValueOrEmpty } from '../../../../common/last_value_utils'; +import { getLastValue } from '../../../../common/last_value_utils'; import { first, get } from 'lodash'; import { overwrite } from '../helpers'; import { getActiveSeries } from '../helpers/get_active_series'; @@ -52,7 +52,7 @@ export function processBucket(panel, req, searchStrategy, capabilities, extractF if (!result) return null; const data = get(result, 'data', []); result.slope = trendSinceLastBucket(data); - result.last = getLastValueOrEmpty(data); + result.last = getLastValue(data); return result; }) ); diff --git a/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts b/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts index 679393d2ad09a1..d2405395248234 100644 --- a/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts +++ b/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts @@ -1004,55 +1004,37 @@ const addEmptyValueRuleForSavedObjectsWithLessAndGreaterThenZeroRules: SavedObje gauge_color_rules: gaugeColorRules = [], } = params; - const compareWithEqualMethods = ['lte', 'gte']; - const emptyRule = { - operator: 'empty', - value: null, - }; - - const getRulesWithComparingToZero = (rules: any[] = []) => - last( + const getRuleWithComparingToZero = (rules: any[] = []) => { + const compareWithEqualMethods = ['lte', 'gte']; + return last( rules.filter( (rule) => compareWithEqualMethods.includes(rule.operator) && rule.value === 0 ) ); + }; - const convertRuleToEmpty = ({ id, ...rest }: any = {}) => ({ - ...rest, - ...emptyRule, + const convertRuleToEmpty = (rule: any = {}) => ({ + ...rule, id: uuid.v4(), + operator: 'empty', + value: null, }); - const lastBarRule = getRulesWithComparingToZero(barColorRules) ?? null; - const lastBackgroundRule = getRulesWithComparingToZero(backgroundColorRules) ?? null; - const lastGaugeRule = getRulesWithComparingToZero(gaugeColorRules) ?? null; + const addEmptyRuleToListIfNecessary = (rules: any[]) => { + const rule = getRuleWithComparingToZero(rules); - const colorRules = { - bar_color_rules: barColorRules, - background_color_rules: backgroundColorRules, - gauge_color_rules: gaugeColorRules, - }; - - if (lastBarRule) { - colorRules.bar_color_rules = [ - ...colorRules.bar_color_rules, - convertRuleToEmpty(lastBarRule), - ]; - } + if (rule) { + return [...rules, convertRuleToEmpty(rule)]; + } - if (lastBackgroundRule) { - colorRules.background_color_rules = [ - ...colorRules.background_color_rules, - convertRuleToEmpty(lastBackgroundRule), - ]; - } + return rules; + }; - if (lastGaugeRule) { - colorRules.gauge_color_rules = [ - ...colorRules.gauge_color_rules, - convertRuleToEmpty(lastGaugeRule), - ]; - } + const colorRules = { + bar_color_rules: addEmptyRuleToListIfNecessary(barColorRules), + background_color_rules: addEmptyRuleToListIfNecessary(backgroundColorRules), + gauge_color_rules: addEmptyRuleToListIfNecessary(gaugeColorRules), + }; return { ...doc,