From 3ce8d87b368bed8625f569c0f22ed3457c373dce Mon Sep 17 00:00:00 2001 From: ruchika-narang <79983862+ruchika-narang@users.noreply.github.com> Date: Mon, 26 Sep 2022 22:48:04 +0530 Subject: [PATCH] [BUG]: Revert code for treemap and histogram. (#1037) * Revert code for histogram and treemap after antlr merge because of crashes in app Signed-off-by: ruchika-narang * Fixes after rebasing with main and test cases failing Signed-off-by: ruchika-narang * Removed commented code Signed-off-by: ruchika-narang * Working on review comments, renaming metrics to series Signed-off-by: ruchika-narang * Removing extra import after rebasing main Signed-off-by: ruchika-narang * Working on review comments Signed-off-by: ruchika-narang * Replacing series and dimension with dynamic naming Signed-off-by: ruchika-narang * Updated snapshots Signed-off-by: ruchika-narang * Fixed failing test case issue Signed-off-by: ruchika-narang * Resolving review comment Signed-off-by: ruchika-narang Signed-off-by: ruchika-narang --- .../common/constants/explorer.ts | 20 +-- .../common/constants/shared.ts | 38 ++--- .../common/query_manager/ast/types/stats.ts | 4 +- .../common/query_manager/utils/index.ts | 2 +- .../common/types/explorer.ts | 6 +- .../__snapshots__/utils.test.tsx.snap | 27 ++-- .../event_analytics/explorer/explorer.tsx | 123 ++++++++++----- .../explorer/sidebar/field_insights.tsx | 6 +- .../config_panel/config_panel.tsx | 10 +- .../config_controls/config_color_theme.tsx | 4 +- .../config_line_chart_styles.tsx | 4 +- .../config_panel_option_gauge.tsx | 8 +- .../config_controls/config_panel_options.tsx | 10 +- .../data_config_panel_item.tsx | 149 ++++++++++-------- .../logs_view_config_panel_item.tsx | 28 ++-- .../treemap_config_panel_item.tsx | 99 +++++------- .../explorer/visualizations/index.tsx | 8 +- .../__tests__/__snapshots__/bar.test.tsx.snap | 9 +- .../visualizations/charts/bar/bar.tsx | 30 ++-- .../visualizations/charts/bar/bar_type.ts | 4 +- .../charts/financial/gauge/gauge.tsx | 81 +++++----- .../charts/financial/gauge/gauge_type.ts | 4 +- .../charts/helpers/viz_types.ts | 92 +++++------ .../charts/histogram/histogram.tsx | 40 +++-- .../charts/histogram/histogram_type.ts | 4 +- .../visualizations/charts/lines/line.tsx | 57 ++++--- .../visualizations/charts/lines/line_type.ts | 12 +- .../charts/logs_view/logs_view.tsx | 2 +- .../visualizations/charts/maps/heatmap.tsx | 52 +++--- .../charts/maps/treemap_type.ts | 4 +- .../visualizations/charts/maps/treemaps.tsx | 74 +++++---- .../visualizations/charts/pie/pie.tsx | 66 +++++--- .../visualizations/charts/pie/pie_type.ts | 8 +- .../visualizations/visualization.tsx | 4 +- 34 files changed, 595 insertions(+), 494 deletions(-) diff --git a/dashboards-observability/common/constants/explorer.ts b/dashboards-observability/common/constants/explorer.ts index d801ff9fb..a56bd529d 100644 --- a/dashboards-observability/common/constants/explorer.ts +++ b/dashboards-observability/common/constants/explorer.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { visChartTypes } from './shared'; +import { VIS_CHART_TYPES } from './shared'; export const EVENT_ANALYTICS_DOCUMENTATION_URL = 'https://opensearch.org/docs/latest/observability-plugin/event-analytics/'; export const OPEN_TELEMETRY_LOG_CORRELATION_LINK = @@ -81,11 +81,11 @@ export const DEFAULT_AVAILABILITY_QUERY = 'stats count() by span( timestamp, 1h export const ADD_BUTTON_TEXT = '+ Add color theme'; export const VIZ_CONTAIN_XY_AXIS = [ - visChartTypes.Bar, - visChartTypes.Histogram, - visChartTypes.Line, - visChartTypes.Pie, - visChartTypes.Scatter, + VIS_CHART_TYPES.Bar, + VIS_CHART_TYPES.Histogram, + VIS_CHART_TYPES.Line, + VIS_CHART_TYPES.Pie, + VIS_CHART_TYPES.Scatter, ]; // default ppl aggregation method options @@ -153,7 +153,7 @@ export interface DefaultGaugeChartParametersProps { ThresholdsMaxLimit: number; } -export const DefaultGaugeChartParameters: DefaultGaugeChartParametersProps = { +export const DEFAULT_GAUGE_CHART_PARAMETERS: DefaultGaugeChartParametersProps = { GaugeTitleSize: 14, DisplayDefaultGauges: 1, OrientationDefault: 'h', @@ -166,10 +166,12 @@ export const DefaultGaugeChartParameters: DefaultGaugeChartParametersProps = { export const PLOTLY_PIE_COLUMN_NUMBER = 2; export const PIE_XAXIS_GAP = 0.2; export const PIE_YAXIS_GAP = 0.1; -export interface DefaultPieChartParametersProps { +export interface DefaultPieChartParameterProps { DefaultMode: string; } -export const DefaultPieChartParameters: DefaultPieChartParametersProps = { +export const DEFAULT_PIE_CHART_PARAMETERS: DefaultPieChartParameterProps = { DefaultMode: 'pie', }; +export const GROUPBY = 'dimensions'; +export const AGGREGATIONS = 'series'; diff --git a/dashboards-observability/common/constants/shared.ts b/dashboards-observability/common/constants/shared.ts index e61909789..71f46f706 100644 --- a/dashboards-observability/common/constants/shared.ts +++ b/dashboards-observability/common/constants/shared.ts @@ -2,8 +2,6 @@ * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ - -import { IField } from '../../common/types/explorer'; import CSS from 'csstype'; // Client route @@ -72,7 +70,7 @@ export const pageStyles: CSS.Properties = { maxWidth: '1130px', }; -export enum visChartTypes { +export enum VIS_CHART_TYPES { Bar = 'bar', HorizontalBar = 'horizontal_bar', Line = 'line', @@ -86,30 +84,20 @@ export enum visChartTypes { LogsView = 'logs_view', } -export interface ValueOptionsAxes { - xaxis?: IField[]; - yaxis?: IField[]; - zaxis?: IField[]; - childField?: IField[]; - valueField?: IField[]; - series?: IField[]; - value?: IField[]; -} - export const NUMERICAL_FIELDS = ['short', 'integer', 'long', 'float', 'double']; export const ENABLED_VIS_TYPES = [ - visChartTypes.Bar, - visChartTypes.HorizontalBar, - visChartTypes.Line, - visChartTypes.Pie, - visChartTypes.HeatMap, - visChartTypes.Text, - visChartTypes.TreeMap, - visChartTypes.Gauge, - visChartTypes.Histogram, - visChartTypes.Scatter, - visChartTypes.LogsView, + VIS_CHART_TYPES.Bar, + VIS_CHART_TYPES.HorizontalBar, + VIS_CHART_TYPES.Line, + VIS_CHART_TYPES.Pie, + VIS_CHART_TYPES.HeatMap, + VIS_CHART_TYPES.Text, + VIS_CHART_TYPES.TreeMap, + VIS_CHART_TYPES.Gauge, + VIS_CHART_TYPES.Histogram, + VIS_CHART_TYPES.Scatter, + VIS_CHART_TYPES.LogsView, ]; //Live tail constants @@ -175,7 +163,7 @@ export interface DefaultChartStylesProps { DefaultModeScatter: string; } -export const DefaultChartStyles: DefaultChartStylesProps = { +export const DEFAULT_CHART_STYLES: DefaultChartStylesProps = { DefaultModeLine: 'lines', Interpolation: 'spline', LineWidth: 2, diff --git a/dashboards-observability/common/query_manager/ast/types/stats.ts b/dashboards-observability/common/query_manager/ast/types/stats.ts index 959ae7847..3127c5c6f 100644 --- a/dashboards-observability/common/query_manager/ast/types/stats.ts +++ b/dashboards-observability/common/query_manager/ast/types/stats.ts @@ -53,7 +53,7 @@ export interface ExpressionChunk { value: string | number; } -export interface DataConfigMetric { +export interface DataConfigSeries { alias: string; label: string; name: string; @@ -61,7 +61,7 @@ export interface DataConfigMetric { } export interface AggregationConfigurations { - metrics: Array; + series: Array; dimensions: Array; span: SpanChunk; } diff --git a/dashboards-observability/common/query_manager/utils/index.ts b/dashboards-observability/common/query_manager/utils/index.ts index eded2c827..5d84ed72e 100644 --- a/dashboards-observability/common/query_manager/utils/index.ts +++ b/dashboards-observability/common/query_manager/utils/index.ts @@ -10,7 +10,7 @@ export const composeAggregations = ( staleStats: PreviouslyParsedStaleStats ) => { return { - aggregations: aggConfig.metrics.map((metric) => ({ + aggregations: aggConfig.series.map((metric) => ({ function_alias: metric.alias, function: { name: metric.aggregation, diff --git a/dashboards-observability/common/types/explorer.ts b/dashboards-observability/common/types/explorer.ts index 2c34b30cd..34087e24b 100644 --- a/dashboards-observability/common/types/explorer.ts +++ b/dashboards-observability/common/types/explorer.ts @@ -16,6 +16,8 @@ import { FINAL_QUERY, SELECTED_TIMESTAMP, SELECTED_DATE_RANGE, + GROUPBY, + AGGREGATIONS, } from '../constants/explorer'; import { CoreStart, @@ -294,8 +296,8 @@ export interface DimensionSpan { } export interface ConfigList { - dimensions?: ConfigListEntry[] | HistogramConfigList[]; - metrics?: ConfigListEntry[]; + [GROUPBY]?: ConfigListEntry[] | HistogramConfigList[]; + [AGGREGATIONS]?: ConfigListEntry[]; breakdowns?: ConfigListEntry[] | HistogramConfigList[]; span?: DimensionSpan; } diff --git a/dashboards-observability/public/components/custom_panels/helpers/__tests__/__snapshots__/utils.test.tsx.snap b/dashboards-observability/public/components/custom_panels/helpers/__tests__/__snapshots__/utils.test.tsx.snap index ac6bc701d..81c1b660a 100644 --- a/dashboards-observability/public/components/custom_panels/helpers/__tests__/__snapshots__/utils.test.tsx.snap +++ b/dashboards-observability/public/components/custom_panels/helpers/__tests__/__snapshots__/utils.test.tsx.snap @@ -1420,7 +1420,9 @@ exports[`Utils helper functions renders displayVisualization function 1`] = ` } } > - + - + - + { + const timeUnitValue = TIME_INTERVAL_OPTIONS.find( + (time_unit) => time_unit.value === groupByToken?.span?.span_expression.time_unit + )?.text; + return groupByToken?.span !== null + ? { + time_field: [ + { + name: groupByToken?.span.span_expression.field, + type: 'timestamp', + label: groupByToken?.span.span_expression.field, + }, + ], + unit: [ + { + text: timeUnitValue, + value: groupByToken?.span.span_expression.time_unit, + label: timeUnitValue, + }, + ], + interval: groupByToken?.span.span_expression.literal_value, + } + : undefined; + }; + + const getUpdatedDataConfig = (statsToken: statsChunk) => { + const groupByToken = statsToken.groupby; + const seriesToken = statsToken.aggregations && statsToken.aggregations[0]; + const span = getSpanValue(groupByToken); + switch (curVisId) { + case VIS_CHART_TYPES.TreeMap: + return { + [GROUPBY]: [ + { + childField: { + ...(groupByToken?.group_fields + ? { + label: groupByToken?.group_fields[0].name ?? '', + name: groupByToken?.group_fields[0].name ?? '', + } + : { label: '', name: '' }), + }, + parentFields: [], + }, + ], + [AGGREGATIONS]: [ + { + valueField: { + ...(seriesToken + ? { + label: `${seriesToken.function?.name}(${seriesToken.function?.value_expression})`, + name: `${seriesToken.function?.name}(${seriesToken.function?.value_expression})`, + } + : { label: '', name: '' }), + }, + }, + ], + }; + case VIS_CHART_TYPES.Histogram: + return { + [GROUPBY]: [{ bucketSize: '', bucketOffset: '' }], + [AGGREGATIONS]: [], + }; + default: + return { + [AGGREGATIONS]: statsToken.aggregations.map((agg) => ({ + label: agg.function?.value_expression, + name: agg.function?.value_expression, + aggregation: agg.function?.name, + })), + [GROUPBY]: groupByToken?.group_fields?.map((agg) => ({ + label: agg.name ?? '', + name: agg.name ?? '', + })), + span, + }; + } + }; + const handleQuerySearch = useCallback( async (availability?: boolean) => { // clear previous selected timestamp when index pattern changes @@ -842,49 +925,15 @@ export const Explorer = ({ if (selectedContentTabId === TAB_CHART_ID) { // parse stats section on every search + const qm = new QueryManager(); const statsTokens = qm.queryParser().parse(tempQuery).getStats(); - const timeUnitValue = TIME_INTERVAL_OPTIONS.find( - (time_unit) => time_unit.value === statsTokens.groupby?.span.span_expression.time_unit - )?.text; - const span = - statsTokens.groupby?.span !== null - ? { - time_field: [ - { - name: statsTokens.groupby?.span.span_expression.field, - type: 'timestamp', - label: statsTokens.groupby?.span.span_expression.field, - }, - ], - unit: [ - { - text: timeUnitValue, - value: statsTokens.groupby?.span.span_expression.time_unit, - label: timeUnitValue, - }, - ], - interval: statsTokens.groupby?.span.span_expression.literal_value, - } - : undefined; + const updatedDataConfig = getUpdatedDataConfig(statsTokens); await dispatch( changeVizConfig({ tabId, vizId: curVisId, - data: { - dataConfig: { - metrics: statsTokens.aggregations.map((agg) => ({ - label: agg.function?.value_expression, - name: agg.function?.value_expression, - aggregation: agg.function?.name, - })), - dimensions: statsTokens.groupby?.group_fields?.map((agg) => ({ - label: agg.name ?? '', - name: agg.name ?? '', - })), - span, - }, - }, + data: { ...updatedDataConfig }, }) ); } diff --git a/dashboards-observability/public/components/event_analytics/explorer/sidebar/field_insights.tsx b/dashboards-observability/public/components/event_analytics/explorer/sidebar/field_insights.tsx index 6a682cc5c..b9414ba70 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/sidebar/field_insights.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/sidebar/field_insights.tsx @@ -48,8 +48,8 @@ export const FieldInsights = ({ field, query }: any) => { format: 'viz', }, ]; - const numericalTypes = ['short', 'integer', 'long', 'float', 'double']; - const isNumericalField = indexOf(numericalTypes, field.type) > 0; + const NUMERICAL_TYPES = ['short', 'integer', 'long', 'float', 'double']; + const isNumericalField = indexOf(NUMERICAL_TYPES, field.type) > 0; const [curReport, setCurReport] = useState({ ...generalReports[0] }); const [reportContent, setReportContent] = useState({}); @@ -137,7 +137,7 @@ export const FieldInsights = ({ field, query }: any) => { ); })} - {indexOf(numericalTypes, field.type) > 0 && + {indexOf(NUMERICAL_TYPES, field.type) > 0 && numericalOnlyReports.map((report) => { return ( diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panel.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panel.tsx index eb3142cdf..db15a837d 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panel.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panel.tsx @@ -25,11 +25,7 @@ import { getDefaultSpec } from '../visualization_specs/default_spec'; import { TabContext } from '../../../hooks'; import { DefaultEditorControls } from './config_panel_footer'; import { getVisType } from '../../../../visualizations/charts/vis_types'; -import { - ENABLED_VIS_TYPES, - ValueOptionsAxes, - visChartTypes, -} from '../../../../../../common/constants/shared'; +import { ENABLED_VIS_TYPES, VIS_CHART_TYPES } from '../../../../../../common/constants/shared'; import { VIZ_CONTAIN_XY_AXIS } from '../../../../../../common/constants/explorer'; const CONFIG_LAYOUT_TEMPLATE = ` @@ -108,7 +104,7 @@ export const ConfigPanel = ({ // To check, If user empty any of the value options const isValidValueOptionConfigSelected = useMemo(() => { const valueOptions = vizConfigs.dataConfig?.valueOptions; - const { TreeMap, Gauge, HeatMap } = visChartTypes; + const { TreeMap, Gauge, HeatMap } = VIS_CHART_TYPES; const isValidValueOptionsXYAxes = VIZ_CONTAIN_XY_AXIS.includes(curVisId) && valueOptions?.xaxis?.length !== 0 && @@ -229,7 +225,7 @@ export const ConfigPanel = ({ const memorizedVisualizationTypes = useMemo( () => ENABLED_VIS_TYPES.map((vs: string) => - vs === visChartTypes.Line || vs === visChartTypes.Scatter + vs === VIS_CHART_TYPES.Line || vs === VIS_CHART_TYPES.Scatter ? getVisType(vs, { type: vs }) : getVisType(vs) ), diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_color_theme.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_color_theme.tsx index 07801e5fe..227fefbfa 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_color_theme.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_color_theme.tsx @@ -18,7 +18,7 @@ import { } from '@elastic/eui'; import { isEmpty } from 'lodash'; import { ADD_BUTTON_TEXT } from '../../../../../../../../common/constants/explorer'; -import { visChartTypes } from '../../../../../../../../common/constants/shared'; +import { VIS_CHART_TYPES } from '../../../../../../../../common/constants/shared'; export const ConfigColorTheme = ({ visualizations, @@ -40,7 +40,7 @@ export const ConfigColorTheme = ({ const options = (dataConfig?.valueOptions?.metrics && dataConfig.valueOptions.metrics.length !== 0 ? dataConfig.valueOptions.metrics - : vis.name === visChartTypes.Histogram + : vis.name === VIS_CHART_TYPES.Histogram ? defaultAxes.yaxis ?? [] : fields ).map((item) => ({ diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_line_chart_styles.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_line_chart_styles.tsx index bd36ea856..b753854a1 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_line_chart_styles.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_line_chart_styles.tsx @@ -7,7 +7,7 @@ import React, { useMemo, useCallback, Fragment } from 'react'; import { EuiAccordion, EuiSpacer } from '@elastic/eui'; import { ButtonGroupItem } from './config_button_group'; import { IConfigPanelOptionSection } from '../../../../../../../../common/types/explorer'; -import { visChartTypes } from '../../../../../../../../common/constants/shared'; +import { VIS_CHART_TYPES } from '../../../../../../../../common/constants/shared'; export const ConfigLineChartStyles = ({ visualizations, @@ -54,7 +54,7 @@ export const ConfigLineChartStyles = ({ (schema: IConfigPanelOptionSection) => schema.mapTo !== 'interpolation' ); } - } else if (visualizations?.vis?.name === visChartTypes.Scatter) { + } else if (visualizations?.vis?.name === VIS_CHART_TYPES.Scatter) { return schemas.filter((schema: IConfigPanelOptionSection) => ['style', 'pointSize'].includes(schema.mapTo) ); diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_panel_option_gauge.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_panel_option_gauge.tsx index 519cd2d73..e04a46343 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_panel_option_gauge.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_panel_option_gauge.tsx @@ -5,7 +5,7 @@ import React, { useState, useEffect } from 'react'; import { EuiFormRow, EuiFieldNumber } from '@elastic/eui'; -import { DefaultGaugeChartParameters } from '../../../../../../../../common/constants/explorer'; +import { DEFAULT_GAUGE_CHART_PARAMETERS } from '../../../../../../../../common/constants/explorer'; const helpText = `Limit number of gauges.`; @@ -20,12 +20,12 @@ export const ConfigPanelOptionGauge = ({ ? dataConfig.valueOptions.dimensions.filter((i) => i.name !== '') : []; const [numberOfGauges, setNumberOfGauges] = useState( - DefaultGaugeChartParameters.DisplayDefaultGauges + DEFAULT_GAUGE_CHART_PARAMETERS.DisplayDefaultGauges ); useEffect(() => { if (!vizState) { - setNumberOfGauges(DefaultGaugeChartParameters.DisplayDefaultGauges); + setNumberOfGauges(DEFAULT_GAUGE_CHART_PARAMETERS.DisplayDefaultGauges); } }, [vizState?.numberOfGauges]); @@ -37,7 +37,7 @@ export const ConfigPanelOptionGauge = ({ setNumberOfGauges(Number(e.target.value)); }} value={numberOfGauges} - min={DefaultGaugeChartParameters.DisplayDefaultGauges} + min={DEFAULT_GAUGE_CHART_PARAMETERS.DisplayDefaultGauges} onBlur={() => { const newPanelOptions = { ...panelOptionsValues, diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_panel_options.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_panel_options.tsx index e6db2acb7..6097073af 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_panel_options.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_panel_options.tsx @@ -5,8 +5,8 @@ import React, { useCallback, useState, useEffect } from 'react'; import { EuiFieldText, EuiForm, EuiFormRow, EuiTextArea, EuiAccordion } from '@elastic/eui'; -import { visChartTypes } from '../../../../../../../../common/constants/shared'; -import { DefaultGaugeChartParameters } from '../../../../../../../../common/constants/explorer'; +import { VIS_CHART_TYPES } from '../../../../../../../../common/constants/shared'; +import { DEFAULT_GAUGE_CHART_PARAMETERS } from '../../../../../../../../common/constants/explorer'; import { ConfigPanelOptionGauge } from './config_panel_option_gauge'; const helpText = 'Name your visualization.'; @@ -24,9 +24,9 @@ export const ConfigPanelOptions = ({ visualizations, handleConfigChange, vizStat setPanelOptionsValues({ title: vizState?.title || '', description: vizState?.description || '', - ...(visualizations?.vis?.name?.toLowerCase() === visChartTypes.Gauge && { + ...(visualizations?.vis?.name?.toLowerCase() === VIS_CHART_TYPES.Gauge && { numberOfGauges: - vizState?.numberOfGauges || DefaultGaugeChartParameters.DisplayDefaultGauges, + vizState?.numberOfGauges || DEFAULT_GAUGE_CHART_PARAMETERS.DisplayDefaultGauges, }), }); }, [name, vizState?.title, vizState?.description, vizState?.numberOfGauges]); @@ -62,7 +62,7 @@ export const ConfigPanelOptions = ({ visualizations, handleConfigChange, vizStat onBlur={() => handleConfigChange(panelOptionsValues)} /> - {visualizations?.vis?.name?.toLowerCase() === visChartTypes.Gauge && ( + {visualizations?.vis?.name?.toLowerCase() === VIS_CHART_TYPES.Gauge && ( { const dispatch = useDispatch(); - const { tabId, handleQuerySearch, handleQueryChange, setTempQuery, fetchData } = useContext( - TabContext - ); + const { + tabId, + handleQuerySearch, + handleQueryChange, + setTempQuery, + fetchData, + changeVisualizationConfig, + curVisId, + } = useContext(TabContext); const { data } = visualizations; const { data: vizData = {}, metadata: { fields = [] } = {} } = data?.rawVizData; const { @@ -116,59 +124,77 @@ export const DataConfigPanelItem = ({ ...configList, [name]: [ ...configList[name], - name === 'metrics' ? initialMetricEntry : initialDimensionEntry, + name === AGGREGATIONS ? initialSeriesEntry : initialDimensionEntry, ], }; setConfigList(list); }; - const updateChart = (updatedConfigList = configList) => { - const statsTokens = qm.queryParser().parse(data.query.rawQuery).getStats(); - const newQuery = qm - .queryBuilder() - .build(data.query.rawQuery, composeAggregations(updatedConfigList, statsTokens)); - - batch(async () => { - await handleQueryChange(newQuery); - await dispatch( - changeQuery({ - tabId, - query: { - ...data.query, - [RAW_QUERY]: newQuery, - }, - }) - ); - await fetchData(); - await dispatch( + const updateChart = (updatedConfigList: ConfigList = configList) => { + if (visualizations.vis.name === VIS_CHART_TYPES.Histogram) { + dispatch( changeVizConfig({ tabId, - vizId: visualizations.vis.name, + vizId: curVisId, data: { + ...userConfigs, dataConfig: { - metrics: updatedConfigList.metrics, - dimensions: updatedConfigList.dimensions, - breakdowns: updatedConfigList.breakdowns, - span: updatedConfigList.span, + ...userConfigs.dataConfig, + [GROUPBY]: configList[GROUPBY], + [AGGREGATIONS]: configList[AGGREGATIONS], }, }, }) ); - }); + } else { + const statsTokens = qm.queryParser().parse(data.query.rawQuery).getStats(); + const newQuery = qm + .queryBuilder() + .build(data.query.rawQuery, composeAggregations(updatedConfigList, statsTokens)); + + batch(async () => { + await handleQueryChange(newQuery); + await dispatch( + changeQuery({ + tabId, + query: { + ...data.query, + [RAW_QUERY]: newQuery, + }, + }) + ); + await fetchData(); + await dispatch( + changeVizConfig({ + tabId, + vizId: visualizations.vis.name, + data: { + dataConfig: { + ...userConfigs.dataConfig, + [GROUPBY]: configList[GROUPBY], + [AGGREGATIONS]: configList[AGGREGATIONS], + breakdowns: updatedConfigList.breakdowns, + span: updatedConfigList.span, + }, + }, + }) + ); + }); + } }; const isPositionButtonVisible = (sectionName: string) => - sectionName === 'metrics' && - (visualizations.vis.name === visChartTypes.Line || - visualizations.vis.name === visChartTypes.Scatter); + sectionName === AGGREGATIONS && + (visualizations.vis.name === VIS_CHART_TYPES.Line || + visualizations.vis.name === VIS_CHART_TYPES.Scatter); const getOptionsAvailable = (sectionName: string) => { const selectedFields = {}; const unselectedFields = fieldOptionList.filter((field) => !selectedFields[field.label]); - return sectionName === 'metrics' + return sectionName === AGGREGATIONS ? unselectedFields - : visualizations.vis.name === visChartTypes.Line || - visualizations.vis.name === visChartTypes.Scatter + : visualizations.vis.name === VIS_CHART_TYPES.Line || + visualizations.vis.name === VIS_CHART_TYPES.Scatter ? unselectedFields.filter((i) => i.type === 'timestamp') : unselectedFields; }; @@ -181,18 +207,17 @@ export const DataConfigPanelItem = ({ <>
- {sectionName === 'dimensions' && - visualizations.vis.name === visChartTypes.HeatMap && ( - -
{index === 0 ? 'X-Axis' : 'Y-Axis'}
-
- )} + {sectionName === GROUPBY && visualizations.vis.name === VIS_CHART_TYPES.HeatMap && ( + +
{index === 0 ? 'X-Axis' : 'Y-Axis'}
+
+ )} - {sectionName === 'metrics' && ( + {sectionName === AGGREGATIONS && ( ))} - {visualizations.vis.name !== visChartTypes.HeatMap && ( + {visualizations.vis.name !== VIS_CHART_TYPES.HeatMap && ( handleServiceAdd(sectionName)} disabled={ sectionName === 'dimensions' && - (visualizations.vis.name === visChartTypes.Line || - visualizations.vis.name === visChartTypes.Scatter) + (visualizations.vis.name === VIS_CHART_TYPES.Line || + visualizations.vis.name === VIS_CHART_TYPES.Scatter) } > Add @@ -310,10 +335,8 @@ export const DataConfigPanelItem = ({ fullWidth placeholder="auto" value={ - configList?.dimensions && - configList?.dimensions.length > 0 && - configList.dimensions[0][type] - ? configList.dimensions[0][type] + configList[GROUPBY] && configList[GROUPBY].length > 0 && configList[GROUPBY][0][type] + ? configList[GROUPBY][0][type] : '' } onChange={(e) => updateHistogramConfig('dimensions', type, e.target.value)} @@ -324,10 +347,10 @@ export const DataConfigPanelItem = ({ ); const getBreakDownFields = useCallback( - (configList) => { - return configList.dimensions; + (configList: ConfigList) => { + return configList[GROUPBY]; }, - [configList.dimensions] + [configList[GROUPBY]] ); const Breakdowns = useMemo(() => { @@ -341,7 +364,7 @@ export const DataConfigPanelItem = ({ aria-label="Accessible screen reader label" placeholder="Select fields" singleSelection={false} - options={configList.dimensions} + options={configList[GROUPBY]} selectedOptions={configList.breakdowns ?? []} onChange={(fields) => { setConfigList((staleState) => { @@ -358,7 +381,7 @@ export const DataConfigPanelItem = ({
); - }, [configList.dimensions, configList.breakdowns]); + }, [configList[GROUPBY], configList.breakdowns]); const DateHistogram = useMemo(() => { return ( @@ -448,19 +471,19 @@ export const DataConfigPanelItem = ({

Data Configurations

- {visualizations.vis.name !== visChartTypes.Histogram ? ( + {visualizations.vis.name !== VIS_CHART_TYPES.Histogram ? ( <>

Series

- {getCommonUI(configList.metrics, 'metrics')} + {getCommonUI(configList[AGGREGATIONS], AGGREGATIONS)}

Dimensions

- {getCommonUI(configList.dimensions, 'dimensions')} + {getCommonUI(configList[GROUPBY], GROUPBY)}

Date Histogram

diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/logs_view_config_panel_item.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/logs_view_config_panel_item.tsx index d5ac25e73..696422006 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/logs_view_config_panel_item.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/logs_view_config_panel_item.tsx @@ -14,10 +14,12 @@ import { EuiIcon, EuiText, } from '@elastic/eui'; -import { batch, useDispatch, useSelector } from 'react-redux'; import { cloneDeep } from 'lodash'; +import { batch, useDispatch, useSelector } from 'react-redux'; import { + AGGREGATIONS, AVAILABLE_FIELDS, + GROUPBY, SELECTED_FIELDS, } from '../../../../../../../../common/constants/explorer'; import { @@ -64,8 +66,8 @@ export const LogsViewConfigPanelItem = ({ useEffect(() => { if (fieldOptionList.length === 0) { setConfigList({ - metrics: [], - dimensions: visualizations?.data?.explorer?.explorerFields?.selectedFields.map((field) => ({ + [AGGREGATIONS]: [], + [GROUPBY]: visualizations?.data?.explorer?.explorerFields?.selectedFields.map((field) => ({ ...field, label: field.name, })), @@ -90,11 +92,11 @@ export const LogsViewConfigPanelItem = ({ }; const updateChart = () => { - if ((configList.dimensions as ConfigListEntry[]).some((field) => field.label === '')) { + if ((configList[GROUPBY] as ConfigListEntry[]).some((field) => field.label === '')) { return; } const nextFields = cloneDeep(explorerFields); - const selectedFields = (configList.dimensions as ConfigListEntry[]).map((field) => ({ + const selectedFields = (configList[GROUPBY] as ConfigListEntry[]).map((field) => ({ name: field.name, type: field.type, })); @@ -129,8 +131,8 @@ export const LogsViewConfigPanelItem = ({ dataConfig: { ...userConfigs.dataConfig, valueOptions: { - dimensions: configList.dimensions, - metrics: configList.metrics, + [GROUPBY]: configList[GROUPBY], + [AGGREGATIONS]: configList[AGGREGATIONS], }, }, }, @@ -142,7 +144,7 @@ export const LogsViewConfigPanelItem = ({ if (fieldOptionList.length !== 0) { return []; } - const dimensionNames = (configList.dimensions as ConfigListEntry[]).map((field) => field.name); + const dimensionNames = (configList[GROUPBY] as ConfigListEntry[]).map((field) => field.name); const availableFields = visualizations?.data?.explorer?.explorerFields?.availableFields.filter( (field) => !dimensionNames.includes(field.name) ); @@ -154,19 +156,19 @@ export const LogsViewConfigPanelItem = ({ const updateLogsViewConfig = (value: string, field: ConfigListEntry) => { const list = { ...configList }; - const index = (list.dimensions as ConfigListEntry[]).findIndex( + const index = (list[GROUPBY] as ConfigListEntry[]).findIndex( (dim) => dim.label === field.label ); const selectedField = visualizations?.data?.explorer?.explorerFields?.availableFields.find( (fld) => fld.name === value ); const newField = { ...selectedField, label: value }; - list.dimensions[index] = newField; + list[GROUPBY][index] = newField; setConfigList(list); }; const getLogsViewUI = () => { - const list = configList.dimensions ? configList.dimensions : []; + const list = configList[GROUPBY] ? configList[GROUPBY] : []; const listUI = list.map((field, index) => ( handleServiceRemove(index, 'dimensions')} + onClick={() => handleServiceRemove(index, GROUPBY)} /> } @@ -203,7 +205,7 @@ export const LogsViewConfigPanelItem = ({ fullWidth iconType="plusInCircleFilled" color="primary" - onClick={() => handleServiceAdd('dimensions')} + onClick={() => handleServiceAdd(GROUPBY)} disabled={fieldOptionList.length !== 0} > Add diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/treemap_config_panel_item.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/treemap_config_panel_item.tsx index e8d68a871..b51756450 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/treemap_config_panel_item.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/treemap_config_panel_item.tsx @@ -13,17 +13,14 @@ import { EuiFormRow, EuiPanel, } from '@elastic/eui'; -import { useDispatch, batch } from 'react-redux'; -import { changeQuery } from '../../../../../redux/slices/query_slice'; -import { - change as changeVizConfig, - selectVisualizationConfig, -} from '../../../../../redux/slices/viualization_config_slice'; +import { useDispatch } from 'react-redux'; import { ConfigTreemapParentFields } from './config_treemap_parents'; -import { numericalTypes, RAW_QUERY } from '../../../../../../../../common/constants/explorer'; +import { + AGGREGATIONS, + GROUPBY, + NUMERICAL_TYPES, +} from '../../../../../../../../common/constants/explorer'; import { TabContext } from '../../../../../hooks'; -import { composeAggregations } from '../../../../../../../../common/query_manager/utils'; -import { DataConfigPanelProps } from '../../../../../../../../common/types/explorer'; export const TreemapConfigPanelItem = ({ fieldOptionList, @@ -31,9 +28,7 @@ export const TreemapConfigPanelItem = ({ qm, }: DataConfigPanelProps) => { const dispatch = useDispatch(); - const { tabId, curVisId, changeVisualizationConfig, fetchData, handleQueryChange } = useContext< - any - >(TabContext); + const { tabId, curVisId, changeVisualizationConfig } = useContext(TabContext); const { data } = visualizations; const { userConfigs } = data; @@ -42,8 +37,8 @@ export const TreemapConfigPanelItem = ({ const newEntry = { label: '', name: '' }; const [configList, setConfigList] = useState({ - dimensions: [{ childField: { ...newEntry }, parentFields: [] }], - metrics: [{ valueField: { ...newEntry } }], + [GROUPBY]: [{ childField: { ...newEntry }, parentFields: [] }], + [AGGREGATIONS]: [{ valueField: { ...newEntry } }], }); useEffect(() => { @@ -71,42 +66,26 @@ export const TreemapConfigPanelItem = ({ setConfigList(newList); }; - const updateChart = (updatedConfigList = configList) => { - const statsTokens = qm.queryParser().parse(data.query.rawQuery).getStats(); - const newQuery = qm - .queryBuilder() - .build(data.query.rawQuery, composeAggregations(updatedConfigList, statsTokens)); - - batch(async () => { - await handleQueryChange(newQuery); - await dispatch( - changeQuery({ - tabId, - query: { - ...data.query, - [RAW_QUERY]: newQuery, - }, - }) - ); - await fetchData(); - await dispatch( - changeVizConfig({ - tabId, - vizId: visualizations.vis.name, - data: { - dataConfig: { - metrics: updatedConfigList.metrics, - dimensions: updatedConfigList.dimensions, - }, + const updateChart = () => { + dispatch( + changeVisualizationConfig({ + tabId, + vizId: curVisId, + data: { + ...userConfigs, + dataConfig: { + ...userConfigs.dataConfig, + [GROUPBY]: configList[GROUPBY], + [AGGREGATIONS]: configList[AGGREGATIONS], }, - }) - ); - }); + }, + }) + ); }; const getOptionsAvailable = (sectionName: string) => { - const { dimensions, metrics } = configList; - const selectedFields = {}; + const { dimensions, series } = configList; + let selectedFields = {}; let allSelectedFields = []; for (const key in configList) { @@ -114,9 +93,9 @@ export const TreemapConfigPanelItem = ({ const [dimElements] = dimensions; const { childField, parentFields } = dimElements; allSelectedFields = [childField, ...parentFields]; - } else if (key === 'metrics') { - const [metricsElement] = metrics; - allSelectedFields = [metricsElement.valueField]; + } else if (key === AGGREGATIONS) { + const [seriesElement] = series; + allSelectedFields = [seriesElement.valueField]; } const allValidSelectedFields = allSelectedFields.filter((item) => item?.label); allValidSelectedFields.length > 0 && @@ -124,8 +103,8 @@ export const TreemapConfigPanelItem = ({ } const unselectedFields = fieldOptionList.filter((field) => !selectedFields[field.label]); - return sectionName === 'metrics' - ? unselectedFields.filter((field) => numericalTypes.includes(field.type)) + return sectionName === AGGREGATIONS + ? unselectedFields.filter((field) => NUMERICAL_TYPES.includes(field.type)) : unselectedFields; }; @@ -143,7 +122,7 @@ export const TreemapConfigPanelItem = ({ - updateList('dimensions', 'childField', val.length > 0 ? val[0].label : '') + updateList(GROUPBY, 'childField', val.length > 0 ? val[0].label : '') } /> ({ + dropdownList={getOptionsAvailable(GROUPBY).map((opt) => ({ label: opt.label, name: opt.label, }))} selectedAxis={configList.dimensions[0]?.parentFields} - onSelectChange={(val) => updateList('dimensions', 'parentFields', val)} + onSelectChange={(val) => updateList(GROUPBY, 'parentFields', val)} /> @@ -176,15 +155,15 @@ export const TreemapConfigPanelItem = ({ - updateList('metrics', 'valueField', val.length > 0 ? val[0].label : '') + updateList(AGGREGATIONS, 'valueField', val.length > 0 ? val[0].label : '') } /> @@ -196,7 +175,7 @@ export const TreemapConfigPanelItem = ({ updateChart()} + onClick={updateChart} size="s" > Update chart diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx index 17d817bc3..55018e3c8 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx @@ -22,7 +22,7 @@ import { ConfigPanel } from './config_panel'; import { Sidebar } from '../sidebar'; import { DataConfigPanelItem } from './config_panel/config_panes/config_controls/data_config_panel_item'; import { TabContext } from '../../hooks'; -import { PPL_STATS_REGEX, visChartTypes } from '../../../../../common/constants/shared'; +import { PPL_STATS_REGEX, VIS_CHART_TYPES } from '../../../../../common/constants/shared'; import { TreemapConfigPanelItem } from './config_panel/config_panes/config_controls/treemap_config_panel_item'; import { LogsViewConfigPanelItem } from './config_panel/config_panes/config_controls/logs_view_config_panel_item'; @@ -67,7 +67,7 @@ export const ExplorerVisualizations = ({ const renderDataConfigContainer = () => { switch (curVisId) { - case visChartTypes.TreeMap: + case VIS_CHART_TYPES.TreeMap: return ( ); - case visChartTypes.LogsView: + case VIS_CHART_TYPES.LogsView: return ( handleAddField(field)} handleRemoveField={(field: IField) => handleRemoveField(field)} isFieldToggleButtonDisabled={ - vis.name === visChartTypes.LogsView + vis.name === VIS_CHART_TYPES.LogsView ? isEmpty(explorerData.jsonData) || !isEmpty(query[RAW_QUERY].match(PPL_STATS_REGEX)) : true diff --git a/dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/bar.test.tsx.snap b/dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/bar.test.tsx.snap index b51fac742..b0f5e3c57 100644 --- a/dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/bar.test.tsx.snap +++ b/dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/bar.test.tsx.snap @@ -553,7 +553,9 @@ exports[`Bar component Renders bar component 1`] = ` } } > - + { @@ -34,11 +38,11 @@ export const Bar = ({ visualizations, layout, config }: any) => { if ( isEmpty(queriedVizData) || - !Array.isArray(dataConfig.dimensions) || - !Array.isArray(dataConfig.metrics) || + !Array.isArray(dataConfig[GROUPBY]) || + !Array.isArray(dataConfig[AGGREGATIONS]) || (dataConfig.breakdowns && !Array.isArray(dataConfig.breakdowns)) ) - return ; + return ; /** * determine stylings @@ -58,9 +62,7 @@ export const Bar = ({ visualizations, layout, config }: any) => { dataConfig?.legend?.showLegend && dataConfig.legend.showLegend !== visMetaData.showlegend ); const legendPosition = dataConfig?.legend?.position || visMetaData.legendposition; - visualizations.data?.rawVizData?.dataConfig?.metrics - ? visualizations.data?.rawVizData?.dataConfig?.metrics - : []; + const labelSize = dataConfig?.chartStyles?.labelSize || DEFAULT_LABEL_SIZE; const getSelectedColorTheme = (field: any, index: number) => @@ -78,7 +80,7 @@ export const Bar = ({ visualizations, layout, config }: any) => { // breakdown selections if (dataConfig.breakdowns) { return [ - ...dataConfig.dimensions.filter( + ...dataConfig[GROUPBY].filter( (dimension) => !some(dataConfig.breakdowns, (breakdown) => breakdown.label === dimension.label) ), @@ -88,18 +90,18 @@ export const Bar = ({ visualizations, layout, config }: any) => { // span selection const timestampField = find(fields, (field) => field.type === 'timestamp'); if (dataConfig.span && dataConfig.span.time_field && timestampField) { - return [timestampField, ...dataConfig.dimensions]; + return [timestampField, ...dataConfig[GROUPBY]]; } - return [...dataConfig.dimensions]; - }, [dataConfig.dimensions, dataConfig.breakdowns]); + return [...dataConfig[GROUPBY]]; + }, [dataConfig[GROUPBY], dataConfig.breakdowns]); /** * determine y axis */ const yaxes = useMemo(() => { - return Array.isArray(dataConfig.metrics) ? [...dataConfig.metrics] : []; - }, [dataConfig.metrics]); + return Array.isArray(dataConfig[AGGREGATIONS]) ? [...dataConfig[AGGREGATIONS]] : []; + }, [dataConfig[AGGREGATIONS]]); /** * prepare data for visualization, map x-xais to y-xais diff --git a/dashboards-observability/public/components/visualizations/charts/bar/bar_type.ts b/dashboards-observability/public/components/visualizations/charts/bar/bar_type.ts index 2a0bc0c18..9210850e5 100644 --- a/dashboards-observability/public/components/visualizations/charts/bar/bar_type.ts +++ b/dashboards-observability/public/components/visualizations/charts/bar/bar_type.ts @@ -16,13 +16,13 @@ import { ConfigLegend, InputFieldItem, } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls'; -import { DefaultChartStyles } from '../../../../../common/constants/shared'; +import { DEFAULT_CHART_STYLES } from '../../../../../common/constants/shared'; import { fetchConfigObject } from '../../../../components/event_analytics/utils/utils'; import { ConfigColorTheme } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_color_theme'; const sharedConfigs = getPlotlySharedConfigs(); const VIS_CATEGORY = getPlotlyCategory(); -const { LegendPosition, ShowLegend } = DefaultChartStyles; +const { LegendPosition, ShowLegend } = DEFAULT_CHART_STYLES; export const createBarTypeDefinition = (params: any) => ({ name: 'bar', type: 'bar', diff --git a/dashboards-observability/public/components/visualizations/charts/financial/gauge/gauge.tsx b/dashboards-observability/public/components/visualizations/charts/financial/gauge/gauge.tsx index b9b9f1549..9faad87e1 100644 --- a/dashboards-observability/public/components/visualizations/charts/financial/gauge/gauge.tsx +++ b/dashboards-observability/public/components/visualizations/charts/financial/gauge/gauge.tsx @@ -6,10 +6,15 @@ import React, { useMemo } from 'react'; import Plotly from 'plotly.js-dist'; import { Plt } from '../../../plotly/plot'; -import { PLOTLY_GAUGE_COLUMN_NUMBER } from '../../../../../../common/constants/explorer'; -import { DefaultGaugeChartParameters } from '../../../../../../common/constants/explorer'; +import { + AGGREGATIONS, + GROUPBY, + PLOTLY_GAUGE_COLUMN_NUMBER, +} from '../../../../../../common/constants/explorer'; +import { DEFAULT_GAUGE_CHART_PARAMETERS } from '../../../../../../common/constants/explorer'; import { ThresholdUnitType } from '../../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_thresholds'; import { EmptyPlaceholder } from '../../../../event_analytics/explorer/visualizations/shared_components/empty_placeholder'; +import { IVisualizationContainerProps } from '../../../../../../common/types/explorer'; const { GaugeTitleSize, @@ -17,22 +22,33 @@ const { OrientationDefault, TickLength, LegendPlacement, -} = DefaultGaugeChartParameters; +} = DEFAULT_GAUGE_CHART_PARAMETERS; export const Gauge = ({ visualizations, layout, config }: any) => { const { - data, - metadata: { fields }, - } = visualizations.data.rawVizData; + data: { + defaultAxes, + indexFields, + query, + rawVizData: { + data: queriedVizData, + metadata: { fields }, + }, + userConfigs, + }, + vis: visMetaData, + }: IVisualizationContainerProps = visualizations; // data config parametrs - const { dataConfig = {}, layoutConfig = {} } = visualizations.data.userConfigs; - const dimensions = dataConfig?.dimensions - ? dataConfig.dimensions.filter((item) => item.name !== '') + const { dataConfig = {}, layoutConfig = {} } = userConfigs; + const dimensions = dataConfig[GROUPBY] + ? dataConfig[GROUPBY].filter((item) => item.name !== '') + : []; + const series = dataConfig[AGGREGATIONS] + ? dataConfig[AGGREGATIONS].filter((item) => item.name !== '') : []; - const metrics = dataConfig?.metrics ? dataConfig.metrics.filter((item) => item.name !== '') : []; const dimensionsLength = dimensions.length; - const metricsLength = metrics.length; + const seriesLength = series.length; const numberOfGauges = dataConfig?.panelOptions?.numberOfGauges || DisplayDefaultGauges; // style parameters @@ -44,41 +60,41 @@ export const Gauge = ({ visualizations, layout, config }: any) => { const orientation = dataConfig?.chartStyles?.orientation || OrientationDefault; const legendPlacement = dataConfig?.chartStyles?.legendPlacement || LegendPlacement; - const isEmptyPlot = !metricsLength; + const isEmptyPlot = !seriesLength; - if (isEmptyPlot) return ; + if (isEmptyPlot) return ; const gaugeData: Plotly.Data[] = useMemo(() => { let calculatedGaugeData: Plotly.Data[] = []; - if (dimensionsLength || metricsLength) { + if (dimensionsLength || seriesLength) { // case 1,2: no dimension, single/multiple metrics - if (!dimensionsLength && metricsLength >= 1) { - calculatedGaugeData = metrics.map((metric: any) => { + if (!dimensionsLength && seriesLength >= 1) { + calculatedGaugeData = series.map((seriesItem: any) => { return { - field_name: metric.name, - value: data[metric.name][0], + field_name: seriesItem.name, + value: queriedVizData[seriesItem.name][0], }; }); } // case 3: multiple dimensions and multiple metrics - if (dimensionsLength && metricsLength) { + if (dimensionsLength && seriesLength) { const selectedDimensionsData = dimensions - .map((dimension: any) => data[dimension.name].slice(0, numberOfGauges)) + .map((dimension: any) => queriedVizData[dimension.name].slice(0, numberOfGauges)) .reduce((prev, cur) => { return prev.map((i, j) => `${i}, ${cur[j]}`); }); - const selectedMetricsData = metrics.map((metric: any) => - data[`${metric.aggregation}(${metric.name})`].slice(0, numberOfGauges) + const selectedSeriesData = series.map((seriesItem: any) => + queriedVizData[`${seriesItem.aggregation}(${seriesItem.name})`].slice(0, numberOfGauges) ); - selectedMetricsData.map((metricSlice: any, metricSliceIndex: number) => { + selectedSeriesData.map((seriesSlice: any, seriesSliceIndex: number) => { calculatedGaugeData = [ ...calculatedGaugeData, - ...metricSlice.map((metricSliceData: any, metricSliceDataIndex: number) => { + ...seriesSlice.map((seriesSliceData: any, seriesSliceDataIndex: number) => { return { - field_name: `${selectedDimensionsData[metricSliceDataIndex]}, ${metrics[metricSliceIndex].name}`, - value: metricSliceData, + field_name: `${selectedDimensionsData[seriesSliceDataIndex]}, ${series[seriesSliceIndex].name}`, + value: seriesSliceData, }; }), ]; @@ -140,8 +156,8 @@ export const Gauge = ({ visualizations, layout, config }: any) => { return calculatedGaugeData; }, [ dimensions, - metrics, - data, + series, + queriedVizData, fields, thresholds, showThresholdMarkers, @@ -170,14 +186,7 @@ export const Gauge = ({ visualizations, layout, config }: any) => { ...(layoutConfig.layout && layoutConfig.layout), title: dataConfig?.panelOptions?.title || layoutConfig.layout?.title || '', }; - }, [ - data, - layout, - gaugeData.length, - layoutConfig.layout, - dataConfig?.panelOptions?.title, - orientation, - ]); + }, [layout, gaugeData.length, layoutConfig.layout, dataConfig?.panelOptions?.title, orientation]); const mergedConfigs = { ...config, diff --git a/dashboards-observability/public/components/visualizations/charts/financial/gauge/gauge_type.ts b/dashboards-observability/public/components/visualizations/charts/financial/gauge/gauge_type.ts index 835e75e91..2da38fefd 100644 --- a/dashboards-observability/public/components/visualizations/charts/financial/gauge/gauge_type.ts +++ b/dashboards-observability/public/components/visualizations/charts/financial/gauge/gauge_type.ts @@ -15,11 +15,11 @@ import { ConfigChartOptions, ButtonGroupItem, } from '../../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls'; -import { DefaultGaugeChartParameters } from '../../../../../../common/constants/explorer'; +import { DEFAULT_GAUGE_CHART_PARAMETERS } from '../../../../../../common/constants/explorer'; const sharedConfigs = getPlotlySharedConfigs(); const VIS_CATEGORY = getPlotlyCategory(); -const { ThresholdsMaxLimit } = DefaultGaugeChartParameters; +const { ThresholdsMaxLimit } = DEFAULT_GAUGE_CHART_PARAMETERS; export const createGaugeTypeDefinition = (params: any = {}) => ({ name: 'Gauge', diff --git a/dashboards-observability/public/components/visualizations/charts/helpers/viz_types.ts b/dashboards-observability/public/components/visualizations/charts/helpers/viz_types.ts index e23968693..adc7aeabd 100644 --- a/dashboards-observability/public/components/visualizations/charts/helpers/viz_types.ts +++ b/dashboards-observability/public/components/visualizations/charts/helpers/viz_types.ts @@ -11,9 +11,13 @@ import { IQuery, ExplorerData, } from '../../../../../common/types/explorer'; -import { visChartTypes } from '../../../../../common/constants/shared'; +import { VIS_CHART_TYPES } from '../../../../../common/constants/shared'; import { QueryManager } from '../../../../../common/query_manager'; -import { TIME_INTERVAL_OPTIONS } from '../../../../../common/constants/explorer'; +import { + AGGREGATIONS, + GROUPBY, + TIME_INTERVAL_OPTIONS, +} from '../../../../../common/constants/explorer'; interface IVizContainerProps { vizId: string; appData?: { fromApp: boolean }; @@ -33,7 +37,7 @@ const initialDimensionEntry = { name: '', }; -const initialMetricEntry = { +const initialSeriesEntry = { alias: '', label: '', name: '', @@ -51,15 +55,15 @@ const getDefaultXYAxisLabels = (vizFields: IField[], visName: string) => { const mapXaxis = (): Array<{ [key: string]: string }> => { const xaxis = vizFieldsWithLabel.filter((field) => field.type === 'timestamp'); - return visName === visChartTypes.Line + return visName === VIS_CHART_TYPES.Line ? xaxis.length === 0 ? [initialDimensionEntry] : xaxis : [vizFieldsWithLabel[vizFieldsWithLabel.length - 1]]; }; - const mapYaxis = (): Array<{ [key: string]: string }> => - visName === visChartTypes.Line + const mapYaxis = (): { [key: string]: string }[] => + visName === VIS_CHART_TYPES.Line ? vizFieldsWithLabel.filter((field) => field.type !== 'timestamp') : take( vizFieldsWithLabel, @@ -81,8 +85,8 @@ const defaultUserConfigs = (queryString, visualizationName: string) => { const statsTokens = qm.queryParser().parse(queryString.rawQuery).getStats(); if (!statsTokens) { tempUserConfigs = { - metrics: [], - dimensions: [], + [AGGREGATIONS]: [], + [GROUPBY]: [], }; } else { const fieldInfo = statsTokens.groupby?.span?.span_expression?.field; @@ -104,11 +108,11 @@ const defaultUserConfigs = (queryString, visualizationName: string) => { : [], }, }; - if (visualizationName === visChartTypes.LogsView) { + if (visualizationName === VIS_CHART_TYPES.LogsView) { tempUserConfigs = { ...tempUserConfigs, - metrics: [], - dimensions: statsTokens.aggregations + [AGGREGATIONS]: [], + [GROUPBY]: statsTokens.aggregations .map((agg) => ({ label: agg.name ?? '', name: agg.name ?? '', @@ -120,50 +124,22 @@ const defaultUserConfigs = (queryString, visualizationName: string) => { })) ), }; - } else if (visualizationName === visChartTypes.HeatMap) { + } else if (visualizationName === VIS_CHART_TYPES.HeatMap) { tempUserConfigs = { ...tempUserConfigs, - dimensions: [initialDimensionEntry, initialDimensionEntry], - metrics: [initialMetricEntry], - }; - } else if (visualizationName === visChartTypes.TreeMap) { - tempUserConfigs = { - dimensions: [ - { - childField: { - ...(statsTokens.groupby?.group_fields.length > 0 - ? { - label: statsTokens.groupby?.group_fields[0].name, - name: statsTokens.groupby?.group_fields[0].name, - } - : initialEntryTreemap), - }, - parentFields: [], - }, - ], - metrics: [ - { - valueField: { - ...(statsTokens.aggregations.length > 0 - ? { - label: statsTokens.aggregations[0].function?.value_expression, - name: statsTokens.aggregations[0].function?.value_expression, - } - : initialEntryTreemap), - }, - }, - ], + [GROUPBY]: [initialDimensionEntry, initialDimensionEntry], + [AGGREGATIONS]: [initialSeriesEntry], }; } else { tempUserConfigs = { ...tempUserConfigs, - metrics: statsTokens.aggregations.map((agg) => ({ + [AGGREGATIONS]: statsTokens.aggregations.map((agg) => ({ alias: agg.alias, label: agg.function?.value_expression, name: agg.function?.value_expression, aggregation: agg.function?.name, })), - dimensions: statsTokens.groupby?.group_fields?.map((agg) => ({ + [GROUPBY]: statsTokens.groupby?.group_fields?.map((agg) => ({ label: agg.name ?? '', name: agg.name ?? '', })), @@ -181,9 +157,9 @@ const getUserConfigs = ( ) => { let configOfUser = userSelectedConfigs; const axesData = getDefaultXYAxisLabels(vizFields, visName); - if (!(userSelectedConfigs.dataConfig?.dimensions || userSelectedConfigs.dataConfig?.metrics)) { + if (!(userSelectedConfigs.dataConfig?.GROUPBY || userSelectedConfigs.dataConfig?.AGGREGATIONS)) { switch (visName) { - case visChartTypes.HeatMap: + case VIS_CHART_TYPES.HeatMap: configOfUser = { ...userSelectedConfigs, dataConfig: { @@ -192,28 +168,34 @@ const getUserConfigs = ( }, }; break; - case visChartTypes.TreeMap: + case VIS_CHART_TYPES.TreeMap: configOfUser = { ...userSelectedConfigs, dataConfig: { ...userSelectedConfigs?.dataConfig, - ...defaultUserConfigs(query, visName), + [GROUPBY]: [ + { + childField: { ...(axesData.xaxis ? axesData.xaxis[0] : initialEntryTreemap) }, + parentFields: [], + }, + ], + [AGGREGATIONS]: [ + { valueField: { ...(axesData.yaxis ? axesData.yaxis[0] : initialEntryTreemap) } }, + ], }, }; break; - case visChartTypes.Histogram: + case VIS_CHART_TYPES.Histogram: configOfUser = { ...userSelectedConfigs, dataConfig: { ...userSelectedConfigs?.dataConfig, - valueOptions: { - dimensions: [{ bucketSize: '', bucketOffset: '' }], - metrics: [], - }, + [GROUPBY]: [{ bucketSize: '', bucketOffset: '' }], + [AGGREGATIONS]: [], }, }; break; - case visChartTypes.LogsView: + case VIS_CHART_TYPES.LogsView: configOfUser = { ...userSelectedConfigs, dataConfig: { @@ -246,7 +228,7 @@ export const getVizContainerProps = ({ explorer = { explorerData: { jsonData: [], jsonDataAll: [] } }, }: IVizContainerProps): IVisualizationContainerProps => { const getVisTypeData = () => - vizId === visChartTypes.Line || vizId === visChartTypes.Scatter + vizId === VIS_CHART_TYPES.Line || vizId === VIS_CHART_TYPES.Scatter ? { ...getVisType(vizId, { type: vizId }) } : { ...getVisType(vizId) }; diff --git a/dashboards-observability/public/components/visualizations/charts/histogram/histogram.tsx b/dashboards-observability/public/components/visualizations/charts/histogram/histogram.tsx index 08a1930ee..52af6fb9a 100644 --- a/dashboards-observability/public/components/visualizations/charts/histogram/histogram.tsx +++ b/dashboards-observability/public/components/visualizations/charts/histogram/histogram.tsx @@ -7,21 +7,31 @@ import React, { useMemo } from 'react'; import { take, isEmpty, last } from 'lodash'; import { Plt } from '../../plotly/plot'; import { - DefaultChartStyles, + DEFAULT_CHART_STYLES, PLOTLY_COLOR, FILLOPACITY_DIV_FACTOR, - visChartTypes, + VIS_CHART_TYPES, } from '../../../../../common/constants/shared'; +import { IVisualizationContainerProps } from '../../../../../common/types/explorer'; import { hexToRgb } from '../../../../components/event_analytics/utils/utils'; +import { GROUPBY } from '../../../../../common/constants/explorer'; export const Histogram = ({ visualizations, layout, config }: any) => { - const { LineWidth, FillOpacity, LegendPosition, ShowLegend } = DefaultChartStyles; + const { LineWidth, FillOpacity, LegendPosition, ShowLegend } = DEFAULT_CHART_STYLES; const { - data = {}, - metadata: { fields }, - } = visualizations.data.rawVizData; - const { defaultAxes } = visualizations?.data; - const { dataConfig = {}, layoutConfig = {} } = visualizations?.data?.userConfigs; + data: { + defaultAxes, + indexFields, + query, + rawVizData: { + data: queriedVizData, + metadata: { fields }, + }, + userConfigs, + }, + vis: visMetaData, + }: IVisualizationContainerProps = visualizations; + const { dataConfig = {}, layoutConfig = {} } = userConfigs; const lastIndex = fields.length - 1; const lineWidth = dataConfig?.chartStyles?.lineWidth || LineWidth; const showLegend = @@ -40,11 +50,11 @@ export const Histogram = ({ visualizations, layout, config }: any) => { const valueSeries = defaultAxes?.yaxis || take(fields, lastIndex > 0 ? lastIndex : 1); const xbins: any = {}; - if (dataConfig?.valueOptions?.dimensions[0].bucketSize) { - xbins.size = dataConfig.valueOptions.dimensions[0].bucketSize; + if (dataConfig[GROUPBY] && dataConfig[GROUPBY][0].bucketSize) { + xbins.size = dataConfig[GROUPBY][0].bucketSize; } - if (dataConfig?.valueOptions?.dimensions[0].bucketOffset) { - xbins.start = dataConfig.valueOptions.dimensions[0].bucketOffset; + if (dataConfig[GROUPBY] && dataConfig[GROUPBY][0].bucketOffset) { + xbins.start = dataConfig[GROUPBY][0].bucketOffset; } const selectedColorTheme = (field: any, index: number, opacity?: number) => { @@ -60,8 +70,8 @@ export const Histogram = ({ visualizations, layout, config }: any) => { const hisValues = useMemo( () => valueSeries.map((field: any, index: number) => ({ - x: data[field.name], - type: visChartTypes.Histogram, + x: queriedVizData[field.name], + type: VIS_CHART_TYPES.Histogram, name: field.name, hoverinfo: tooltipMode === 'hidden' ? 'none' : tooltipText, marker: { @@ -73,7 +83,7 @@ export const Histogram = ({ visualizations, layout, config }: any) => { }, xbins: !isEmpty(xbins) ? xbins : undefined, })), - [valueSeries, data, fillOpacity, lineWidth, xbins, selectedColorTheme] + [valueSeries, queriedVizData, fillOpacity, lineWidth, xbins, selectedColorTheme] ); const mergedLayout = { diff --git a/dashboards-observability/public/components/visualizations/charts/histogram/histogram_type.ts b/dashboards-observability/public/components/visualizations/charts/histogram/histogram_type.ts index de9dcf0bc..f87b4920f 100644 --- a/dashboards-observability/public/components/visualizations/charts/histogram/histogram_type.ts +++ b/dashboards-observability/public/components/visualizations/charts/histogram/histogram_type.ts @@ -13,12 +13,12 @@ import { SliderConfig, ConfigColorTheme, } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls'; -import { DefaultChartStyles } from '../../../../../common/constants/shared'; +import { DEFAULT_CHART_STYLES } from '../../../../../common/constants/shared'; import { fetchConfigObject } from '../../../../components/event_analytics/utils/utils'; const sharedConfigs = getPlotlySharedConfigs(); const VIS_CATEGORY = getPlotlyCategory(); -const { LineWidth, FillOpacity, ShowLegend, LegendPosition } = DefaultChartStyles; +const { LineWidth, FillOpacity, ShowLegend, LegendPosition } = DEFAULT_CHART_STYLES; export const createHistogramVisDefinition = (params = {}) => ({ name: 'histogram', diff --git a/dashboards-observability/public/components/visualizations/charts/lines/line.tsx b/dashboards-observability/public/components/visualizations/charts/lines/line.tsx index 7234d4430..b93bd6757 100644 --- a/dashboards-observability/public/components/visualizations/charts/lines/line.tsx +++ b/dashboards-observability/public/components/visualizations/charts/lines/line.tsx @@ -9,13 +9,15 @@ import { Plt } from '../../plotly/plot'; import { AvailabilityUnitType } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_availability'; import { ThresholdUnitType } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_thresholds'; import { - DefaultChartStyles, + DEFAULT_CHART_STYLES, FILLOPACITY_DIV_FACTOR, PLOTLY_COLOR, - visChartTypes, + VIS_CHART_TYPES, } from '../../../../../common/constants/shared'; import { hexToRgb } from '../../../../components/event_analytics/utils/utils'; import { EmptyPlaceholder } from '../../../event_analytics/explorer/visualizations/shared_components/empty_placeholder'; +import { IVisualizationContainerProps } from '../../../../../common/types/explorer'; +import { AGGREGATIONS, GROUPBY } from '../../../../../common/constants/explorer'; export const Line = ({ visualizations, layout, config }: any) => { const { @@ -28,20 +30,23 @@ export const Line = ({ visualizations, layout, config }: any) => { ShowLegend, DefaultModeScatter, LabelAngle, - } = DefaultChartStyles; + } = DEFAULT_CHART_STYLES; const { - data = {}, - metadata: { fields }, - } = visualizations.data.rawVizData; - const { defaultAxes } = visualizations.data; - const { - dataConfig = {}, - layoutConfig = {}, - availabilityConfig = {}, - } = visualizations?.data?.userConfigs; + data: { + defaultAxes, + indexFields, + query, + rawVizData: { + data: queriedVizData, + metadata: { fields }, + }, + userConfigs, + }, + vis: visMetaData, + }: IVisualizationContainerProps = visualizations; + const { dataConfig = {}, layoutConfig = {}, availabilityConfig = {} } = userConfigs; - // const xaxis = dataConfig?.dimensions ? dataConfig.dimensions.filter((item) => item.label) : []; - const yaxis = dataConfig?.metrics ? dataConfig.metrics.filter((item) => item.label) : []; + const yaxis = dataConfig[AGGREGATIONS] ? dataConfig[AGGREGATIONS].filter((item) => item.label) : []; const tooltipMode = dataConfig?.tooltipOptions?.tooltipMode !== undefined ? dataConfig.tooltipOptions.tooltipMode @@ -53,10 +58,10 @@ export const Line = ({ visualizations, layout, config }: any) => { const lastIndex = fields.length - 1; - const visType: string = visualizations.vis.name; + const visType: string = visMetaData?.name; const mode = dataConfig?.chartStyles?.style || - (visType === visChartTypes.Line ? DefaultModeLine : DefaultModeScatter); + (visType === VIS_CHART_TYPES.Line ? DefaultModeLine : DefaultModeScatter); const lineShape = dataConfig?.chartStyles?.interpolation || Interpolation; const lineWidth = dataConfig?.chartStyles?.lineWidth || LineWidth; const showLegend = !( @@ -81,13 +86,13 @@ export const Line = ({ visualizations, layout, config }: any) => { const timestampField = find(fields, (field) => field.type === 'timestamp'); if (dataConfig.span && dataConfig.span.time_field && timestampField) { - xaxis = [timestampField, ...dataConfig.dimensions]; + xaxis = [timestampField, ...dataConfig[GROUPBY]]; } else { - xaxis = dataConfig.dimensions; + xaxis = dataConfig[GROUPBY]; } if (isEmpty(xaxis) || isEmpty(yaxis)) - return ; + return ; let valueSeries; if (!isEmpty(xaxis) && !isEmpty(yaxis)) { @@ -138,8 +143,8 @@ export const Line = ({ visualizations, layout, config }: any) => { }; return { - x: data[!isEmpty(xaxis) ? xaxis[0]?.label : fields[lastIndex].name], - y: data[`${field.aggregation}(${field.name})`], + x: queriedVizData[!isEmpty(xaxis) ? xaxis[0]?.label : fields[lastIndex].name], + y: queriedVizData[`${field.aggregation}(${field.name})`], type: isBarMode ? 'bar' : 'scatter', name: field.label, mode, @@ -201,15 +206,15 @@ export const Line = ({ visualizations, layout, config }: any) => { const mapToLine = (list: ThresholdUnitType[] | AvailabilityUnitType[], lineStyle: any) => { return list.map((thr: ThresholdUnitType) => { thresholdTraces.x.push( - data[!isEmpty(xaxis) ? xaxis[xaxis.length - 1]?.label : fields[lastIndex].name][0] + queriedVizData[!isEmpty(xaxis) ? xaxis[xaxis.length - 1]?.label : fields[lastIndex].name][0] ); thresholdTraces.y.push(thr.value * (1 + 0.06)); thresholdTraces.text.push(thr.name); return { type: 'line', - x0: data[!isEmpty(xaxis) ? xaxis[0]?.label : fields[lastIndex].name][0], + x0: queriedVizData[!isEmpty(xaxis) ? xaxis[0]?.label : fields[lastIndex].name][0], y0: thr.value, - x1: last(data[!isEmpty(xaxis) ? xaxis[0]?.label : fields[lastIndex].name]), + x1: last(queriedVizData[!isEmpty(xaxis) ? xaxis[0]?.label : fields[lastIndex].name]), y1: thr.value, name: thr.name || '', opacity: 0.7, @@ -229,7 +234,7 @@ export const Line = ({ visualizations, layout, config }: any) => { calculatedLineValues = [...calculatedLineValues, thresholdTraces]; } return [mergedLayout, calculatedLineValues]; - }, [data, fields, lastIndex, layout, layoutConfig, xaxis, yaxis, mode, valueSeries]); + }, [queriedVizData, fields, lastIndex, layout, layoutConfig, xaxis, yaxis, mode, valueSeries]); const mergedConfigs = useMemo( () => ({ @@ -242,6 +247,6 @@ export const Line = ({ visualizations, layout, config }: any) => { return isDimensionTimestamp ? ( ) : ( - + ); }; diff --git a/dashboards-observability/public/components/visualizations/charts/lines/line_type.ts b/dashboards-observability/public/components/visualizations/charts/lines/line_type.ts index 4956075d6..cdcb0fd07 100644 --- a/dashboards-observability/public/components/visualizations/charts/lines/line_type.ts +++ b/dashboards-observability/public/components/visualizations/charts/lines/line_type.ts @@ -17,8 +17,8 @@ import { } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls'; import { ConfigAvailability } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_availability'; import { - DefaultChartStyles, - visChartTypes, + DEFAULT_CHART_STYLES, + VIS_CHART_TYPES, PLOTLY_COLOR, } from '../../../../../common/constants/shared'; import { ButtonGroupItem } from '../../../../../public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group'; @@ -36,14 +36,14 @@ const { LegendPosition, ShowLegend, LabelAngle, -} = DefaultChartStyles; +} = DEFAULT_CHART_STYLES; export const createLineTypeDefinition = (params: any = {}) => ({ name: params.type, type: params.type, id: params.type, - label: params.type === visChartTypes.Line ? 'Time series' : 'Scatter', - fulllabel: params.type === visChartTypes.Line ? 'Time series' : 'Scatter', + label: params.type === VIS_CHART_TYPES.Line ? 'Time series' : 'Scatter', + fulllabel: params.type === VIS_CHART_TYPES.Line ? 'Time series' : 'Scatter', icontype: 'visLine', category: VIS_CATEGORY.BASICS, selection: { @@ -125,7 +125,7 @@ export const createLineTypeDefinition = (params: any = {}) => ({ { name: 'Lines + Markers', id: 'lines+markers' }, ], defaultSelections: [ - params.type === visChartTypes.Line + params.type === VIS_CHART_TYPES.Line ? { name: 'Lines', id: DefaultModeLine } : { name: 'Marker', id: DefaultModeScatter }, ], diff --git a/dashboards-observability/public/components/visualizations/charts/logs_view/logs_view.tsx b/dashboards-observability/public/components/visualizations/charts/logs_view/logs_view.tsx index 13a6516b4..0e8e88f4c 100644 --- a/dashboards-observability/public/components/visualizations/charts/logs_view/logs_view.tsx +++ b/dashboards-observability/public/components/visualizations/charts/logs_view/logs_view.tsx @@ -2,8 +2,8 @@ * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ -import { IExplorerFields } from '../../../../../common/types/explorer'; import React from 'react'; +import { IExplorerFields } from '../../../../../common/types/explorer'; import { RAW_QUERY, SELECTED_TIMESTAMP } from '../../../../../common/constants/explorer'; import { DataGrid } from '../../../../components/event_analytics/explorer/events_views/data_grid'; import './logs_view.scss'; diff --git a/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx b/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx index 221ff5556..7b06b2bdc 100644 --- a/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx +++ b/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx @@ -16,35 +16,45 @@ import { HEATMAP_SINGLE_COLOR, } from '../../../../../common/constants/colors'; import { hexToRgb, lightenColor } from '../../../../components/event_analytics/utils/utils'; -import { NUMERICAL_FIELDS } from '../../../../../common/constants/shared'; +import { IVisualizationContainerProps } from '../../../../../common/types/explorer'; +import { AGGREGATIONS, GROUPBY } from '../../../../../common/constants/explorer'; export const HeatMap = ({ visualizations, layout, config }: any) => { const { - data, - metadata: { fields }, - } = visualizations.data.rawVizData; - const { dataConfig = {}, layoutConfig = {} } = visualizations?.data?.userConfigs; + data: { + defaultAxes, + indexFields, + query, + rawVizData: { + data: queriedVizData, + metadata: { fields }, + }, + userConfigs, + }, + vis: visMetaData, + }: IVisualizationContainerProps = visualizations; + const { dataConfig = {}, layoutConfig = {} } = userConfigs; - if (fields.length < 3) return ; + if (fields.length < 3) return ; - const xaxisField = dataConfig?.dimensions[0]; - const yaxisField = dataConfig?.dimensions[1]; - const zMetrics = dataConfig?.metrics[0]; + const xaxisField = dataConfig[GROUPBY][0]; + const yaxisField = dataConfig[GROUPBY][1]; + const zMetrics = dataConfig[AGGREGATIONS][0]; if ( isEmpty(xaxisField) || isEmpty(yaxisField) || isEmpty(zMetrics) || - isEmpty(data[xaxisField.label]) || - isEmpty(data[yaxisField.label]) || - isEmpty(data[`${zMetrics.aggregation}(${zMetrics.name})`]) || - dataConfig?.dimensions.length > 2 || - dataConfig?.metrics.length > 1 + isEmpty(queriedVizData[xaxisField.label]) || + isEmpty(queriedVizData[yaxisField.label]) || + isEmpty(queriedVizData[`${zMetrics.aggregation}(${zMetrics.name})`]) || + dataConfig[GROUPBY].length > 2 || + dataConfig[AGGREGATIONS].length > 1 ) - return ; + return ; - const uniqueYaxis = uniq(data[yaxisField.label]); - const uniqueXaxis = uniq(data[xaxisField.label]); + const uniqueYaxis = uniq(queriedVizData[yaxisField.label]); + const uniqueXaxis = uniq(queriedVizData[xaxisField.label]); const uniqueYaxisLength = uniqueYaxis.length; const uniqueXaxisLength = uniqueXaxis.length; const tooltipMode = @@ -79,9 +89,9 @@ export const HeatMap = ({ visualizations, layout, config }: any) => { const buckets = {}; // maps bukcets to metrics - for (let i = 0; i < data[xaxisField.label].length; i++) { - buckets[`${data[xaxisField.label][i]},${data[yaxisField.label][i]}`] = - data[`${zMetrics.aggregation}(${zMetrics.name})`][i]; + for (let i = 0; i < queriedVizData[xaxisField.label].length; i++) { + buckets[`${queriedVizData[xaxisField.label][i]},${queriedVizData[yaxisField.label][i]}`] = + queriedVizData[`${zMetrics.aggregation}(${zMetrics.name})`][i]; } // initialize empty 2 dimensional array, inner loop for each xaxis field, outer loop for yaxis @@ -104,7 +114,7 @@ export const HeatMap = ({ visualizations, layout, config }: any) => { return heapMapZaxis; }, [ - data, + queriedVizData, uniqueYaxis, uniqueXaxis, uniqueYaxisLength, diff --git a/dashboards-observability/public/components/visualizations/charts/maps/treemap_type.ts b/dashboards-observability/public/components/visualizations/charts/maps/treemap_type.ts index 338d39c9c..1a87a428b 100644 --- a/dashboards-observability/public/components/visualizations/charts/maps/treemap_type.ts +++ b/dashboards-observability/public/components/visualizations/charts/maps/treemap_type.ts @@ -16,13 +16,13 @@ import { } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls'; import { DEFAULT_PALETTE, COLOR_PALETTES } from '../../../../../common/constants/colors'; import { ButtonGroupItem } from '../../../../../public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group'; -import { DefaultChartStyles } from '../../../../../common/constants/shared'; +import { DEFAULT_CHART_STYLES } from '../../../../../common/constants/shared'; import { fetchConfigObject } from '../../../../components/event_analytics/utils/utils'; const sharedConfigs = getPlotlySharedConfigs(); const VIS_CATEGORY = getPlotlyCategory(); -const { SortSectors } = DefaultChartStyles; +const { SortSectors } = DEFAULT_CHART_STYLES; export interface BarTypeParams {} diff --git a/dashboards-observability/public/components/visualizations/charts/maps/treemaps.tsx b/dashboards-observability/public/components/visualizations/charts/maps/treemaps.tsx index 47e160bc1..e9e7dd5d7 100644 --- a/dashboards-observability/public/components/visualizations/charts/maps/treemaps.tsx +++ b/dashboards-observability/public/components/visualizations/charts/maps/treemaps.tsx @@ -14,25 +14,35 @@ import { MULTI_COLOR_PALETTE, SINGLE_COLOR_PALETTE, } from '../../../../../common/constants/colors'; -import { DefaultChartStyles } from '../../../../../common/constants/shared'; +import { DEFAULT_CHART_STYLES } from '../../../../../common/constants/shared'; +import { IVisualizationContainerProps } from '../../../../../common/types/explorer'; +import { GROUPBY, AGGREGATIONS } from '../../../../../common/constants/explorer'; export const TreeMap = ({ visualizations, layout, config }: any) => { - const { DefaultSortSectors } = DefaultChartStyles; - + const { DefaultSortSectors } = DEFAULT_CHART_STYLES; const { - data, - metadata: { fields }, - } = visualizations.data.rawVizData; - const { dataConfig = {}, layoutConfig = {} } = visualizations?.data?.userConfigs; + data: { + defaultAxes, + indexFields, + query, + rawVizData: { + data: queriedVizData, + metadata: { fields }, + }, + userConfigs, + }, + vis: visMetaData, + }: IVisualizationContainerProps = visualizations; + const { dataConfig = {}, layoutConfig = {} } = userConfigs; const childField = - dataConfig?.valueOptions?.dimensions && dataConfig.valueOptions.dimensions[0].childField - ? dataConfig.valueOptions.dimensions[0].childField + dataConfig[GROUPBY] && dataConfig[GROUPBY][0].childField + ? dataConfig[GROUPBY][0].childField : fields[fields.length - 1]; const parentFields = - dataConfig?.valueOptions?.dimensions && dataConfig.valueOptions.dimensions[0].parentFields - ? dataConfig.valueOptions.dimensions[0].parentFields + dataConfig[GROUPBY] && dataConfig[GROUPBY][0].parentFields + ? dataConfig[GROUPBY][0].parentFields : []; const tooltipMode = dataConfig?.tooltipOptions?.tooltipMode !== undefined @@ -44,8 +54,8 @@ export const TreeMap = ({ visualizations, layout, config }: any) => { : 'all'; const valueField = - dataConfig?.valueOptions?.metrics && dataConfig.valueOptions.metrics[0].valueField - ? dataConfig.valueOptions.metrics[0].valueField + dataConfig[AGGREGATIONS] && dataConfig[AGGREGATIONS][0].valueField + ? dataConfig[AGGREGATIONS][0].valueField : fields[0]; const colorField = @@ -65,15 +75,16 @@ export const TreeMap = ({ visualizations, layout, config }: any) => { const areParentFieldsInvalid = new Set([...parentFields.map((field) => field.name)]).size !== parentFields.length || - parentFields.some((field) => isEmpty(data[field.name]) || isEqual(childField.name, field.name)); + parentFields.some( + (field) => isEmpty(queriedVizData[field.name]) || isEqual(childField.name, field.name) + ); if ( - isEmpty(data[childField.name]) || - isEmpty(data[valueField.name]) || - indexOf(NUMERICAL_FIELDS, valueField.type) < 0 || + isEmpty(queriedVizData[childField.name]) || + isEmpty(queriedVizData[valueField.name]) || areParentFieldsInvalid ) - return ; + return ; const [treemapData, mergedLayout] = useMemo(() => { let labelsArray: string[] = [], @@ -82,11 +93,13 @@ export const TreeMap = ({ visualizations, layout, config }: any) => { colorsArray: string[] = []; if (parentFields.length === 0) { - labelsArray = [...data[childField.name]]; + labelsArray = [...queriedVizData[childField.name]]; parentsArray = [...Array(labelsArray.length).fill('')]; - valuesArray = [...data[valueField.name]]; + valuesArray = [...queriedVizData[valueField.name]]; if (colorField.name === MULTI_COLOR_PALETTE) { - colorsArray = [...Array(data[childField.name].length).fill(colorField.childColor)]; + colorsArray = [ + ...Array(queriedVizData[childField.name].length).fill(colorField.childColor), + ]; } } else { let currentLevel = parentFields.length - 1; @@ -95,7 +108,7 @@ export const TreeMap = ({ visualizations, layout, config }: any) => { .slice(0) .reverse() .map((field, i) => { - const uniqueParents = uniq(data[field.name]) as string[]; + const uniqueParents = uniq(queriedVizData[field.name]) as string[]; labelsArray = [...labelsArray, ...uniqueParents]; if (i === 0) { parentsArray = [...Array(uniqueParents.length).fill('')]; @@ -110,10 +123,10 @@ export const TreeMap = ({ visualizations, layout, config }: any) => { : []; } else { const currentParentIndices = uniqueParents.map((parent) => - data[field.name].findIndex((index) => index === parent) + queriedVizData[field.name].findIndex((index) => index === parent) ); const lastParents = currentParentIndices.map( - (index) => data[lastParentField.name][index] + (index) => queriedVizData[lastParentField.name][index] ); parentsArray = [...parentsArray, ...lastParents]; valuesArray = [...valuesArray, ...Array(lastParents.length).fill(0)]; @@ -131,12 +144,15 @@ export const TreeMap = ({ visualizations, layout, config }: any) => { lastParentField = field; }); - labelsArray = [...labelsArray, ...data[childField.name]]; - valuesArray = [...valuesArray, ...data[valueField.name]]; - parentsArray = [...parentsArray, ...data[lastParentField.name]]; + labelsArray = [...labelsArray, ...queriedVizData[childField.name]]; + valuesArray = [...valuesArray, ...queriedVizData[valueField.name]]; + parentsArray = [...parentsArray, ...queriedVizData[lastParentField.name]]; colorsArray = colorField.name === MULTI_COLOR_PALETTE - ? [...colorsArray, ...Array(data[childField.name].length).fill(colorField.childColor)] + ? [ + ...colorsArray, + ...Array(queriedVizData[childField.name].length).fill(colorField.childColor), + ] : []; } @@ -184,7 +200,7 @@ export const TreeMap = ({ visualizations, layout, config }: any) => { return [mapData, mapLayout]; }, [ - data, + queriedVizData, childField, valueField, parentFields, diff --git a/dashboards-observability/public/components/visualizations/charts/pie/pie.tsx b/dashboards-observability/public/components/visualizations/charts/pie/pie.tsx index 89d1657fe..13a4e1611 100644 --- a/dashboards-observability/public/components/visualizations/charts/pie/pie.tsx +++ b/dashboards-observability/public/components/visualizations/charts/pie/pie.tsx @@ -8,62 +8,76 @@ import { isEmpty, find } from 'lodash'; import { Plt } from '../../plotly/plot'; import { EmptyPlaceholder } from '../../../event_analytics/explorer/visualizations/shared_components/empty_placeholder'; import { getTooltipHoverInfo } from '../../../event_analytics/utils/utils'; -import { ConfigListEntry } from '../../../../../common/types/explorer'; +import { + ConfigListEntry, + IVisualizationContainerProps, +} from '../../../../../common/types/explorer'; import { DEFAULT_PALETTE, HEX_CONTRAST_COLOR } from '../../../../../common/constants/colors'; import { PLOTLY_PIE_COLUMN_NUMBER, PIE_YAXIS_GAP, PIE_XAXIS_GAP, + AGGREGATIONS, + GROUPBY, } from '../../../../../common/constants/explorer'; export const Pie = ({ visualizations, layout, config }: any) => { - const { vis } = visualizations; const { - data, - metadata: { fields }, - } = visualizations.data.rawVizData; + data: { + defaultAxes, + indexFields, + query, + rawVizData: { + data: queriedVizData, + metadata: { fields }, + }, + userConfigs, + }, + vis: visMetaData, + }: IVisualizationContainerProps = visualizations; + const { dataConfig: { chartStyles = {}, - dimensions = [], - metrics = [], span = {}, legend = {}, panelOptions = {}, tooltipOptions = {}, + [GROUPBY]: dimensions = [], + [AGGREGATIONS]: series = [], }, layoutConfig = {}, } = visualizations?.data?.userConfigs; - const type = chartStyles.mode || vis.mode; + const type = chartStyles.mode || visMetaData.mode; const colorTheme = chartStyles.colorTheme ? chartStyles.colorTheme : { name: DEFAULT_PALETTE }; - const showLegend = legend.showLegend === 'hidden' ? false : vis.showlegend; - const legendSize = legend.size || vis.legendSize; - const labelSize = chartStyles.labelSize || vis.labelSize; + const showLegend = legend.showLegend === 'hidden' ? false : visMetaData.showlegend; + const legendSize = legend.size || visMetaData.legendSize; + const labelSize = chartStyles.labelSize || visMetaData.labelSize; const title = panelOptions.title || layoutConfig.layout?.title || ''; const timestampField = find(fields, (field) => field.type === 'timestamp'); /** * determine x axis */ - let xaxes: ConfigListEntry[]; + let xaxes: ConfigListEntry[] = []; if (span && span.time_field && timestampField) { xaxes = [timestampField, ...dimensions]; } else { xaxes = dimensions; } - if (isEmpty(xaxes) || isEmpty(metrics)) { - return ; + if (isEmpty(xaxes) || isEmpty(series)) { + return ; } const invertHex = (hex: string) => (Number(`0x1${hex}`) ^ HEX_CONTRAST_COLOR).toString(16).substr(1).toUpperCase(); const labelsOfXAxis = xaxes.reduce((prev, cur) => { - if (data[cur.name]) { - if (prev.length === 0) return data[cur.name].flat(); + if (queriedVizData[cur.name]) { + if (prev.length === 0) return queriedVizData[cur.name].flat(); return prev.map( - (item: string | number, index: number) => `${item}, ${data[cur.name][index]}` + (item: string | number, index: number) => `${item}, ${queriedVizData[cur.name][index]}` ); } }, []); @@ -72,13 +86,13 @@ export const Pie = ({ visualizations, layout, config }: any) => { const pies = useMemo( () => - metrics.map((field: any, index: number) => { + series.map((field: any, index: number) => { const fieldName = field.alias ? field.alias : `${field.aggregation}(${field.name})`; const marker = colorTheme.name !== DEFAULT_PALETTE ? { marker: { - colors: [...Array(data[fieldName].length).fill(colorTheme.childColor)], + colors: [...Array(queriedVizData[fieldName].length).fill(colorTheme.childColor)], line: { color: hexColor, width: 1, @@ -88,7 +102,7 @@ export const Pie = ({ visualizations, layout, config }: any) => { : undefined; return { labels: labelsOfXAxis, - values: data[fieldName], + values: queriedVizData[fieldName], type: 'pie', name: fieldName, hole: type === 'pie' ? 0 : 0.5, @@ -111,17 +125,17 @@ export const Pie = ({ visualizations, layout, config }: any) => { }, }; }), - [metrics, data, labelSize, labelsOfXAxis, colorTheme] + [series, queriedVizData, labelSize, labelsOfXAxis, colorTheme] ); const mergedLayout = useMemo(() => { - const isAtleastOneFullRow = Math.floor(metrics.length / PLOTLY_PIE_COLUMN_NUMBER) > 0; + const isAtleastOneFullRow = Math.floor(series.length / PLOTLY_PIE_COLUMN_NUMBER) > 0; return { grid: { xgap: PIE_XAXIS_GAP, ygap: PIE_YAXIS_GAP, - rows: Math.floor(metrics.length / PLOTLY_PIE_COLUMN_NUMBER) + 1, - columns: isAtleastOneFullRow ? PLOTLY_PIE_COLUMN_NUMBER : metrics.length, + rows: Math.floor(series.length / PLOTLY_PIE_COLUMN_NUMBER) + 1, + columns: isAtleastOneFullRow ? PLOTLY_PIE_COLUMN_NUMBER : series.length, pattern: 'independent', }, ...layout, @@ -129,14 +143,14 @@ export const Pie = ({ visualizations, layout, config }: any) => { title, legend: { ...layout.legend, - orientation: legend.position || vis.legendposition, + orientation: legend.position || visMetaData.legendposition, ...(legendSize && { font: { size: legendSize }, }), }, showlegend: showLegend, }; - }, [metrics, layoutConfig.layout, title, layout.legend]); + }, [series, layoutConfig.layout, title, layout.legend]); const mergedConfigs = useMemo( () => ({ diff --git a/dashboards-observability/public/components/visualizations/charts/pie/pie_type.ts b/dashboards-observability/public/components/visualizations/charts/pie/pie_type.ts index c8fea3d51..593d30d38 100644 --- a/dashboards-observability/public/components/visualizations/charts/pie/pie_type.ts +++ b/dashboards-observability/public/components/visualizations/charts/pie/pie_type.ts @@ -17,14 +17,14 @@ import { } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls'; import { fetchConfigObject } from '../../../../components/event_analytics/utils/utils'; import { DEFAULT_PALETTE, PIE_PALETTES } from '../../../../../common/constants/colors'; -import { PLOTLY_COLOR, DefaultChartStyles } from '../../../../../common/constants/shared'; -import { DefaultPieChartParameters } from '../../../../../common/constants/explorer'; +import { PLOTLY_COLOR, DEFAULT_CHART_STYLES } from '../../../../../common/constants/shared'; +import { DEFAULT_PIE_CHART_PARAMETERS } from '../../../../../common/constants/explorer'; const sharedConfigs = getPlotlySharedConfigs(); const VIS_CATEGORY = getPlotlyCategory(); -const { ShowLegend, LegendPosition } = DefaultChartStyles; -const { DefaultMode } = DefaultPieChartParameters; +const { ShowLegend, LegendPosition } = DEFAULT_CHART_STYLES; +const { DefaultMode } = DEFAULT_PIE_CHART_PARAMETERS; export const createPieTypeDefinition = (params: any) => ({ name: 'pie', diff --git a/dashboards-observability/public/components/visualizations/visualization.tsx b/dashboards-observability/public/components/visualizations/visualization.tsx index c3c13c4b9..75ba98241 100644 --- a/dashboards-observability/public/components/visualizations/visualization.tsx +++ b/dashboards-observability/public/components/visualizations/visualization.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { isArray } from 'lodash'; import { VisualizationChart } from './visualization_chart'; import { EmptyPlaceholder } from '../event_analytics/explorer/visualizations/shared_components/empty_placeholder'; -import { visChartTypes } from '../../../common/constants/shared'; +import { VIS_CHART_TYPES } from '../../../common/constants/shared'; interface IVisualizationProps {} @@ -24,7 +24,7 @@ export const Visualization = ({ visualizations }: IVisualizationProps) => { return ( <> - {vis?.type === visChartTypes.LogsView || (isVizDataValid && isVizFieldValid) ? ( + {vis?.type === VIS_CHART_TYPES.LogsView || (isVizDataValid && isVizFieldValid) ? ( ) : (