diff --git a/dashboards-observability/common/constants/explorer.ts b/dashboards-observability/common/constants/explorer.ts index 9199fc8cd..9d52923fe 100644 --- a/dashboards-observability/common/constants/explorer.ts +++ b/dashboards-observability/common/constants/explorer.ts @@ -85,6 +85,7 @@ export const VIZ_CONTAIN_XY_AXIS = [ visChartTypes.Histogram, visChartTypes.Line, visChartTypes.Pie, + visChartTypes.Scatter, ]; // default ppl aggregation method options diff --git a/dashboards-observability/common/constants/shared.ts b/dashboards-observability/common/constants/shared.ts index d4021c350..5d381df7a 100644 --- a/dashboards-observability/common/constants/shared.ts +++ b/dashboards-observability/common/constants/shared.ts @@ -82,7 +82,8 @@ export enum visChartTypes { Text = 'text', Gauge = 'gauge', Histogram = 'histogram', - TreeMap = 'tree_map' + TreeMap = 'tree_map', + Scatter = 'scatter', } export interface ValueOptionsAxes { @@ -97,7 +98,7 @@ export interface ValueOptionsAxes { 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]; +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]; //Live tail constants export const LIVE_OPTIONS = [ @@ -150,7 +151,7 @@ export const LIVE_OPTIONS = [ export const LIVE_END_TIME ='now'; export interface DefaultChartStylesProps { - DefaultMode: string, + DefaultModeLine: string, Interpolation: string, LineWidth: number, FillOpacity: number, @@ -159,10 +160,11 @@ export interface DefaultChartStylesProps { LegendPosition: string, LabelAngle: number, DefaultSortSectors: string, + DefaultModeScatter: string, }; export const DefaultChartStyles: DefaultChartStylesProps = { - DefaultMode: 'lines', + DefaultModeLine: 'lines', Interpolation: 'spline', LineWidth: 2, FillOpacity: 40, @@ -171,6 +173,7 @@ export const DefaultChartStyles: DefaultChartStylesProps = { LegendPosition: 'v', LabelAngle: 0, DefaultSortSectors: 'largest_to_smallest', + DefaultModeScatter: 'markers' } export const FILLOPACITY_DIV_FACTOR = 200; 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 1cac93734..4dce6ebdd 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 @@ -2451,6 +2451,314 @@ 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": "Data", + "sections": Array [ + Object { + "editor": [Function], + "id": "legend", + "mapTo": "legend", + "name": "Legend", + "schemas": Array [ + Object { + "component": null, + "mapTo": "showLegend", + "name": "Show Legend", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "show", + "name": "Show", + }, + ], + "options": Array [ + Object { + "id": "show", + "name": "Show", + }, + Object { + "id": "hidden", + "name": "Hidden", + }, + ], + }, + }, + Object { + "component": null, + "mapTo": "position", + "name": "Position", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "v", + "name": "Right", + }, + ], + "options": Array [ + Object { + "id": "v", + "name": "Right", + }, + Object { + "id": "h", + "name": "Bottom", + }, + ], + }, + }, + Object { + "component": [Function], + "eleType": "input", + "mapTo": "legendSize", + "name": "Legend Size", + "title": "Legend Size", + }, + ], + }, + Object { + "editor": [Function], + "id": "chart_styles", + "mapTo": "chartStyles", + "name": "Chart styles", + "schemas": Array [ + Object { + "component": [Function], + "eleType": "buttons", + "mapTo": "style", + "name": "Mode", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "markers", + "name": "Marker", + }, + ], + "options": Array [ + Object { + "id": "lines", + "name": "Lines", + }, + Object { + "id": "markers", + "name": "Marker", + }, + Object { + "id": "lines+markers", + "name": "Lines + Markers", + }, + ], + }, + }, + Object { + "component": [Function], + "eleType": "buttons", + "mapTo": "interpolation", + "name": "Interpolation", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "spline", + "name": "Smooth", + }, + ], + "options": Array [ + Object { + "id": "linear", + "name": "Linear", + }, + Object { + "id": "spline", + "name": "Smooth", + }, + Object { + "id": "hv", + "name": "Step before", + }, + Object { + "id": "vh", + "name": "Step after", + }, + ], + }, + }, + Object { + "component": [Function], + "defaultState": 2, + "eleType": "slider", + "mapTo": "lineWidth", + "name": "Line width", + "props": Object { + "max": 10, + }, + }, + Object { + "component": [Function], + "defaultState": 40, + "eleType": "slider", + "mapTo": "fillOpacity", + "name": "Fill Opacity", + "props": Object { + "max": 100, + }, + }, + Object { + "component": [Function], + "defaultState": 5, + "eleType": "slider", + "mapTo": "pointSize", + "name": "Point Size", + "props": Object { + "max": 40, + }, + }, + Object { + "component": [Function], + "eleType": "input", + "mapTo": "labelSize", + "name": "Label Size", + "title": "Label Size", + }, + Object { + "component": [Function], + "defaultState": 0, + "eleType": "slider", + "mapTo": "rotateLabels", + "name": "Rotate labels", + "props": Object { + "max": 90, + "min": -90, + "showTicks": true, + "ticks": Array [ + Object { + "label": "-90°", + "value": -90, + }, + Object { + "label": "-45°", + "value": -45, + }, + Object { + "label": "0°", + "value": 0, + }, + Object { + "label": "45°", + "value": 45, + }, + Object { + "label": "90°", + "value": 90, + }, + ], + }, + }, + ], + }, + Object { + "editor": [Function], + "id": "color-theme", + "mapTo": "colorTheme", + "name": "Color theme", + "schemas": Array [], + }, + Object { + "defaultState": Array [], + "editor": [Function], + "id": "thresholds", + "mapTo": "thresholds", + "name": "Thresholds", + "schemas": Array [], + }, + ], + }, + Object { + "content": Array [], + "editor": [Function], + "id": "style-panel", + "mapTo": "layoutConfig", + "name": "Layout", + }, + Object { + "editor": [Function], + "id": "availability-panel", + "mapTo": "availabilityConfig", + "name": "Availability", + }, + ], + }, + "fullLabel": "Scatter", + "icon": [Function], + "iconType": "visLine", + "id": "scatter", + "label": "Scatter", + "name": "scatter", + "selection": Object { + "dataLoss": "nothing", + }, + "seriesAxis": "yaxis", + "type": "scatter", + "visConfig": Object { + "config": Object { + "barmode": "scatter", + "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" 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 27cf3379c..81e0ff8b7 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 @@ -61,7 +61,7 @@ interface PanelTabType { content?: any; } -export const ConfigPanel = ({ visualizations, setCurVisId, callback, changeIsValidConfigOptionState }: any) => { +export const ConfigPanel = ({ visualizations, setCurVisId, callback, changeIsValidConfigOptionState }: any) => { const { tabId, curVisId, dispatch, changeVisualizationConfig, setToast } = useContext( TabContext ); @@ -74,7 +74,7 @@ export const ConfigPanel = ({ visualizations, setCurVisId, callback, changeIsVal if (curVisId === visChartTypes.TreeMap) { chartBasedAxes["childField"] = data.defaultAxes.xaxis ?? []; chartBasedAxes["valueField"] = valueField && [valueField]; - } else if(curVisId === visChartTypes.HeatMap){ + } else if (curVisId === visChartTypes.HeatMap) { chartBasedAxes["zaxis"] = valueField && [valueField]; } else { chartBasedAxes = { ...data.defaultAxes }; @@ -112,8 +112,8 @@ export const ConfigPanel = ({ visualizations, setCurVisId, callback, changeIsVal [] ); - // To check, If user empty any of the value options - const isValidValueOptionConfigSelected = useMemo(() => { + // To check, If user empty any of the value options + const isValidValueOptionConfigSelected = useMemo(() => { const valueOptions = vizConfigs.dataConfig?.valueOptions; const { TreeMap, Gauge, HeatMap } = visChartTypes; const isValidValueOptionsXYAxes = VIZ_CONTAIN_XY_AXIS.includes(curVisId) && @@ -127,7 +127,8 @@ export const ConfigPanel = ({ visualizations, setCurVisId, callback, changeIsVal bar: isValidValueOptionsXYAxes, line: isValidValueOptionsXYAxes, histogram: isValidValueOptionsXYAxes, - pie: isValidValueOptionsXYAxes + pie: isValidValueOptionsXYAxes, + scatter: isValidValueOptionsXYAxes, } return isValid_valueOptions[curVisId]; }, [vizConfigs.dataConfig]); @@ -221,8 +222,13 @@ export const ConfigPanel = ({ visualizations, setCurVisId, callback, changeIsVal }; const memorizedVisualizationTypes = useMemo(() => { + let visDefinition = {} return ENABLED_VIS_TYPES.map((vs: string) => { - const visDefinition = getVisType(vs); + if (vs === visChartTypes.Line || vs === visChartTypes.Scatter) { + visDefinition = vs === visChartTypes.Line ? getVisType(vs, { type: visChartTypes.Line }) : getVisType(vs, { type: visChartTypes.Scatter }); + } else { + visDefinition = getVisType(vs); + } return { ...visDefinition, }; 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 5d85c64c0..45acd2e16 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,6 +7,7 @@ import React, { useMemo, useCallback } 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'; export const ConfigLineChartStyles = ({ visualizations, @@ -33,9 +34,18 @@ export const ConfigLineChartStyles = ({ /* To update the schema options based on current style mode selection */ const currentSchemas = useMemo(() => { - if (!vizState?.style || vizState?.style === 'lines') { + if (!vizState?.style) { + if (visualizations?.vis?.name === visChartTypes.Scatter) { + return schemas.filter((schema: IConfigPanelOptionSection) => ["style", "pointSize"].includes(schema.mapTo)); + } else { + return schemas.filter((schema: IConfigPanelOptionSection) => schema.mapTo !== 'pointSize'); + } + } + + if (vizState?.style === "lines") { return schemas.filter((schema: IConfigPanelOptionSection) => schema.mapTo !== 'pointSize'); } + if (vizState?.style === 'bar') { return schemas.filter( (schema: IConfigPanelOptionSection) => 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 5cd49891e..033339ebb 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 @@ -174,7 +174,8 @@ export const DataConfigPanelItem = ({ fieldOptionList, visualizations }: any) => }; const isPositionButtonVisible = (sectionName: string) => - sectionName === 'metrics' && visualizations.vis.name === visChartTypes.Line; + sectionName === 'metrics' && + (visualizations.vis.name === visChartTypes.Line || visualizations.vis.name === visChartTypes.Scatter); const getOptionsAvailable = (sectionName: string) => { let selectedFields = {}; 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 075082cc0..3681f34b5 100644 --- a/dashboards-observability/public/components/visualizations/charts/helpers/viz_types.ts +++ b/dashboards-observability/public/components/visualizations/charts/helpers/viz_types.ts @@ -44,9 +44,14 @@ export const getVizContainerProps = ({ userConfigs = {}, appData = {}, }: IVizContainerProps): IVisualizationContainerProps => { - const visType = { - ...getVisType(vizId), + const getVisTypeData = () => { + if (vizId === visChartTypes.Line || vizId === visChartTypes.Scatter) { + return vizId === visChartTypes.Line ? { ...getVisType(vizId, { type: visChartTypes.Line }) } : { ...getVisType(vizId, { type: visChartTypes.Scatter }) }; + } else { + return { ...getVisType(vizId) } + } } + return { data: { appData: { ...appData }, @@ -55,9 +60,11 @@ export const getVizContainerProps = ({ indexFields: { ...indexFields }, userConfigs: { ...userConfigs }, defaultAxes: { - ...getDefaultXYAxisLabels(rawVizData?.metadata?.fields, visType.name), + ...getDefaultXYAxisLabels(rawVizData?.metadata?.fields, getVisTypeData().name), }, }, - vis: visType, + vis: { + ...getVisTypeData() + }, }; }; diff --git a/dashboards-observability/public/components/visualizations/charts/lines/line.tsx b/dashboards-observability/public/components/visualizations/charts/lines/line.tsx index c2429b14f..32e95b3bd 100644 --- a/dashboards-observability/public/components/visualizations/charts/lines/line.tsx +++ b/dashboards-observability/public/components/visualizations/charts/lines/line.tsx @@ -8,25 +8,12 @@ import { take, isEmpty, last } from 'lodash'; 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, - FILLOPACITY_DIV_FACTOR, - PLOTLY_COLOR, -} from '../../../../../common/constants/shared'; +import { DefaultChartStyles, FILLOPACITY_DIV_FACTOR, PLOTLY_COLOR, visChartTypes } from '../../../../../common/constants/shared'; import { hexToRgb } from '../../../../components/event_analytics/utils/utils'; import { EmptyPlaceholder } from '../../../event_analytics/explorer/visualizations/shared_components/empty_placeholder'; export const Line = ({ visualizations, layout, config }: any) => { - const { - DefaultMode, - Interpolation, - LineWidth, - FillOpacity, - MarkerSize, - LegendPosition, - ShowLegend, - LabelAngle, - } = DefaultChartStyles; + const { DefaultModeLine, Interpolation, LineWidth, FillOpacity, MarkerSize, LegendPosition, ShowLegend, DefaultModeScatter, LabelAngle } = DefaultChartStyles; const { data = {}, metadata: { fields }, @@ -38,15 +25,14 @@ export const Line = ({ visualizations, layout, config }: any) => { availabilityConfig = {}, } = visualizations?.data?.userConfigs; - const dataConfigTab = - visualizations.data?.rawVizData?.line?.dataConfig && - visualizations.data.rawVizData.line.dataConfig; + let visType: string = visualizations.vis.name; + const dataConfigTab = visualizations.data?.rawVizData?.[visType]?.dataConfig && visualizations.data.rawVizData[visType].dataConfig; const xaxis = dataConfigTab?.dimensions ? dataConfigTab?.dimensions.filter((item) => item.label) : []; const yaxis = dataConfigTab?.metrics ? dataConfigTab?.metrics.filter((item) => item.label) : []; const lastIndex = fields.length - 1; - const mode = dataConfig?.chartStyles?.style || DefaultMode; + const mode = dataConfig?.chartStyles?.style || (visType === visChartTypes.Line ? DefaultModeLine : DefaultModeScatter); const lineShape = dataConfig?.chartStyles?.interpolation || Interpolation; const lineWidth = dataConfig?.chartStyles?.lineWidth || LineWidth; const showLegend = !( 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 9413b0322..4fa43c2ff 100644 --- a/dashboards-observability/public/components/visualizations/charts/lines/line_type.ts +++ b/dashboards-observability/public/components/visualizations/charts/lines/line_type.ts @@ -6,7 +6,6 @@ import { Line } from './line'; import { getPlotlySharedConfigs, getPlotlyCategory } from '../shared/shared_configs'; import { LensIconChartLine } from '../../assets/chart_line'; -import { PLOTLY_COLOR } from '../../../../../common/constants/shared'; import { VizDataPanel } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/default_vis_editor'; import { ConfigEditor } from '../../../event_analytics/explorer/visualizations/config_panel/config_panes/json_editor'; import { @@ -17,28 +16,19 @@ import { ConfigColorTheme } 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 } from '../../../../../common/constants/shared'; +import { DefaultChartStyles, visChartTypes, PLOTLY_COLOR } from '../../../../../common/constants/shared'; import { ButtonGroupItem } from '../../../../../public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group'; import { SliderConfig } from '../../../../../public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider'; const sharedConfigs = getPlotlySharedConfigs(); const VIS_CATEGORY = getPlotlyCategory(); -const { - DefaultMode, - Interpolation, - LineWidth, - FillOpacity, - MarkerSize, - LegendPosition, - ShowLegend, - LabelAngle -} = DefaultChartStyles; +const { DefaultModeLine, Interpolation, LineWidth, FillOpacity, MarkerSize, LegendPosition, ShowLegend, DefaultModeScatter, LabelAngle } = DefaultChartStyles; export const createLineTypeDefinition = (params: any = {}) => ({ - name: 'line', - type: 'line', - id: 'line', - label: 'Time series', - fullLabel: 'Time series', + 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', iconType: 'visLine', category: VIS_CATEGORY.BASICS, selection: { @@ -111,7 +101,7 @@ export const createLineTypeDefinition = (params: any = {}) => ({ { name: 'Marker', id: 'markers' }, { name: 'Lines + Markers', id: 'lines+markers' }, ], - defaultSelections: [{ name: 'Lines', id: DefaultMode }], + defaultSelections: [params.type === visChartTypes.Line ? { name: 'Lines', id: DefaultModeLine } : { name: 'Marker', id: DefaultModeScatter }], }, }, { @@ -241,7 +231,7 @@ export const createLineTypeDefinition = (params: any = {}) => ({ config: { ...sharedConfigs.config, ...{ - barmode: 'line', + barmode: params.type, xaxis: { automargin: true, }, diff --git a/dashboards-observability/public/components/visualizations/charts/vis_types.ts b/dashboards-observability/public/components/visualizations/charts/vis_types.ts index 0d3998547..28f6e90e5 100644 --- a/dashboards-observability/public/components/visualizations/charts/vis_types.ts +++ b/dashboards-observability/public/components/visualizations/charts/vis_types.ts @@ -27,6 +27,7 @@ export const VIS_TYPES = { heatmap: createMapsVisDefinition, tree_map: createTreeMapDefinition, text: createTextTypeDefinition, + scatter: createLineTypeDefinition }; export const getVisType = (visType: string, params: any = {}) => {