From df2e9b5384bceb32b7268e9ac19b03b67453306a Mon Sep 17 00:00:00 2001 From: Ramneet Chopra Date: Thu, 18 Aug 2022 12:28:38 +0530 Subject: [PATCH 1/6] metrics chart base code added Signed-off-by: Ramneet Chopra --- .../common/constants/explorer.ts | 48 +++- .../common/constants/shared.ts | 2 + .../common/types/explorer.ts | 11 + .../explorer/visualizations/app.scss | 1 + .../data_config_panel_item.tsx | 18 +- .../metric_config_panel_item.tsx | 238 ++++++++++++++++++ .../explorer/visualizations/index.tsx | 44 +++- .../charts/metrics/metrics.scss | 31 +++ .../visualizations/charts/metrics/metrics.tsx | 69 +++++ .../charts/metrics/metrics_type.ts | 69 +++++ .../visualizations/charts/vis_types.ts | 2 + 11 files changed, 505 insertions(+), 28 deletions(-) create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/metric_config_panel_item.tsx create mode 100644 dashboards-observability/public/components/visualizations/charts/metrics/metrics.scss create mode 100644 dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx create mode 100644 dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts diff --git a/dashboards-observability/common/constants/explorer.ts b/dashboards-observability/common/constants/explorer.ts index 9d52923fe..ae4f222e0 100644 --- a/dashboards-observability/common/constants/explorer.ts +++ b/dashboards-observability/common/constants/explorer.ts @@ -120,7 +120,16 @@ export const AGGREGATION_OPTIONS = [ ]; // numeric fields type for metrics -export const numericalTypes = ['float', 'double', 'bigint', 'long', 'octet', 'short', 'byte', 'integer']; +export const numericalTypes = [ + 'float', + 'double', + 'bigint', + 'long', + 'octet', + 'short', + 'byte', + 'integer', +]; // Data table constants export const GRID_HEADER_COLUMN_MAX_WIDTH = '150px'; export const GRID_PAGE_RANGE_DISPLAY = 5; @@ -136,13 +145,13 @@ export const HEADER_HEIGHT = 35; // gauge chart default parameters export interface DefaultGaugeChartParametersProps { - GaugeTitleSize: number, - DisplayDefaultGauges: number, - OrientationDefault: string, - TickLength: number, - LegendPlacement: string, - ThresholdsMaxLimit: number -}; + GaugeTitleSize: number; + DisplayDefaultGauges: number; + OrientationDefault: string; + TickLength: number; + LegendPlacement: string; + ThresholdsMaxLimit: number; +} export const DefaultGaugeChartParameters: DefaultGaugeChartParametersProps = { GaugeTitleSize: 14, @@ -150,5 +159,24 @@ export const DefaultGaugeChartParameters: DefaultGaugeChartParametersProps = { OrientationDefault: 'h', TickLength: 5, LegendPlacement: 'center', - ThresholdsMaxLimit: 1 -} + ThresholdsMaxLimit: 1, +}; + +// default ppl aggregation method options for metrics +export const METRICS_AGGREGATION_OPTIONS = [ + { + label: 'COUNT', + }, + { + label: 'SUM', + }, + { + label: 'AVERAGE', + }, + { + label: 'MAX', + }, + { + label: 'MIN', + }, +]; diff --git a/dashboards-observability/common/constants/shared.ts b/dashboards-observability/common/constants/shared.ts index e61909789..1223818c4 100644 --- a/dashboards-observability/common/constants/shared.ts +++ b/dashboards-observability/common/constants/shared.ts @@ -84,6 +84,7 @@ export enum visChartTypes { TreeMap = 'tree_map', Scatter = 'scatter', LogsView = 'logs_view', + Metrics = 'metrics', } export interface ValueOptionsAxes { @@ -110,6 +111,7 @@ export const ENABLED_VIS_TYPES = [ visChartTypes.Histogram, visChartTypes.Scatter, visChartTypes.LogsView, + visChartTypes.Metrics, ]; //Live tail constants diff --git a/dashboards-observability/common/types/explorer.ts b/dashboards-observability/common/types/explorer.ts index 9d3cb5072..3e3d4d890 100644 --- a/dashboards-observability/common/types/explorer.ts +++ b/dashboards-observability/common/types/explorer.ts @@ -274,3 +274,14 @@ export interface ConfigList { dimensions?: ConfigListEntry[] | HistogramConfigList[]; metrics?: ConfigListEntry[]; } + +export interface MetricListEntry { + label: string; + aggregation: string[]; + custom_label: string; + name: string; +} + +export interface MetricList { + metrics?: MetricListEntry[]; +} diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/app.scss b/dashboards-observability/public/components/event_analytics/explorer/visualizations/app.scss index ef67ba34b..a403ae110 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/app.scss +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/app.scss @@ -43,6 +43,7 @@ ::-webkit-scrollbar { width: 10px; + height: 10px; } ::-webkit-scrollbar-track { diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx index 986d023e9..f6070e711 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx @@ -76,6 +76,7 @@ export const DataConfigPanelItem = ({ fieldOptionList, visualizations }: any) => } else if ( visualizations.vis.name !== visChartTypes.HeatMap && visualizations.vis.name !== visChartTypes.Histogram && + visualizations.vis.name !== visChartTypes.Metrics && (data.defaultAxes.xaxis || data.defaultAxes.yaxis) ) { const { xaxis, yaxis } = data.defaultAxes; @@ -94,6 +95,10 @@ export const DataConfigPanelItem = ({ fieldOptionList, visualizations }: any) => setConfigList({ dimensions: [{ bucketSize: '', bucketOffset: '' }], }); + } else if (visualizations.vis.name === visChartTypes.Metrics) { + setConfigList({ + metrics: [initialConfigEntry], + }); } }, [ data.defaultAxes, @@ -311,11 +316,14 @@ export const DataConfigPanelItem = ({ fieldOptionList, visualizations }: any) => {visualizations.vis.name !== visChartTypes.Histogram ? ( <> - -

