From 7e7a414b5c5b2dfdeb79164b60af7979871a9199 Mon Sep 17 00:00:00 2001 From: Shankha Das Date: Fri, 24 Jun 2022 14:17:37 +0000 Subject: [PATCH 1/3] enhancement for heatmap with new UI Signed-off-by: Shankha Das --- .../common/types/explorer.ts | 14 ++ .../__snapshots__/config_panel.test.tsx.snap | 14 -- .../data_config_panel_item.tsx | 232 +++++++++++------- .../explorer/visualizations/index.tsx | 1 - .../visualizations/charts/maps/heatmap.tsx | 33 ++- .../charts/maps/heatmap_type.ts | 14 -- 6 files changed, 169 insertions(+), 139 deletions(-) diff --git a/dashboards-observability/common/types/explorer.ts b/dashboards-observability/common/types/explorer.ts index 3220add36..2204a6ab4 100644 --- a/dashboards-observability/common/types/explorer.ts +++ b/dashboards-observability/common/types/explorer.ts @@ -230,3 +230,17 @@ export interface LiveTailProps { isLiveTailPopoverOpen: boolean; dataTestSubj: string; } + +export interface ConfigListEntry { + label: string; + aggregation: string; + custom_label: string; + name: string; + side: string; + type: string; +} + +export interface ConfigList { + dimensions?: ConfigListEntry[]; + metrics?: ConfigListEntry[]; +} 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 724090f83..d58a98230 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 @@ -1277,20 +1277,6 @@ exports[`Config panel component Renders config panel with visualization data 1`] "mapTo": "dataConfig", "name": "Data", "sections": Array [ - Object { - "editor": [Function], - "id": "value_options", - "mapTo": "valueOptions", - "name": "Value options", - "schemas": Array [ - Object { - "component": null, - "isSingleSelection": true, - "mapTo": "zaxis", - "name": "Z-axis", - }, - ], - }, Object { "editor": [Function], "id": "chart_styles", 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 bb4d22822..dc6855551 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 @@ -3,50 +3,76 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { useContext, useEffect, useState } from 'react'; -import { EuiTitle, EuiComboBox, EuiSpacer, EuiButton, EuiFieldText, EuiFlexItem, EuiFormRow, EuiIcon, EuiPanel, EuiText } from '@elastic/eui'; +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 { AGGREGATION_OPTIONS } from '../../../../../../../../common/constants/explorer'; import { ButtonGroupItem } from './config_button_group'; import { visChartTypes } from '../../../../../../../../common/constants/shared'; +import { ConfigList } from '../../../../../../../../common/types/explorer'; import { TabContext } from '../../../../../hooks'; -export const DataConfigPanelItem = ({ - fieldOptionList, - visualizations, -}: any) => { + +export const DataConfigPanelItem = ({ 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 newEntry = { label: "", aggregation: "", custom_label: "", name: "", side: "right" }; + const initialConfigEntry = { + label: '', + aggregation: '', + custom_label: '', + name: '', + side: 'right', + type: '', + }; - const [configList, setConfigList] = useState({ - dimensions: [{ ...newEntry }], - metrics: [{ ...newEntry }], - }); + const [configList, setConfigList] = useState({}); useEffect(() => { if (data.rawVizData?.dataConfig) { setConfigList({ - ...data.rawVizData.dataConfig - }) - } else if (data.defaultAxes.xaxis || data.defaultAxes.yaxis) { + ...data.rawVizData.dataConfig, + }); + } else if ( + visualizations.vis.name !== visChartTypes.HeatMap && + (data.defaultAxes.xaxis || data.defaultAxes.yaxis) + ) { const { xaxis, yaxis } = data.defaultAxes; setConfigList({ - dimensions: [...xaxis && xaxis], - metrics: [...yaxis && yaxis], - }) + dimensions: [...(xaxis && xaxis)], + metrics: [...(yaxis && yaxis)], + }); + } else { + setConfigList({ + dimensions: [initialConfigEntry, initialConfigEntry], + metrics: [initialConfigEntry], + }); } - }, [data.defaultAxes, data.rawVizData?.dataConfig]); + }, [data.defaultAxes, data.rawVizData?.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 }; + listItem = { + ...listItem, + [field]: value, + type: value !== '' ? fields.find((x) => x.name === value).type : '', + }; const newList = { ...list, [name]: [ @@ -56,7 +82,7 @@ export const DataConfigPanelItem = ({ ], }; setConfigList(newList); - } + }; const handleServiceRemove = (index: number, name: string) => { const list = { ...configList }; @@ -74,7 +100,7 @@ export const DataConfigPanelItem = ({ const updateChart = () => { dispatch( renderExplorerVis({ - tabId: tabId, + tabId, data: { ...explorerVisualizations, dataConfig: { @@ -86,81 +112,101 @@ export const DataConfigPanelItem = ({ ); } - const isPositionButtonAllow = (sectionName: string) => sectionName === 'metrics' && (visualizations.vis.name === visChartTypes.Line || visualizations.vis.name === visChartTypes.Bar); + const isPositionButtonVisible = (sectionName: string) => + sectionName === 'metrics' && + (visualizations.vis.name === visChartTypes.Line || + visualizations.vis.name === visChartTypes.Bar); + + const getCommonUI = (lists, sectionName: string) => + lists && + lists.map((singleField, index: number) => ( + <> +
+
+ {sectionName === 'dimensions' && visualizations.vis.name === visChartTypes.HeatMap && ( + +
{index === 0 ? 'X-Axis' : 'Y-Axis'}
+
+ )} + + + handleServiceRemove(index, sectionName)} + /> + + ) + } + > + + updateList(e.length > 0 ? e[0].label : '', index, sectionName, 'aggregation') + } + /> + + + + updateList(e.length > 0 ? e[0].label : '', index, sectionName, 'label') + } + /> + - const getCommonUI = (lists, sectionName: string) => lists.map((singleField, index: number) => ( - <> -
-
- - - handleServiceRemove(index, sectionName)} - /> - - ) - } - > - updateList(e.length > 0 ? e[0].label : '', 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" /> - - - {isPositionButtonAllow(sectionName) && ( - - updateList(id, index, sectionName, 'side')} + + updateList(e.target.value, index, sectionName, 'custom_label')} + aria-label="Use aria labels when no actual label is in use" /> - )} - - {lists.length - 1 === index && - - handleServiceAdd(sectionName)}> - Add - - - } - + {isPositionButtonVisible(sectionName) && ( + + updateList(id, index, sectionName, 'side')} + /> + + )} + + + {visualizations.vis.name !== visChartTypes.HeatMap && lists.length - 1 === index && ( + + handleServiceAdd(sectionName)} + > + Add + + + )} +
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 543b498fc..cece6e284 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx @@ -81,7 +81,6 @@ export const ExplorerVisualizations = ({
diff --git a/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx b/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx index 9155dea04..d6b71a0ad 100644 --- a/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx +++ b/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx @@ -29,30 +29,29 @@ export const HeatMap = ({ visualizations, layout, config }: any) => { if (fields.length < 3) return ; - const xaxisField = fields[fields.length - 2]; - const yaxisField = fields[fields.length - 1]; - const zMetrics = - dataConfig?.valueOptions && dataConfig?.valueOptions.zaxis - ? dataConfig?.valueOptions.zaxis[0] - : yaxis.length > 0 - ? yaxis[0] - : fields[fields.length - 3]; - const uniqueYaxis = uniq(data[yaxisField.name]); - const uniqueXaxis = uniq(data[xaxisField.name]); - const uniqueYaxisLength = uniqueYaxis.length; - const uniqueXaxisLength = uniqueXaxis.length; + const xaxisField = visualizations.data?.rawVizData?.dataConfig?.dimensions[0]; + const yaxisField = visualizations.data?.rawVizData?.dataConfig?.dimensions[1]; + const zMetrics = visualizations.data?.rawVizData?.dataConfig?.metrics[0]; + console.log("xaxisField", xaxisField); + console.log("yaxisField", yaxisField); + console.log("zMetrics", zMetrics); if ( isEmpty(xaxisField) || isEmpty(yaxisField) || isEmpty(zMetrics) || - isEmpty(data[xaxisField.name]) || - isEmpty(data[yaxisField.name]) || - isEmpty(data[zMetrics.name]) || + isEmpty(data[xaxisField.label]) || + isEmpty(data[yaxisField.label]) || + isEmpty(data[zMetrics.label]) || indexOf(NUMERICAL_FIELDS, zMetrics.type) < 0 ) return ; + const uniqueYaxis = uniq(data[yaxisField.label]); + const uniqueXaxis = uniq(data[xaxisField.label]); + const uniqueYaxisLength = uniqueYaxis.length; + const uniqueXaxisLength = uniqueXaxis.length; + const colorField = dataConfig?.chartStyles ? dataConfig?.chartStyles.colorMode && dataConfig?.chartStyles.colorMode[0].name === OPACITY ? dataConfig?.chartStyles.color ?? HEATMAP_SINGLE_COLOR @@ -75,8 +74,8 @@ export const HeatMap = ({ visualizations, layout, config }: any) => { const buckets = {}; // maps bukcets to metrics - for (let i = 0; i < data[xaxisField.name].length; i++) { - buckets[`${data[xaxisField.name][i]},${data[yaxisField.name][i]}`] = data[zMetrics.name][i]; + for (let i = 0; i < data[xaxisField.label].length; i++) { + buckets[`${data[xaxisField.label][i]},${data[yaxisField.label][i]}`] = data[zMetrics.label][i]; } // initialize empty 2 dimensional array, inner loop for each xaxis field, outer loop for yaxis diff --git a/dashboards-observability/public/components/visualizations/charts/maps/heatmap_type.ts b/dashboards-observability/public/components/visualizations/charts/maps/heatmap_type.ts index 4b8872931..8bcd56697 100644 --- a/dashboards-observability/public/components/visualizations/charts/maps/heatmap_type.ts +++ b/dashboards-observability/public/components/visualizations/charts/maps/heatmap_type.ts @@ -44,20 +44,6 @@ export const createMapsVisDefinition = () => ({ mapTo: 'dataConfig', editor: VizDataPanel, sections: [ - { - id: 'value_options', - name: 'Value options', - editor: ConfigValueOptions, - mapTo: 'valueOptions', - schemas: [ - { - name: 'Z-axis', - isSingleSelection: true, - component: null, - mapTo: 'zaxis', - }, - ], - }, { id: 'chart_styles', name: 'Chart Styles', From 5017a0c4050d4b1e55b59c617fcea1b81e49aac8 Mon Sep 17 00:00:00 2001 From: Shankha Das Date: Fri, 24 Jun 2022 14:22:14 +0000 Subject: [PATCH 2/3] line chart test cases Signed-off-by: Shankha Das --- .../integration/1_event_analytics.spec.js | 13 +++- .../.cypress/utils/event_constants.js | 59 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/dashboards-observability/.cypress/integration/1_event_analytics.spec.js b/dashboards-observability/.cypress/integration/1_event_analytics.spec.js index 6e6d06d4e..f2b0db3c6 100644 --- a/dashboards-observability/.cypress/integration/1_event_analytics.spec.js +++ b/dashboards-observability/.cypress/integration/1_event_analytics.spec.js @@ -18,6 +18,10 @@ import { landOnEventExplorer, landOnEventVisualizations, landOnPanels, + renderTreeMapchart, + renderPieChart, + renderLineChartForDataConfig, + DataConfigLineChart } from '../utils/event_constants'; import { supressResizeObserverIssue } from '../utils/constants'; @@ -845,4 +849,11 @@ describe('Render Table View', () => { cy.get('.euiButtonEmpty__text').eq('6').click(); cy.get('.euiContextMenuItem__text').eq(1).click(); }); -}); \ No newline at end of file +}); + +describe('Render Time series chart/Line chart and verify Data configurations UI ', () => { + it('Render line chart and verify Data Configuration Panel', () => { + renderLineChartForDataConfig(); + DataConfigLineChart(); + }); +}); diff --git a/dashboards-observability/.cypress/utils/event_constants.js b/dashboards-observability/.cypress/utils/event_constants.js index e7ac570c5..4db8c146d 100644 --- a/dashboards-observability/.cypress/utils/event_constants.js +++ b/dashboards-observability/.cypress/utils/event_constants.js @@ -79,3 +79,62 @@ export const landOnPanels = () => { ); cy.wait(delay); }; + +export const renderTreeMapchart = () => { + querySearch(TEST_QUERIES[5].query, TEST_QUERIES[5].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').type('Tree Map').type('{enter}'); + cy.get('#configPanel__panelOptions .euiFieldText').click().type('Tree Map'); + cy.get('.euiFlexItem .euiFormRow [placeholder="Description"]').click().type('This is the description for Tree Map'); + cy.get('.euiFormControlLayoutIcons [data-test-subj ="comboBoxToggleListButton"]').eq(1).click(); + cy.get('.euiComboBoxOption__content').eq(2).click(); + cy.get('.euiFormControlLayoutIcons [data-test-subj ="comboBoxToggleListButton"]').eq(2).click(); + cy.get('.euiComboBoxOption__content').eq(1).click(); + cy.get('.euiFormControlLayoutIcons [data-test-subj ="comboBoxToggleListButton"]').eq(3).click(); + cy.get('.euiComboBoxOption__content').eq(0).click(); + cy.get('.euiIEFlexWrapFix').eq(2).contains('Treemap').should('exist'); + cy.get('#configPanel__treemap_options').contains('Tiling Algorithm').should('exist'); + cy.get('[data-test-subj = "comboBoxInput"]').eq(4).click(); + cy.get('button[name="Slice Dice"]').click(); +}; + +export const renderPieChart = () => { + querySearch(TEST_QUERIES[5].query, TEST_QUERIES[5].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').click(); + cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Pie').click(); + cy.wait(delay); + cy.get('#configPanel__panelOptions .euiFieldText').click().type('Pie chart'); + cy.get('.euiFlexItem .euiFormRow [placeholder="Description"]').click().type('This is the description for Pie chart'); + cy.get('.euiIEFlexWrapFix').eq(1).contains('Value options').should('exist'); + cy.get('[data-test-subj="comboBoxInput"]').eq(1).click(); + cy.get('[name="count()"]').eq(0).click(); + cy.get('[data-test-subj="comboBoxToggleListButton"]').eq(0).click(); + cy.get('[data-test-subj="comboBoxInput"]').eq(2).click(); +}; + +export const renderDataConfig = () => { + cy.get('.euiResizablePanel.euiResizablePanel--middle').contains('Data Cofigurations'); + cy.get('.euiTitle.euiTitle--xxsmall').eq(1).contains('Dimensions').should('exist'); + cy.get('.first-division .euiFormLabel.euiFormRow__label').eq(0).contains('Aggregation'); + cy.get('[data-test-subj="comboBoxSearchInput"]').eq(0).click(); + cy.get('.euiComboBoxOption__content').eq(2).click(); + cy.get('.first-division .euiFormLabel.euiFormRow__label').eq(1).contains('Field'); + cy.get('[data-test-subj="comboBoxSearchInput"]').eq(1).click(); + cy.get('.euiComboBoxOption__content').eq(1).click(); + cy.get('.euiFieldText[placeholder="Custom label"]').eq(0).type('Average field'); + cy.get('.euiTitle.euiTitle--xxsmall').eq(2).contains('Metrics').should('exist'); + cy.get('.first-division .euiFormLabel.euiFormRow__label').eq(0).contains('Aggregation'); + cy.get('.euiFormRow__fieldWrapper .euiComboBox').eq(2).click(); + cy.get('.euiComboBoxOption__content').eq(4).click(); + cy.get('.first-division .euiFormLabel.euiFormRow__label').eq(4).click(); + cy.get('.euiComboBoxOption__content').eq(0).click(); + cy.get('.euiFieldText[placeholder="Custom label"]').eq(1).type('Min field'); + cy.get('.euiButton__text').contains('Right').click(); + cy.get('[data-test-subj="visualizeEditorRenderButton"]').contains('Update chart').click(); + cy.get('.js-plotly-plot').should('exist'); +}; + +export const renderLineChart = () => { + landOnEventVisualizations(); + querySearch(TEST_QUERIES[5].query, TEST_QUERIES[5].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').type('Line').type('{enter}'); +}; From b802383d35bff0998d544c3b5468a5c203184027 Mon Sep 17 00:00:00 2001 From: Shankha Das Date: Fri, 24 Jun 2022 15:11:26 +0000 Subject: [PATCH 3/3] console logs removed Signed-off-by: Shankha Das --- .../public/components/visualizations/charts/maps/heatmap.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx b/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx index d6b71a0ad..c0d156905 100644 --- a/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx +++ b/dashboards-observability/public/components/visualizations/charts/maps/heatmap.tsx @@ -33,9 +33,6 @@ export const HeatMap = ({ visualizations, layout, config }: any) => { const yaxisField = visualizations.data?.rawVizData?.dataConfig?.dimensions[1]; const zMetrics = visualizations.data?.rawVizData?.dataConfig?.metrics[0]; - console.log("xaxisField", xaxisField); - console.log("yaxisField", yaxisField); - console.log("zMetrics", zMetrics); if ( isEmpty(xaxisField) || isEmpty(yaxisField) ||