diff --git a/x-pack/plugins/ml/public/application/components/color_range_legend/index.ts b/x-pack/plugins/ml/public/application/components/color_range_legend/index.ts index 8c92f47e5aa0..ec0a1d80e269 100644 --- a/x-pack/plugins/ml/public/application/components/color_range_legend/index.ts +++ b/x-pack/plugins/ml/public/application/components/color_range_legend/index.ts @@ -12,4 +12,5 @@ export { COLOR_RANGE, COLOR_RANGE_SCALE, useCurrentEuiTheme, + EuiThemeType, } from './use_color_range'; diff --git a/x-pack/plugins/ml/public/application/components/color_range_legend/use_color_range.ts b/x-pack/plugins/ml/public/application/components/color_range_legend/use_color_range.ts index f674372da678..004ef72e2f65 100644 --- a/x-pack/plugins/ml/public/application/components/color_range_legend/use_color_range.ts +++ b/x-pack/plugins/ml/public/application/components/color_range_legend/use_color_range.ts @@ -187,6 +187,8 @@ export const useColorRange = ( return scaleTypes[colorRangeScale]; }; +export type EuiThemeType = typeof euiThemeLight | typeof euiThemeDark; + export function useCurrentEuiTheme() { const uiSettings = useUiSettings(); return useMemo( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/_legend.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/_legend.scss index e49a0860d726..cdc217319014 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/_legend.scss +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/_legend.scss @@ -28,19 +28,10 @@ display: 'inline-block'; } -.mlJobMapLegend__trainedModel { - width: 0; - height: 0; - border-left: $euiSizeS solid $euiColorGhost; - border-right: $euiSizeS solid $euiColorGhost; - border-bottom: $euiSizeM solid $euiColorVis3; - display: 'inline-block'; -} - .mlJobMapLegend__sourceNode { height: $euiSizeM; width: $euiSizeM; - background-color: $euiColorLightShade; + background-color: $euiColorWarning; border: $euiBorderThin; border-radius: $euiBorderRadius; display: 'inline-block'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape.tsx index 6333af357c0a..838e1ec2f768 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape.tsx @@ -16,7 +16,8 @@ import React, { import cytoscape from 'cytoscape'; // @ts-ignore no declaration file import dagre from 'cytoscape-dagre'; -import { cytoscapeOptions } from './cytoscape_options'; +import { EuiThemeType } from '../../../../components/color_range_legend'; +import { getCytoscapeOptions } from './cytoscape_options'; cytoscape.use(dagre); @@ -25,6 +26,7 @@ export const CytoscapeContext = createContext(undefi interface CytoscapeProps { children?: ReactNode; elements: cytoscape.ElementDefinition[]; + theme: EuiThemeType; height: number; itemsDeleted: boolean; resetCy: boolean; @@ -59,8 +61,8 @@ function getLayoutOptions(width: number, height: number) { name: 'dagre', rankDir: 'LR', fit: true, - padding: 30, - spacingFactor: 0.85, + padding: 20, + spacingFactor: 0.95, boundingBox: { x1: 0, y1: 0, w: width, h: height }, }; } @@ -68,6 +70,7 @@ function getLayoutOptions(width: number, height: number) { export function Cytoscape({ children, elements, + theme, height, itemsDeleted, resetCy, @@ -75,7 +78,7 @@ export function Cytoscape({ width, }: CytoscapeProps) { const [ref, cy] = useCytoscape({ - ...cytoscapeOptions, + ...getCytoscapeOptions(theme), elements, }); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape_options.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape_options.tsx index fe0e816a2b56..9ee68675ee31 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape_options.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape_options.tsx @@ -5,11 +5,11 @@ */ import cytoscape from 'cytoscape'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; import { ANALYSIS_CONFIG_TYPE, JOB_MAP_NODE_TYPES, } from '../../../../../../common/constants/data_frame_analytics'; +import { EuiThemeType } from '../../../../components/color_range_legend'; import classificationJobIcon from './icons/ml_classification_job.svg'; import outlierDetectionJobIcon from './icons/ml_outlier_detection_job.svg'; import regressionJobIcon from './icons/ml_regression_job.svg'; @@ -24,7 +24,7 @@ const MAP_SHAPES = { } as const; type MapShapes = typeof MAP_SHAPES[keyof typeof MAP_SHAPES]; -function shapeForNode(el: cytoscape.NodeSingular): MapShapes { +function shapeForNode(el: cytoscape.NodeSingular, theme: EuiThemeType): MapShapes { const type = el.data('type'); switch (type) { case JOB_MAP_NODE_TYPES.ANALYTICS: @@ -55,7 +55,7 @@ function iconForNode(el: cytoscape.NodeSingular) { } } -function borderColorForNode(el: cytoscape.NodeSingular) { +function borderColorForNode(el: cytoscape.NodeSingular, theme: EuiThemeType) { if (el.selected()) { return theme.euiColorPrimary; } @@ -76,7 +76,7 @@ function borderColorForNode(el: cytoscape.NodeSingular) { } } -export const cytoscapeOptions: cytoscape.CytoscapeOptions = { +export const getCytoscapeOptions = (theme: EuiThemeType): cytoscape.CytoscapeOptions => ({ autoungrabify: true, boxSelectionEnabled: false, maxZoom: 3, @@ -86,10 +86,10 @@ export const cytoscapeOptions: cytoscape.CytoscapeOptions = { selector: 'node', style: { 'background-color': (el: cytoscape.NodeSingular) => - el.data('isRoot') ? theme.euiColorLightShade : theme.euiColorGhost, + el.data('isRoot') ? theme.euiColorWarning : theme.euiColorGhost, 'background-height': '60%', 'background-width': '60%', - 'border-color': (el: cytoscape.NodeSingular) => borderColorForNode(el), + 'border-color': (el: cytoscape.NodeSingular) => borderColorForNode(el, theme), 'border-style': 'solid', // @ts-ignore 'background-image': (el: cytoscape.NodeSingular) => iconForNode(el), @@ -100,7 +100,7 @@ export const cytoscapeOptions: cytoscape.CytoscapeOptions = { 'font-size': theme.euiFontSizeXS, 'min-zoomed-font-size': parseInt(theme.euiSizeL, 10), label: 'data(label)', - shape: (el: cytoscape.NodeSingular) => shapeForNode(el), + shape: (el: cytoscape.NodeSingular) => shapeForNode(el, theme), 'text-background-color': theme.euiColorLightestShade, 'text-background-opacity': 0, 'text-background-padding': theme.paddingSizes.xs, @@ -128,4 +128,4 @@ export const cytoscapeOptions: cytoscape.CytoscapeOptions = { }, }, ], -}; +}); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/legend.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/legend.tsx index 04e415eca169..31c2b12e003d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/legend.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/legend.tsx @@ -4,84 +4,145 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import React, { FC, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiListGroupItem, + EuiListGroup, + EuiPopover, + EuiText, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { JOB_MAP_NODE_TYPES } from '../../../../../../common/constants/data_frame_analytics'; +import { EuiThemeType } from '../../../../components/color_range_legend'; -export const JobMapLegend: FC = () => ( - - - - - - - - - - - - - - - - - - - - - {JOB_MAP_NODE_TYPES.TRANSFORM} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const getJobTypeList = () => ( + <> + + + + + + + + ); + +export const JobMapLegend: FC<{ theme: EuiThemeType }> = ({ theme }) => { + const [showJobTypes, setShowJobTypes] = useState(false); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {JOB_MAP_NODE_TYPES.TRANSFORM} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + setShowJobTypes(!showJobTypes)} + iconType={showJobTypes ? 'arrowUp' : 'arrowDown'} + aria-label={i18n.translate( + 'xpack.ml.dataframe.analyticsMap.legend.showJobTypesAriaLabel', + { + defaultMessage: 'Show job types', + } + )} + /> + } + isOpen={showJobTypes} + closePopover={() => setShowJobTypes(false)} + > + {getJobTypeList()} + + + + + + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/job_map.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/job_map.tsx index 7ca56617ab81..0c314d099015 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/job_map.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/job_map.tsx @@ -5,7 +5,6 @@ */ import React, { FC, useEffect, useState } from 'react'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; @@ -13,11 +12,12 @@ import { Cytoscape, Controls, JobMapLegend } from './components'; import { useMlKibana, useMlUrlGenerator } from '../../../contexts/kibana'; import { JOB_MAP_NODE_TYPES } from '../../../../../common/constants/data_frame_analytics'; import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { useCurrentEuiTheme, EuiThemeType } from '../../../components/color_range_legend'; import { useRefDimensions } from './components/use_ref_dimensions'; import { useFetchAnalyticsMapData } from './use_fetch_analytics_map_data'; import { JobMapTitle } from './job_map_title'; -const cytoscapeDivStyle = { +const getCytoscapeDivStyle = (theme: EuiThemeType) => ({ background: `linear-gradient( 90deg, ${theme.euiPageBackgroundColor} @@ -35,7 +35,7 @@ ${theme.euiColorLightShade}`, backgroundSize: `${theme.euiSizeL} ${theme.euiSizeL}`, margin: `-${theme.gutterTypes.gutterLarge}`, marginTop: 0, -}; +}); interface Props { analyticsId?: string; @@ -64,6 +64,7 @@ export const JobMap: FC = ({ analyticsId, modelId }) => { }, } = useMlKibana(); const urlGenerator = useMlUrlGenerator(); + const { euiTheme } = useCurrentEuiTheme(); const redirectToAnalyticsManagementPage = async () => { const url = await urlGenerator.createUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE }); @@ -139,7 +140,7 @@ export const JobMap: FC = ({ analyticsId, modelId }) => { - + @@ -174,12 +175,16 @@ export const JobMap: FC = ({ analyticsId, modelId }) => { -
+