Dimensions

-
- {getCommonUI(configList.dimensions, 'dimensions')} - + {visualizations.vis.name !== visChartTypes.Metrics && ( + <> + +

Dimensions

+
+ {getCommonUI(configList.dimensions, 'dimensions')} + + )}

Metrics

diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/metric_config_panel_item.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/metric_config_panel_item.tsx new file mode 100644 index 000000000..7f4d13437 --- /dev/null +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/metric_config_panel_item.tsx @@ -0,0 +1,238 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useEffect, useState, useContext } from 'react'; +import { + EuiTitle, + EuiComboBox, + EuiSpacer, + EuiButton, + EuiFieldText, + EuiFlexItem, + EuiFormRow, + EuiIcon, + EuiPanel, + EuiText, +} from '@elastic/eui'; +import { useDispatch, useSelector } from 'react-redux'; +import { + render as renderExplorerVis, + selectExplorerVisualization, +} from '../../../../../../event_analytics/redux/slices/visualization_slice'; +import { + METRICS_AGGREGATION_OPTIONS, + numericalTypes, +} from '../../../../../../../../common/constants/explorer'; +import { visChartTypes } from '../../../../../../../../common/constants/shared'; +import { MetricList, MetricListEntry } from '../../../../../../../../common/types/explorer'; +import { TabContext } from '../../../../../hooks'; + +export const MetricConfigPanelItem = ({ fieldOptionList, visualizations }: any) => { + const dispatch = useDispatch(); + const { tabId } = useContext(TabContext); + const explorerVisualizations = useSelector(selectExplorerVisualization)[tabId]; + const { data } = visualizations; + + const { data: vizData = {}, metadata: { fields = [] } = {} } = data?.rawVizData; + + const initialConfigEntry: MetricListEntry = { + label: '', + aggregation: [], + custom_label: '', + name: '', + }; + + const [configList, setConfigList] = useState({ + metrics: [initialConfigEntry], + }); + + useEffect(() => { + if ( + data.rawVizData?.[visualizations.vis.name] && + data.rawVizData?.[visualizations.vis.name].dataConfig + ) { + setConfigList({ + ...data.rawVizData[visualizations.vis.name].dataConfig, + }); + } + }, [ + data.defaultAxes, + data.rawVizData?.[visualizations.vis.name]?.dataConfig, + visualizations.vis.name, + ]); + + const updateList = (value: string, index: number, name: string, field: string) => { + let list = { ...configList }; + let listItem = { ...list[name][index] }; + listItem = { + ...listItem, + [field]: value, + }; + const updatedList = { + ...list, + [name]: [ + ...list[name].slice(0, index), + listItem, + ...list[name].slice(index + 1, list[name].length), + ], + }; + setConfigList(updatedList); + }; + + const updateListWithAgg = (value: string[], index: number, name: string, field: string) => { + const list = { ...configList }; + const listItem = { ...list[name][index] }; + const updatedList = { + ...list, + [name]: [ + ...list[name].slice(0, index), + { + ...listItem, + [field]: value.map((val) => val), + }, + ...list[name].slice(index + 1, list[name].length), + ], + }; + setConfigList(updatedList); + }; + + const handleServiceRemove = (index: number, name: string) => { + const list = { ...configList }; + const arr = [...list[name]]; + arr.splice(index, 1); + const updatedList = { ...list, [name]: arr }; + setConfigList(updatedList); + }; + + const handleServiceAdd = (name: string) => { + const updatedList = { ...configList, [name]: [...configList[name], initialConfigEntry] }; + setConfigList(updatedList); + }; + + const updateChart = () => { + dispatch( + renderExplorerVis({ + tabId, + data: { + ...explorerVisualizations, + [visualizations.vis.name]: { + dataConfig: { + metrics: configList.metrics, + }, + }, + }, + }) + ); + }; + + const getOptionsAvailable = (sectionName: string) => { + let selectedFields = {}; + for (const key in configList) { + configList[key] && configList[key].forEach((field) => (selectedFields[field.label] = true)); + } + const unselectedFields = fieldOptionList.filter((field) => !selectedFields[field.label]); + return unselectedFields.filter((field) => numericalTypes.includes(field.type)); + }; + + const getCommonUI = (lists, sectionName: string) => + lists && + lists.map((singleField, index: number) => ( + <> +
+
+ + + handleServiceRemove(index, sectionName)} + /> + + ) + } + > + 0 ? singleField.aggregation : [] + } + onChange={(e) => + updateListWithAgg(e.length > 0 ? e : '', index, sectionName, 'aggregation') + } + /> + + + + updateList(e.length > 0 ? e[0].label : '', index, sectionName, 'label') + } + /> + + + + updateList(e.target.value, index, sectionName, 'custom_label')} + aria-label="Use aria labels when no actual label is in use" + /> + + + + {visualizations.vis.name !== visChartTypes.HeatMap && lists.length - 1 === index && ( + + handleServiceAdd(sectionName)} + > + Add + + + )} + +
+
+ + + )); + + return ( + <> + +

Data Configurations

+
+ + + +

Metrics

+
+ {getCommonUI(configList.metrics, 'metrics')} + + + 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 d1ce0398f..2615060e3 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx @@ -18,6 +18,8 @@ import { DataConfigPanelItem } from './config_panel/config_panes/config_controls import { TabContext } from '../../hooks'; import { PPL_STATS_REGEX, visChartTypes } from '../../../../../common/constants/shared'; import { TreemapConfigPanelItem } from './config_panel/config_panes/config_controls/treemap_config_panel_item'; +import { MetricConfigPanelItem } from './config_panel/config_panes/config_controls/metric_config_panel_item'; + interface IExplorerVisualizationsProps { query: IQuery; curVisId: string; @@ -55,6 +57,34 @@ export const ExplorerVisualizations = ({ return { ...field, label: field.name }; }); + const renderConfigPanelItem = () => { + if (curVisId === visChartTypes.TreeMap) { + return ( + + ); + } else if (curVisId === visChartTypes.Metrics) { + return ( + + ); + } else { + return ( + + ); + } + }; + return ( {(EuiResizablePanel, EuiResizableButton) => ( @@ -98,19 +128,7 @@ export const ExplorerVisualizations = ({ > - {curVisId === visChartTypes.TreeMap ? ( - - ) : ( - - )} + {renderConfigPanelItem()} diff --git a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.scss b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.scss new file mode 100644 index 000000000..c742e8527 --- /dev/null +++ b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.scss @@ -0,0 +1,31 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +.metricsContainer { + font-size: 16px; + display: flex; + align-items: center; + justify-content: center; + overflow-x: auto; + height: 1180px; +} + +.metricValueContainer { + padding: 20px 0; +} + +.metricValue { + text-align: center; +} + +.aggregateValue { + font-size: 48px; + font-weight: 700; +} + +.aggregateLabel { + font-size: 24px; + font-weight: 400; +} diff --git a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx new file mode 100644 index 000000000..3ba529e27 --- /dev/null +++ b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx @@ -0,0 +1,69 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +import { EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; +import React from 'react'; +import { sum, min, max, meanBy } from 'lodash'; +import { EmptyPlaceholder } from '../../../event_analytics/explorer/visualizations/shared_components/empty_placeholder'; +import './metrics.scss'; + +export const Metrics = ({ visualizations }: any) => { + const { + data, + metadata: { fields }, + } = visualizations.data.rawVizData; + const { dataConfig = {}, layoutConfig = {} } = visualizations.data.userConfigs; + console.log("dataConfig====", dataConfig) + console.log("layoutConfig===", layoutConfig) + const dataConfigTab = + visualizations.data?.rawVizData?.metrics?.dataConfig && + visualizations.data.rawVizData.metrics.dataConfig; + + const calculateAggregateValue = (aggregate: string, label: string) => { + if (aggregate === 'COUNT') { + return data[label].length; + } else if (aggregate === 'AVERAGE') { + return meanBy(data[label]).toFixed(2); + } else if (aggregate === 'MAX') { + return (max(data[label]) as number).toFixed(2); + } else if (aggregate === 'MIN') { + return (min(data[label]) as number).toFixed(2); + } else if (aggregate === 'SUM') { + return sum(data[label]).toFixed(2); + } + }; + + return ( +
+
+ {dataConfigTab && dataConfigTab.metrics.length > 0 ? ( + dataConfigTab.metrics.map((metric) => { + return ( + + {metric.aggregation.length !== 0 && + metric.label !== '' && + metric.aggregation.map((aggFunction) => ( + +
+ {calculateAggregateValue(aggFunction.label, metric.label)} +
+
+ {metric.custom_label !== '' ? metric.custom_label : metric.label} +
+
+ ))} +
+ ); + }) + ) : ( + + )} +
+
+ ) +}; diff --git a/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts b/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts new file mode 100644 index 000000000..26adc73c4 --- /dev/null +++ b/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts @@ -0,0 +1,69 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Metrics } from './metrics'; +import { getPlotlyCategory, getPlotlySharedConfigs } from '../shared/shared_configs'; +import { LensIconChartDatatable } from '../../assets/chart_datatable'; +import { VizDataPanel } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/default_vis_editor'; +import { PLOTLY_COLOR } from '../../../../../common/constants/shared'; + +const sharedConfigs = getPlotlySharedConfigs(); +const VIS_CATEGORY = getPlotlyCategory(); + +export const createMetricsTypeDefinition = (params: any = {}) => ({ + name: 'metrics', + type: 'metrics', + id: 'metrics', + label: 'Metrics', + fulllabel: 'Metrics', + icontype: 'visTable', + category: VIS_CATEGORY.BASICS, + selection: { + dataLoss: 'nothing', + }, + icon: LensIconChartDatatable, + categoryaxis: 'xaxis', + seriesaxis: 'yaxis', + editorconfig: { + panelTabs: [ + { + id: 'data-panel', + name: 'Style', + mapTo: 'dataConfig', + editor: VizDataPanel, + sections: [], + }, + ], + }, + visconfig: { + layout: { + ...sharedConfigs.layout, + colorway: PLOTLY_COLOR, + plot_bgcolor: 'rgba(0, 0, 0, 0)', + paper_bgcolor: 'rgba(0, 0, 0, 0)', + xaxis: { + fixedrange: true, + showgrid: false, + visible: true, + }, + yaxis: { + fixedrange: true, + showgrid: false, + visible: true, + }, + }, + config: { + ...sharedConfigs.config, + barmode: 'line', + xaxis: { + automargin: true, + }, + yaxis: { + automargin: true, + }, + }, + }, + component: Metrics, +}); diff --git a/dashboards-observability/public/components/visualizations/charts/vis_types.ts b/dashboards-observability/public/components/visualizations/charts/vis_types.ts index 9f37f2fbb..e11b1f491 100644 --- a/dashboards-observability/public/components/visualizations/charts/vis_types.ts +++ b/dashboards-observability/public/components/visualizations/charts/vis_types.ts @@ -15,6 +15,7 @@ import { createGaugeTypeDefinition } from './financial/gauge/gauge_type'; import { createTreeMapDefinition } from './maps/treemap_type'; import { createTextTypeDefinition } from './text/text_type'; import { createLogsViewTypeDefinition } from './logs_view/logs_view_type'; +import { createMetricsTypeDefinition } from './metrics/metrics_type'; export const VIS_TYPES = { bar: createBarTypeDefinition, @@ -30,6 +31,7 @@ export const VIS_TYPES = { text: createTextTypeDefinition, scatter: createLineTypeDefinition, logs_view: createLogsViewTypeDefinition, + metrics: createMetricsTypeDefinition, }; export const getVisType = (visType: string, params: any = {}) => { From 79532fe396f598e09769645e394bf15cce92f9e9 Mon Sep 17 00:00:00 2001 From: SivaprasadAluri Date: Mon, 22 Aug 2022 16:50:04 +0530 Subject: [PATCH 2/6] feat: Metric Chart with Styles --- .../config_controls/config_legend.tsx | 5 +- .../__snapshots__/metrics.test.tsx.snap | 568 ++++++++++++++++++ .../charts/__tests__/metrics.test.tsx | 34 ++ .../charts/metrics/metrics.scss | 8 + .../visualizations/charts/metrics/metrics.tsx | 23 +- .../charts/metrics/metrics_type.ts | 27 +- 6 files changed, 655 insertions(+), 10 deletions(-) create mode 100644 dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/metrics.test.tsx.snap create mode 100644 dashboards-observability/public/components/visualizations/charts/__tests__/metrics.test.tsx diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx index f048ab8ad..e9aadc722 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx @@ -8,7 +8,7 @@ import { EuiAccordion, EuiSpacer } from '@elastic/eui'; import { ButtonGroupItem } from './config_button_group'; import { IConfigPanelOptionSection } from '../../../../../../../../common/types/explorer'; -export const ConfigLegend = ({ schemas, vizState, handleConfigChange }: any) => { +export const ConfigLegend = ({ schemas, vizState, handleConfigChange, sectionName = "Legend"}: any) => { const handleConfigurationChange = useCallback( (stateFiledName) => { return (changes) => { @@ -58,7 +58,8 @@ export const ConfigLegend = ({ schemas, vizState, handleConfigChange }: any) => }, [schemas, vizState, handleConfigurationChange]); return ( - + // + {dimensions} ); diff --git a/dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/metrics.test.tsx.snap b/dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/metrics.test.tsx.snap new file mode 100644 index 000000000..0ee3244c3 --- /dev/null +++ b/dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/metrics.test.tsx.snap @@ -0,0 +1,568 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Metrics component Renders metrics component 1`] = ` + +
+

+ + +

+
+ + +
+ +
+ +
+ + + + + + +
+ +

+ + + No results found + + +

+
+ +
+ +
+ + +
+
+ +`; diff --git a/dashboards-observability/public/components/visualizations/charts/__tests__/metrics.test.tsx b/dashboards-observability/public/components/visualizations/charts/__tests__/metrics.test.tsx new file mode 100644 index 000000000..99180cf26 --- /dev/null +++ b/dashboards-observability/public/components/visualizations/charts/__tests__/metrics.test.tsx @@ -0,0 +1,34 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { configure, mount } from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; +import React from 'react'; +import { waitFor } from '@testing-library/react'; +import { Metrics } from '../metrics/metrics'; +import { + LAYOUT_CONFIG, + TEST_VISUALIZATIONS_DATA +} from '../../../../../test/event_analytics_constants'; + +describe('Metrics component', () => { + configure({ adapter: new Adapter() }); + + it('Renders metrics component', async () => { + const wrapper = mount( + + ); + + wrapper.update(); + + await waitFor(() => { + expect(wrapper).toMatchSnapshot(); + }); + }); +}); diff --git a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.scss b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.scss index c742e8527..e3bb39aae 100644 --- a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.scss +++ b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.scss @@ -10,6 +10,14 @@ justify-content: center; overflow-x: auto; height: 1180px; + position: relative; +} + +.metricTitle{ + position:absolute; + top: 20px; + text-align: center; + width: '100%' } .metricValueContainer { diff --git a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx index 3ba529e27..e25f84774 100644 --- a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx +++ b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx @@ -14,11 +14,15 @@ export const Metrics = ({ visualizations }: any) => { metadata: { fields }, } = visualizations.data.rawVizData; const { dataConfig = {}, layoutConfig = {} } = visualizations.data.userConfigs; - console.log("dataConfig====", dataConfig) - console.log("layoutConfig===", layoutConfig) const dataConfigTab = visualizations.data?.rawVizData?.metrics?.dataConfig && visualizations.data.rawVizData.metrics.dataConfig; + const dataTitle = dataConfig?.panelOptions?.title; + + const getSelectedColorTheme = (field: any, index: number) => + (dataConfig?.colorTheme?.length > 0 && + dataConfig.colorTheme.find((colorSelected) => colorSelected.name.name === field) + ?.color) || '#000'; const calculateAggregateValue = (aggregate: string, label: string) => { if (aggregate === 'COUNT') { @@ -35,25 +39,30 @@ export const Metrics = ({ visualizations }: any) => { }; return ( + +
+

{dataTitle}

{dataConfigTab && dataConfigTab.metrics.length > 0 ? ( - dataConfigTab.metrics.map((metric) => { + dataConfigTab.metrics.map((metric, index) => { return ( + {metric.aggregation.length !== 0 && metric.label !== '' && metric.aggregation.map((aggFunction) => ( -
+
{calculateAggregateValue(aggFunction.label, metric.label)}
-
- {metric.custom_label !== '' ? metric.custom_label : metric.label} +
+ {aggFunction.label} {metric.custom_label !== '' ? metric.custom_label : metric.label}
))} @@ -61,7 +70,7 @@ export const Metrics = ({ visualizations }: any) => { ); }) ) : ( - + )}
diff --git a/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts b/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts index 26adc73c4..f9f604826 100644 --- a/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts +++ b/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts @@ -8,6 +8,7 @@ import { getPlotlyCategory, getPlotlySharedConfigs } from '../shared/shared_conf import { LensIconChartDatatable } from '../../assets/chart_datatable'; import { VizDataPanel } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/default_vis_editor'; import { PLOTLY_COLOR } from '../../../../../common/constants/shared'; +import { ConfigColorTheme, ConfigLegend, InputFieldItem } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/config_controls'; const sharedConfigs = getPlotlySharedConfigs(); const VIS_CATEGORY = getPlotlyCategory(); @@ -33,8 +34,32 @@ export const createMetricsTypeDefinition = (params: any = {}) => ({ name: 'Style', mapTo: 'dataConfig', editor: VizDataPanel, - sections: [], + sections: [ + { + id: 'color-theme', + name: 'Color theme', + editor: ConfigColorTheme, + mapTo: 'colorTheme', + schemas: [], + }, + { + id: 'fontsize', + name: 'Metric FontSize', + editor: ConfigLegend, + mapTo: 'FontSize', + schemas: [ + { + title: 'Font size', + name: 'Font size', + component: InputFieldItem, + mapTo: 'fontsize', + eleType: 'input', + }, + ] + }, + ], }, + ], }, visconfig: { From 1e87ad597748109b3f5ba7fdc86ab25f956f230b Mon Sep 17 00:00:00 2001 From: SivaprasadAluri Date: Mon, 22 Aug 2022 12:01:29 +0000 Subject: [PATCH 3/6] updated snaps --- .../__snapshots__/no_results.test.tsx.snap | 6 +- .../__snapshots__/config_panel.test.tsx.snap | 102 ++++++++++++++++++ 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/dashboards-observability/public/components/event_analytics/__tests__/__snapshots__/no_results.test.tsx.snap b/dashboards-observability/public/components/event_analytics/__tests__/__snapshots__/no_results.test.tsx.snap index a128191e4..33f8d184e 100644 --- a/dashboards-observability/public/components/event_analytics/__tests__/__snapshots__/no_results.test.tsx.snap +++ b/dashboards-observability/public/components/event_analytics/__tests__/__snapshots__/no_results.test.tsx.snap @@ -192,11 +192,13 @@ exports[`No result component Renders No result component 1`] = `

- Your query may not match anything in the current time range, or there may not be any data at all in the currently selected time range. Try change time range, query filters or choose different time fields + Your query may not match anything in the current time range, or there may not be any data at all in + the currently selected time range. Try change time range, query filters or choose different time fields

diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/__tests__/__snapshots__/config_panel.test.tsx.snap b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/__tests__/__snapshots__/config_panel.test.tsx.snap index f56e711c7..5eaf20343 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/__tests__/__snapshots__/config_panel.test.tsx.snap +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/__tests__/__snapshots__/config_panel.test.tsx.snap @@ -2839,6 +2839,108 @@ exports[`Config panel component Renders config panel with visualization data 1`] }, }, }, + Object { + "category": "Visualizations", + "categoryaxis": "xaxis", + "component": [Function], + "editorconfig": Object { + "panelTabs": Array [ + Object { + "editor": [Function], + "id": "data-panel", + "mapTo": "dataConfig", + "name": "Style", + "sections": Array [ + Object { + "editor": [Function], + "id": "color-theme", + "mapTo": "colorTheme", + "name": "Color theme", + "schemas": Array [], + }, + Object { + "editor": [Function], + "id": "fontsize", + "mapTo": "FontSize", + "name": "Metric FontSize", + "schemas": Array [ + Object { + "component": [Function], + "eleType": "input", + "mapTo": "fontsize", + "name": "Font size", + "title": "Font size", + }, + ], + }, + ], + }, + ], + }, + "fulllabel": "Metrics", + "icon": [Function], + "icontype": "visTable", + "id": "metrics", + "label": "Metrics", + "name": "metrics", + "selection": Object { + "dataLoss": "nothing", + }, + "seriesaxis": "yaxis", + "type": "metrics", + "visconfig": Object { + "config": Object { + "barmode": "line", + "displaylogo": false, + "responsive": true, + "xaxis": Object { + "automargin": true, + }, + "yaxis": Object { + "automargin": true, + }, + }, + "layout": Object { + "colorway": Array [ + "#3CA1C7", + "#8C55A3", + "#DB748A", + "#F2BE4B", + "#68CCC2", + "#2A7866", + "#843769", + "#374FB8", + "#BD6F26", + "#4C636F", + ], + "height": 1180, + "legend": Object { + "orientation": "v", + "traceorder": "normal", + }, + "margin": Object { + "b": 30, + "l": 60, + "pad": 0, + "r": 30, + "t": 50, + }, + "paper_bgcolor": "rgba(0, 0, 0, 0)", + "plot_bgcolor": "rgba(0, 0, 0, 0)", + "showlegend": true, + "xaxis": Object { + "fixedrange": true, + "showgrid": false, + "visible": true, + }, + "yaxis": Object { + "fixedrange": true, + "showgrid": false, + "visible": true, + }, + }, + }, + }, ] } placeholder="Select a chart" From 4f3d51d38b02f33c0dfd53072172176f1338e033 Mon Sep 17 00:00:00 2001 From: SivaprasadAluri Date: Mon, 22 Aug 2022 12:38:38 +0000 Subject: [PATCH 4/6] removed spaces and comments --- .../config_controls/config_legend.tsx | 17 +++++++--- .../visualizations/charts/metrics/metrics.tsx | 32 +++++++++++-------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx index e9aadc722..3b0fc30ee 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx @@ -8,7 +8,12 @@ import { EuiAccordion, EuiSpacer } from '@elastic/eui'; import { ButtonGroupItem } from './config_button_group'; import { IConfigPanelOptionSection } from '../../../../../../../../common/types/explorer'; -export const ConfigLegend = ({ schemas, vizState, handleConfigChange, sectionName = "Legend"}: any) => { +export const ConfigLegend = ({ + schemas, + vizState, + handleConfigChange, + sectionName = 'Legend', +}: any) => { const handleConfigurationChange = useCallback( (stateFiledName) => { return (changes) => { @@ -50,7 +55,7 @@ export const ConfigLegend = ({ schemas, vizState, handleConfigChange, sectionNa } return ( - + ); @@ -58,8 +63,12 @@ export const ConfigLegend = ({ schemas, vizState, handleConfigChange, sectionNa }, [schemas, vizState, handleConfigurationChange]); return ( - // - + {dimensions} ); diff --git a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx index e25f84774..f603a5097 100644 --- a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx +++ b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx @@ -13,18 +13,18 @@ export const Metrics = ({ visualizations }: any) => { data, metadata: { fields }, } = visualizations.data.rawVizData; - const { dataConfig = {}, layoutConfig = {} } = visualizations.data.userConfigs; + const { dataConfig = {}, layoutConfig = {} } = visualizations.data.userConfigs; const dataConfigTab = visualizations.data?.rawVizData?.metrics?.dataConfig && visualizations.data.rawVizData.metrics.dataConfig; const dataTitle = dataConfig?.panelOptions?.title; const getSelectedColorTheme = (field: any, index: number) => - (dataConfig?.colorTheme?.length > 0 && - dataConfig.colorTheme.find((colorSelected) => colorSelected.name.name === field) - ?.color) || '#000'; + (dataConfig?.colorTheme?.length > 0 && + dataConfig.colorTheme.find((colorSelected) => colorSelected.name.name === field)?.color) || + '#000'; - const calculateAggregateValue = (aggregate: string, label: string) => { + const calculateAggregateValue = (aggregate: string, label: string) => { if (aggregate === 'COUNT') { return data[label].length; } else if (aggregate === 'AVERAGE') { @@ -39,30 +39,34 @@ export const Metrics = ({ visualizations }: any) => { }; return ( - -
-

{dataTitle}

+

{dataTitle}

{dataConfigTab && dataConfigTab.metrics.length > 0 ? ( dataConfigTab.metrics.map((metric, index) => { return ( - {metric.aggregation.length !== 0 && metric.label !== '' && metric.aggregation.map((aggFunction) => ( -
+
{calculateAggregateValue(aggFunction.label, metric.label)}
-
- {aggFunction.label} {metric.custom_label !== '' ? metric.custom_label : metric.label} +
+ {aggFunction.label} + {metric.custom_label !== '' ? metric.custom_label : metric.label}
))} @@ -74,5 +78,5 @@ export const Metrics = ({ visualizations }: any) => { )}
- ) + ); }; From f4a959287a65d568719e5db7cbe91b7a4e02490b Mon Sep 17 00:00:00 2001 From: SivaprasadAluri Date: Mon, 22 Aug 2022 13:47:01 +0000 Subject: [PATCH 5/6] fixed Review comments --- .../__snapshots__/no_results.test.tsx.snap | 6 ++--- .../explorer/visualizations/app.scss | 1 - .../visualizations/charts/metrics/metrics.tsx | 25 ++++++++----------- .../charts/metrics/metrics_type.ts | 4 +-- 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/dashboards-observability/public/components/event_analytics/__tests__/__snapshots__/no_results.test.tsx.snap b/dashboards-observability/public/components/event_analytics/__tests__/__snapshots__/no_results.test.tsx.snap index 33f8d184e..a128191e4 100644 --- a/dashboards-observability/public/components/event_analytics/__tests__/__snapshots__/no_results.test.tsx.snap +++ b/dashboards-observability/public/components/event_analytics/__tests__/__snapshots__/no_results.test.tsx.snap @@ -192,13 +192,11 @@ exports[`No result component Renders No result component 1`] = `

- Your query may not match anything in the current time range, or there may not be any data at all in - the currently selected time range. Try change time range, query filters or choose different time fields + Your query may not match anything in the current time range, or there may not be any data at all in the currently selected time range. Try change time range, query filters or choose different time fields

diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/app.scss b/dashboards-observability/public/components/event_analytics/explorer/visualizations/app.scss index a403ae110..ef67ba34b 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/app.scss +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/app.scss @@ -43,7 +43,6 @@ ::-webkit-scrollbar { width: 10px; - height: 10px; } ::-webkit-scrollbar-track { diff --git a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx index f603a5097..25131f590 100644 --- a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx +++ b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx @@ -19,10 +19,13 @@ export const Metrics = ({ visualizations }: any) => { visualizations.data.rawVizData.metrics.dataConfig; const dataTitle = dataConfig?.panelOptions?.title; + const metricLabel = dataConfigTab?.metrics?.filter((value) => value.label !== ''); + const getSelectedColorTheme = (field: any, index: number) => (dataConfig?.colorTheme?.length > 0 && dataConfig.colorTheme.find((colorSelected) => colorSelected.name.name === field)?.color) || '#000'; + const fontSize = dataConfig?.fontSize?.fontSize; const calculateAggregateValue = (aggregate: string, label: string) => { if (aggregate === 'COUNT') { @@ -43,29 +46,23 @@ export const Metrics = ({ visualizations }: any) => {

{dataTitle}

{dataConfigTab && dataConfigTab.metrics.length > 0 ? ( - dataConfigTab.metrics.map((metric, index) => { + dataConfigTab.metrics.map((metric, index: number) => { return ( - {metric.aggregation.length !== 0 && - metric.label !== '' && - metric.aggregation.map((aggFunction) => ( - -
+ {metric.aggregation.length !== 0 && { metricLabel } && + metric.aggregation.map((aggFunction, i: number) => ( + +
{calculateAggregateValue(aggFunction.label, metric.label)}
-
- {aggFunction.label} +
+ {aggFunction.label} {metric.custom_label !== '' ? metric.custom_label : metric.label}
diff --git a/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts b/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts index f9f604826..98e3cff2e 100644 --- a/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts +++ b/dashboards-observability/public/components/visualizations/charts/metrics/metrics_type.ts @@ -46,13 +46,13 @@ export const createMetricsTypeDefinition = (params: any = {}) => ({ id: 'fontsize', name: 'Metric FontSize', editor: ConfigLegend, - mapTo: 'FontSize', + mapTo: 'fontSize', schemas: [ { title: 'Font size', name: 'Font size', component: InputFieldItem, - mapTo: 'fontsize', + mapTo: 'fontSize', eleType: 'input', }, ] From c190731525d1924f5e645418b0487034d76296b8 Mon Sep 17 00:00:00 2001 From: SivaprasadAluri Date: Thu, 25 Aug 2022 17:48:12 +0530 Subject: [PATCH 6/6] updated with review comments Signed-off-by: SivaprasadAluri --- .../config_controls/config_legend.tsx | 4 ++-- .../visualizations/charts/metrics/metrics.tsx | 21 ++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx index 3b0fc30ee..fd839e857 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx @@ -4,7 +4,7 @@ */ import React, { Fragment, useCallback, useMemo } from 'react'; -import { EuiAccordion, EuiSpacer } from '@elastic/eui'; +import { EuiAccordion, EuiSpacer, htmlIdGenerator } from '@elastic/eui'; import { ButtonGroupItem } from './config_button_group'; import { IConfigPanelOptionSection } from '../../../../../../../../common/types/explorer'; @@ -65,7 +65,7 @@ export const ConfigLegend = ({ return ( diff --git a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx index 25131f590..186d90f4e 100644 --- a/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx +++ b/dashboards-observability/public/components/visualizations/charts/metrics/metrics.tsx @@ -28,16 +28,17 @@ export const Metrics = ({ visualizations }: any) => { const fontSize = dataConfig?.fontSize?.fontSize; const calculateAggregateValue = (aggregate: string, label: string) => { - if (aggregate === 'COUNT') { - return data[label].length; - } else if (aggregate === 'AVERAGE') { - return meanBy(data[label]).toFixed(2); - } else if (aggregate === 'MAX') { - return (max(data[label]) as number).toFixed(2); - } else if (aggregate === 'MIN') { - return (min(data[label]) as number).toFixed(2); - } else if (aggregate === 'SUM') { - return sum(data[label]).toFixed(2); + switch (aggregate) { + case 'COUNT': + return data[label].length; + case 'AVERAGE': + return meanBy(data[label]).toFixed(2); + case 'MAX': + return (max(data[label]) as number).toFixed(2); + case 'MIN': + return (min(data[label]) as number).toFixed(2); + case 'SUM': + return sum(data[label]).toFixed(2); } };