From c3d25c868b7bc3d10fec16b2bac4fdb481576a30 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Wed, 30 Jun 2021 17:41:48 +0100 Subject: [PATCH 1/7] [ML] Fixing missing data visualizer links --- .../data_visualizer/public/api/index.ts | 4 +- .../common/components/results_links/index.ts | 2 +- .../results_links/results_links.tsx | 38 +++++++++++ .../file_data_visualizer_view.js | 1 + .../components/import_view/import_view.js | 1 + .../file_data_visualizer.tsx | 8 ++- .../file_based/file_datavisualizer.tsx | 63 +++++++++++++++++-- 7 files changed, 109 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/data_visualizer/public/api/index.ts b/x-pack/plugins/data_visualizer/public/api/index.ts index 746b43ac86e30..83282a7b0e1ce 100644 --- a/x-pack/plugins/data_visualizer/public/api/index.ts +++ b/x-pack/plugins/data_visualizer/public/api/index.ts @@ -8,9 +8,9 @@ import { lazyLoadModules } from '../lazy_load_bundle'; import type { FileDataVisualizerSpec, IndexDataVisualizerSpec } from '../application'; -export async function getFileDataVisualizerComponent(): Promise { +export async function getFileDataVisualizerComponent(): Promise<() => FileDataVisualizerSpec> { const modules = await lazyLoadModules(); - return modules.FileDataVisualizer; + return () => modules.FileDataVisualizer; } export async function getIndexDataVisualizerComponent(): Promise { const modules = await lazyLoadModules(); diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/index.ts b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/index.ts index 59cb9df6f9ce6..1dca4b7bf2254 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/index.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { ResultsLinks } from './results_links'; +export { ResultsLinks, ResultLink } from './results_links'; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx index a674446397db9..cbe75deff2725 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx @@ -18,6 +18,18 @@ import { FindFileStructureResponse } from '../../../../../../file_upload/common' import type { FileUploadPluginStart } from '../../../../../../file_upload/public'; import { useDataVisualizerKibana } from '../../../kibana_context'; +type LinkType = 'file' | 'index'; + +export interface ResultLink { + id: string; + type: LinkType; + title: string; + icon: string; + description: string; + getUrl(params?: any): Promise; + canDisplay(params?: any): boolean; +} + interface Props { fieldStats: FindFileStructureResponse['field_stats']; index: string; @@ -25,6 +37,7 @@ interface Props { timeFieldName?: string; createIndexPattern: boolean; showFilebeatFlyout(): void; + additionalLinks: ResultLink[]; } interface GlobalState { @@ -41,6 +54,7 @@ export const ResultsLinks: FC = ({ timeFieldName, createIndexPattern, showFilebeatFlyout, + additionalLinks, }) => { const { services: { fileUpload }, @@ -55,6 +69,7 @@ export const ResultsLinks: FC = ({ const [discoverLink, setDiscoverLink] = useState(''); const [indexManagementLink, setIndexManagementLink] = useState(''); const [indexPatternManagementLink, setIndexPatternManagementLink] = useState(''); + const [generatedLinks, setGeneratedLinks] = useState>({}); const { services: { @@ -100,6 +115,16 @@ export const ResultsLinks: FC = ({ getDiscoverUrl(); + Promise.all(additionalLinks.map(({ getUrl }) => getUrl({ globalState, indexPatternId }))).then( + (urls) => { + const linksById = urls.reduce((acc, url, i) => { + acc[additionalLinks[i].id] = url; + return acc; + }, {} as Record); + setGeneratedLinks(linksById); + } + ); + if (!unmounted) { setIndexManagementLink( getUrlForApp('management', { path: '/data/index_management/indices' }) @@ -231,6 +256,19 @@ export const ResultsLinks: FC = ({ onClick={showFilebeatFlyout} /> + {additionalLinks + .filter(({ canDisplay }) => canDisplay()) + .map((link) => ( + + } + data-test-subj="fileDataVisLink-" + title={link.title} + description={link.description} + href={generatedLinks[link.id]} + /> + + ))} ); }; diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js index 99b6ef602985f..054416ad7ba36 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js @@ -372,6 +372,7 @@ export class FileDataVisualizerView extends Component { hideBottomBar={this.hideBottomBar} savedObjectsClient={this.savedObjectsClient} fileUpload={this.props.fileUpload} + resultsLinks={this.props.resultsLinks} /> {bottomBarVisible && ( diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js index 74a3638f555d0..0a64a20f79f80 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js @@ -601,6 +601,7 @@ export class ImportView extends Component { timeFieldName={timeFieldName} createIndexPattern={createIndexPattern} showFilebeatFlyout={this.showFilebeatFlyout} + additionalLinks={this.props.resultsLinks ?? []} /> {isFilebeatFlyoutVisible && ( diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx index b3f7e8531ebf5..3644f7053f1e8 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx @@ -11,9 +11,14 @@ import { getCoreStart, getPluginsStart } from '../../kibana_services'; // @ts-ignore import { FileDataVisualizerView } from './components/file_data_visualizer_view/index'; +import { ResultLink } from '../common/components/results_links'; + +interface Props { + additionalLinks?: ResultLink[]; +} export type FileDataVisualizerSpec = typeof FileDataVisualizer; -export const FileDataVisualizer: FC = () => { +export const FileDataVisualizer: FC = ({ additionalLinks }) => { const coreStart = getCoreStart(); const { data, maps, embeddable, share, security, fileUpload } = getPluginsStart(); const services = { @@ -33,6 +38,7 @@ export const FileDataVisualizer: FC = () => { savedObjectsClient={coreStart.savedObjects.client} http={coreStart.http} fileUpload={fileUpload} + resultsLinks={additionalLinks} /> ); diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx index 0e9eeda51f786..a3508fb27017d 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx @@ -5,22 +5,77 @@ * 2.0. */ -import React, { FC, Fragment, useState, useEffect } from 'react'; +import React, { FC, Fragment, useState, useEffect, useMemo } from 'react'; import { useTimefilter } from '../../contexts/kibana'; import { NavigationMenu } from '../../components/navigation_menu'; import { HelpMenu } from '../../components/help_menu'; -import { useMlKibana } from '../../contexts/kibana'; +import { useMlKibana, useMlUrlGenerator } from '../../contexts/kibana'; + +import { ML_PAGES } from '../../../../common/constants/ml_url_generator'; +import { isFullLicense } from '../../license'; +import { mlNodesAvailable, getMlNodeCount } from '../../ml_nodes_check/check_ml_nodes'; +import { checkPermission } from '../../capabilities/check_capabilities'; + +interface GetUrlParams { + indexPatternId: string; + globalState: any; +} export const FileDataVisualizerPage: FC = () => { useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); const { services: { docLinks, dataVisualizer }, } = useMlKibana(); - const [FileDataVisualizer, setFileDataVisualizer] = useState | null>(null); + const mlUrlGenerator = useMlUrlGenerator(); + getMlNodeCount(); + const [FileDataVisualizer, setFileDataVisualizer] = useState(null); + + const links = useMemo( + () => [ + { + id: 'create_ml_job', + title: 'Create new ML job', + description: '', + icon: 'machineLearningApp', + type: 'file', + getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { + return await mlUrlGenerator.createUrl({ + page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE, + pageState: { + index: indexPatternId, + globalState, + }, + }); + }, + canDisplay: () => { + return isFullLicense() && checkPermission('canCreateJob') && mlNodesAvailable(); + }, + }, + { + id: 'open_in_data_viz', + title: 'Open in Data Visualizer', + description: '', + icon: 'dataVisualizer', + type: 'file', + getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { + return await mlUrlGenerator.createUrl({ + page: ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER, + pageState: { + index: indexPatternId, + globalState, + }, + }); + }, + canDisplay: () => true, + }, + ], + [] + ); useEffect(() => { if (dataVisualizer !== undefined) { + getMlNodeCount(); const { getFileDataVisualizerComponent } = dataVisualizer; getFileDataVisualizerComponent().then(setFileDataVisualizer); } @@ -29,7 +84,7 @@ export const FileDataVisualizerPage: FC = () => { return ( - {FileDataVisualizer} + {FileDataVisualizer !== null && } ); From aaca0b23a93daafa54596cea80bc9cf9dbfee309 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 1 Jul 2021 14:53:45 +0100 Subject: [PATCH 2/7] adding index dataviz links --- .../data_visualizer/public/api/index.ts | 5 +- .../results_links/results_links.tsx | 27 +++--- .../actions_panel/actions_panel.tsx | 52 ++++++++++- .../index_data_visualizer_view.tsx | 5 +- .../index_data_visualizer.tsx | 7 +- .../plugins/data_visualizer/public/index.ts | 7 +- .../file_based/file_datavisualizer.tsx | 20 +++-- .../index_based/index_data_visualizer.tsx | 90 +++++++++++++++++-- 8 files changed, 181 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/data_visualizer/public/api/index.ts b/x-pack/plugins/data_visualizer/public/api/index.ts index 83282a7b0e1ce..3b96e4caad340 100644 --- a/x-pack/plugins/data_visualizer/public/api/index.ts +++ b/x-pack/plugins/data_visualizer/public/api/index.ts @@ -12,7 +12,8 @@ export async function getFileDataVisualizerComponent(): Promise<() => FileDataVi const modules = await lazyLoadModules(); return () => modules.FileDataVisualizer; } -export async function getIndexDataVisualizerComponent(): Promise { + +export async function getIndexDataVisualizerComponent(): Promise<() => IndexDataVisualizerSpec> { const modules = await lazyLoadModules(); - return modules.IndexDataVisualizer; + return () => modules.IndexDataVisualizer; } diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx index cbe75deff2725..03fda1b1aa27c 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx @@ -27,7 +27,7 @@ export interface ResultLink { icon: string; description: string; getUrl(params?: any): Promise; - canDisplay(params?: any): boolean; + canDisplay(params?: any): Promise; } interface Props { @@ -115,15 +115,22 @@ export const ResultsLinks: FC = ({ getDiscoverUrl(); - Promise.all(additionalLinks.map(({ getUrl }) => getUrl({ globalState, indexPatternId }))).then( - (urls) => { - const linksById = urls.reduce((acc, url, i) => { + Promise.all( + additionalLinks.map(async ({ canDisplay, getUrl }) => { + if ((await canDisplay()) === false) { + return null; + } + return getUrl({ globalState, indexPatternId }); + }) + ).then((urls) => { + const linksById = urls.reduce((acc, url, i) => { + if (url !== null) { acc[additionalLinks[i].id] = url; - return acc; - }, {} as Record); - setGeneratedLinks(linksById); - } - ); + } + return acc; + }, {} as Record); + setGeneratedLinks(linksById); + }); if (!unmounted) { setIndexManagementLink( @@ -257,7 +264,7 @@ export const ResultsLinks: FC = ({ /> {additionalLinks - .filter(({ canDisplay }) => canDisplay()) + .filter(({ id }) => generatedLinks[id] !== undefined) .map((link) => ( = ({ indexPattern, searchString, searchQueryLanguage }) => { +export const ActionsPanel: FC = ({ + indexPattern, + searchString, + searchQueryLanguage, + additionalLinks, +}) => { const [globalState] = useUrlState('_g'); const [discoverLink, setDiscoverLink] = useState(''); + const [generatedLinks, setGeneratedLinks] = useState>({}); + const { services: { application: { capabilities }, @@ -76,17 +85,56 @@ export const ActionsPanel: FC = ({ indexPattern, searchString, searchQuer } }; + Promise.all( + additionalLinks.map(async ({ canDisplay, getUrl }) => { + if ((await canDisplay()) === false) { + return null; + } + return getUrl({ globalState, indexPatternId }); + }) + ).then((urls) => { + const linksById = urls.reduce((acc, url, i) => { + if (url !== null) { + acc[additionalLinks[i].id] = url; + } + return acc; + }, {} as Record); + setGeneratedLinks(linksById); + }); + getDiscoverUrl(); return () => { unmounted = true; }; - }, [indexPattern, searchString, searchQueryLanguage, globalState, capabilities, getUrlGenerator]); + }, [ + indexPattern, + searchString, + searchQueryLanguage, + globalState, + capabilities, + getUrlGenerator, + additionalLinks, + ]); // Note we use display:none for the DataRecognizer section as it needs to be // passed the recognizerResults object, and then run the recognizer check which // controls whether the recognizer section is ultimately displayed. return (
+ {additionalLinks + .filter(({ id }) => generatedLinks[id] !== undefined) + .map((link) => ( + <> + + + + ))} {discoverLink && ( <> diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx index b116b25670ad2..c9ae3cf7f69a7 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx @@ -67,6 +67,7 @@ import { HelpMenu } from '../../../common/components/help_menu'; import { TimeBuckets } from '../../services/time_buckets'; import { extractSearchData } from '../../utils/saved_search_utils'; import { DataVisualizerIndexPatternManagement } from '../index_pattern_management'; +import { ResultLink } from '../../../common/components/results_links'; interface DataVisualizerPageState { overallStats: OverallStats; @@ -120,6 +121,7 @@ export const getDefaultDataVisualizerListState = (): Required = (dataVi dataVisualizerProps.currentSavedSearch ); - const { currentIndexPattern } = dataVisualizerProps; + const { currentIndexPattern, additionalLinks } = dataVisualizerProps; useEffect(() => { if (dataVisualizerProps?.currentSavedSearch !== undefined) { @@ -886,6 +888,7 @@ export const IndexDataVisualizerView: FC = (dataVi indexPattern={currentIndexPattern} searchQueryLanguage={searchQueryLanguage} searchString={searchString} + additionalLinks={additionalLinks ?? []} /> diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx index f9e9aece48a06..8e0230a9bc6f9 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx @@ -30,15 +30,18 @@ import { } from '../common/util/url_state'; import { useDataVisualizerKibana } from '../kibana_context'; import { IndexPattern } from '../../../../../../src/plugins/data/common/index_patterns/index_patterns'; +import { ResultLink } from '../common/components/results_links'; export type IndexDataVisualizerSpec = typeof IndexDataVisualizer; export interface DataVisualizerUrlStateContextProviderProps { IndexDataVisualizerComponent: FC; + additionalLinks: ResultLink[]; } export const DataVisualizerUrlStateContextProvider: FC = ({ IndexDataVisualizerComponent, + additionalLinks, }) => { const { services: { @@ -168,6 +171,7 @@ export const DataVisualizerUrlStateContextProvider: FC ) : (
@@ -176,7 +180,7 @@ export const DataVisualizerUrlStateContextProvider: FC { +export const IndexDataVisualizer: FC<{ additionalLinks: ResultLink[] }> = ({ additionalLinks }) => { const coreStart = getCoreStart(); const { data, @@ -204,6 +208,7 @@ export const IndexDataVisualizer: FC = () => { ); diff --git a/x-pack/plugins/data_visualizer/public/index.ts b/x-pack/plugins/data_visualizer/public/index.ts index b0a622dfe490b..1a045f144c015 100644 --- a/x-pack/plugins/data_visualizer/public/index.ts +++ b/x-pack/plugins/data_visualizer/public/index.ts @@ -13,4 +13,9 @@ export function plugin() { export { DataVisualizerPluginStart } from './plugin'; -export type { IndexDataVisualizerViewProps } from './application'; +export type { + FileDataVisualizerSpec, + IndexDataVisualizerSpec, + IndexDataVisualizerViewProps, +} from './application'; +export type { ResultLink } from './application/common/components/results_links'; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx index a3508fb27017d..6adb4ad2bd9fc 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx @@ -6,7 +6,7 @@ */ import React, { FC, Fragment, useState, useEffect, useMemo } from 'react'; - +import { i18n } from '@kbn/i18n'; import { useTimefilter } from '../../contexts/kibana'; import { NavigationMenu } from '../../components/navigation_menu'; import { HelpMenu } from '../../components/help_menu'; @@ -16,6 +16,7 @@ import { ML_PAGES } from '../../../../common/constants/ml_url_generator'; import { isFullLicense } from '../../license'; import { mlNodesAvailable, getMlNodeCount } from '../../ml_nodes_check/check_ml_nodes'; import { checkPermission } from '../../capabilities/check_capabilities'; +import type { ResultLink, FileDataVisualizerSpec } from '../../../../../data_visualizer/public'; interface GetUrlParams { indexPatternId: string; @@ -29,13 +30,16 @@ export const FileDataVisualizerPage: FC = () => { } = useMlKibana(); const mlUrlGenerator = useMlUrlGenerator(); getMlNodeCount(); - const [FileDataVisualizer, setFileDataVisualizer] = useState(null); - const links = useMemo( + const [FileDataVisualizer, setFileDataVisualizer] = useState(null); + + const links: ResultLink[] = useMemo( () => [ { id: 'create_ml_job', - title: 'Create new ML job', + title: i18n.translate('xpack.ml.fileDatavisualizer.actionsPanel.anomalyDetectionTitle', { + defaultMessage: 'Create new ML job', + }), description: '', icon: 'machineLearningApp', type: 'file', @@ -48,13 +52,15 @@ export const FileDataVisualizerPage: FC = () => { }, }); }, - canDisplay: () => { + canDisplay: async () => { return isFullLicense() && checkPermission('canCreateJob') && mlNodesAvailable(); }, }, { id: 'open_in_data_viz', - title: 'Open in Data Visualizer', + title: i18n.translate('xpack.ml.fileDatavisualizer.actionsPanel.dataframeTitle', { + defaultMessage: 'Open in Data Visualizer', + }), description: '', icon: 'dataVisualizer', type: 'file', @@ -67,7 +73,7 @@ export const FileDataVisualizerPage: FC = () => { }, }); }, - canDisplay: () => true, + canDisplay: async () => true, }, ], [] diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx index af803d32e5139..8549fb16db6b9 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx @@ -5,20 +5,34 @@ * 2.0. */ -import React, { FC, Fragment, useEffect, useState } from 'react'; -import { useMlKibana, useTimefilter } from '../../contexts/kibana'; +import React, { FC, Fragment, useEffect, useState, useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; +import { useMlKibana, useTimefilter, useMlUrlGenerator } from '../../contexts/kibana'; import { NavigationMenu } from '../../components/navigation_menu'; import { HelpMenu } from '../../components/help_menu'; -import type { IndexDataVisualizerViewProps } from '../../../../../data_visualizer/public'; +import { ML_PAGES } from '../../../../common/constants/ml_url_generator'; +import { isFullLicense } from '../../license'; +import { mlNodesAvailable, getMlNodeCount } from '../../ml_nodes_check/check_ml_nodes'; +import { checkPermission } from '../../capabilities/check_capabilities'; + +import type { ResultLink, IndexDataVisualizerSpec } from '../../../../../data_visualizer/public'; + +interface GetUrlParams { + indexPatternId: string; + globalState: any; +} + export const IndexDataVisualizerPage: FC = () => { useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); const { services: { docLinks, dataVisualizer }, } = useMlKibana(); - const [ - IndexDataVisualizer, - setIndexDataVisualizer, - ] = useState | null>(null); + const mlUrlGenerator = useMlUrlGenerator(); + getMlNodeCount(); + + const [IndexDataVisualizer, setIndexDataVisualizer] = useState( + null + ); useEffect(() => { if (dataVisualizer !== undefined) { @@ -26,10 +40,70 @@ export const IndexDataVisualizerPage: FC = () => { getIndexDataVisualizerComponent().then(setIndexDataVisualizer); } }, []); + + const links: ResultLink[] = useMemo( + () => [ + { + id: 'create_ml_ad_job', + title: i18n.translate('xpack.ml.indexDatavisualizer.actionsPanel.anomalyDetectionTitle', { + defaultMessage: 'Advanced anomaly detection', + }), + description: i18n.translate( + 'xpack.ml.indexDatavisualizer.actionsPanel.anomalyDetectionDescription', + { + defaultMessage: + 'Create a job with the full range of options for more advanced use cases.', + } + ), + icon: 'createAdvancedJob', + type: 'file', + getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { + return await mlUrlGenerator.createUrl({ + page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED, + pageState: { + index: indexPatternId, + globalState, + }, + }); + }, + canDisplay: async () => { + return isFullLicense() && checkPermission('canCreateJob') && mlNodesAvailable(); + }, + }, + { + id: 'create_ml_dfa_job', + title: i18n.translate('xpack.ml.indexDatavisualizer.actionsPanel.dataframeTitle', { + defaultMessage: 'Data frame analytics', + }), + description: i18n.translate( + 'xpack.ml.indexDatavisualizer.actionsPanel.dataframeDescription', + { + defaultMessage: 'Create outlier detection, regression, or classification analytics.', + } + ), + icon: 'classificationJob', + type: 'file', + getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { + return await mlUrlGenerator.createUrl({ + page: ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB, + pageState: { + index: indexPatternId, + globalState, + }, + }); + }, + canDisplay: async () => { + return isFullLicense() && checkPermission('canCreateJob') && mlNodesAvailable(); + }, + }, + ], + [] + ); + return IndexDataVisualizer ? ( - {IndexDataVisualizer} + {IndexDataVisualizer !== null && } ) : ( From ab143b6008755263b329c1f80688564a4eb493a7 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 1 Jul 2021 15:29:26 +0100 Subject: [PATCH 3/7] fixing permission --- .../datavisualizer/index_based/index_data_visualizer.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx index 8549fb16db6b9..53bc68b568c54 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx @@ -93,7 +93,9 @@ export const IndexDataVisualizerPage: FC = () => { }); }, canDisplay: async () => { - return isFullLicense() && checkPermission('canCreateJob') && mlNodesAvailable(); + return ( + isFullLicense() && checkPermission('canCreateDataFrameAnalytics') && mlNodesAvailable() + ); }, }, ], From 7304780cabd39271a9b99abca627e4ce514ee9cc Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 1 Jul 2021 17:37:42 +0100 Subject: [PATCH 4/7] re-enabling tests --- .../filebeat_config_flyout.tsx | 7 ++- .../results_links/results_links.tsx | 1 + .../actions_panel/actions_panel.tsx | 3 +- .../index_based/index_data_visualizer.tsx | 2 + .../data_visualizer/file_data_visualizer.ts | 3 ++ .../index_data_visualizer_actions_panel.ts | 52 ++++++++++--------- .../apps/ml/permissions/full_ml_access.ts | 13 +++-- .../apps/ml/permissions/read_ml_access.ts | 9 ++-- .../services/ml/data_visualizer_file_based.ts | 5 ++ .../apps/ml/permissions/full_ml_access.ts | 9 ++-- .../apps/ml/permissions/read_ml_access.ts | 10 ++-- 11 files changed, 61 insertions(+), 53 deletions(-) diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx index 6c9df5cf2eba7..e43199fabf76c 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx @@ -73,7 +73,12 @@ export const FilebeatConfigFlyout: FC = ({ - + ; canDisplay(params?: any): Promise; + dataTestSubj?: string; } interface Props { diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx index 44563694ba587..32b0327d49218 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx @@ -27,7 +27,6 @@ interface Props { additionalLinks: ResultLink[]; } -// @todo: Add back create job card in a follow up PR export const ActionsPanel: FC = ({ indexPattern, searchString, @@ -130,7 +129,7 @@ export const ActionsPanel: FC = ({ icon={link.icon} description={link.description} title={link.title} - // data-test-subj="dataVisualizerViewInDiscoverCard" + data-test-subj={link.dataTestSubj} /> diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx index 53bc68b568c54..15a80bdc51c9f 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx @@ -69,6 +69,7 @@ export const IndexDataVisualizerPage: FC = () => { canDisplay: async () => { return isFullLicense() && checkPermission('canCreateJob') && mlNodesAvailable(); }, + dataTestSubj: 'dataVisualizerCreateAdvancedJobCard', }, { id: 'create_ml_dfa_job', @@ -97,6 +98,7 @@ export const IndexDataVisualizerPage: FC = () => { isFullLicense() && checkPermission('canCreateDataFrameAnalytics') && mlNodesAvailable() ); }, + dataTestSubj: 'dataVisualizerCreateDataFrameAnalyticsCard', }, ], [] diff --git a/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts b/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts index 3867ed6f7dfea..dee5b5a5e31c0 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts @@ -273,6 +273,9 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('creates filebeat config'); await ml.dataVisualizerFileBased.selectCreateFilebeatConfig(); + + await ml.testExecution.logTestStep('closes filebeat config'); + await ml.dataVisualizerFileBased.closeCreateFilebeatConfig(); }); }); } diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_actions_panel.ts b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_actions_panel.ts index 93e3b67ca1565..54d7b6ac294d1 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_actions_panel.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_actions_panel.ts @@ -15,16 +15,21 @@ export default function ({ getService }: FtrProviderContext) { this.tags(['mlqa']); const indexPatternName = 'ft_farequote'; - // @TODO: Re-enable in follow up - // const advancedJobWizardDatafeedQuery = `{ - // "bool": { - // "must": [ - // { - // "match_all": {} - // } - // ] - // } - // }`; // Note query is not currently passed to the wizard + + const advancedJobWizardDatafeedQuery = JSON.stringify( + { + bool: { + must: [ + { + match_all: {}, + }, + ], + }, + }, + null, + 2 + ); + // Note query is not currently passed to the wizard before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote'); @@ -48,20 +53,19 @@ export default function ({ getService }: FtrProviderContext) { await ml.jobSourceSelection.selectSourceForIndexBasedDataVisualizer(indexPatternName); }); - // @TODO: Re-enable in follow up - // it('opens the advanced job wizard', async () => { - // await ml.testExecution.logTestStep('displays the actions panel with advanced job card'); - // await ml.dataVisualizerIndexBased.assertActionsPanelExists(); - // await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardExists(); - // await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardExists(); - // - // // Note the search is not currently passed to the wizard, just the index. - // await ml.testExecution.logTestStep('displays the actions panel with advanced job card'); - // await ml.dataVisualizerIndexBased.clickCreateAdvancedJobButton(); - // await ml.jobTypeSelection.assertAdvancedJobWizardOpen(); - // await ml.jobWizardAdvanced.assertDatafeedQueryEditorExists(); - // await ml.jobWizardAdvanced.assertDatafeedQueryEditorValue(advancedJobWizardDatafeedQuery); - // }); + it('opens the advanced job wizard', async () => { + await ml.testExecution.logTestStep('displays the actions panel with advanced job card'); + await ml.dataVisualizerIndexBased.assertActionsPanelExists(); + await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardExists(); + await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardExists(); + + // Note the search is not currently passed to the wizard, just the index. + await ml.testExecution.logTestStep('displays the actions panel with advanced job card'); + await ml.dataVisualizerIndexBased.clickCreateAdvancedJobButton(); + await ml.jobTypeSelection.assertAdvancedJobWizardOpen(); + await ml.jobWizardAdvanced.assertDatafeedQueryEditorExists(); + await ml.jobWizardAdvanced.assertDatafeedQueryEditorValue(advancedJobWizardDatafeedQuery); + }); }); describe('view in discover page action', function () { diff --git a/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts b/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts index 18f4f6a38a7b1..10b57de911a10 100644 --- a/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts +++ b/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts @@ -93,8 +93,8 @@ export default function ({ getService }: FtrProviderContext) { const ecIndexPattern = 'ft_module_sample_ecommerce'; const ecExpectedTotalCount = '287'; - // @TODO: Re-enable in follow up - // const ecExpectedModuleId = 'sample_data_ecommerce'; + + const ecExpectedModuleId = 'sample_data_ecommerce'; const uploadFilePath = path.join( __dirname, @@ -365,11 +365,10 @@ export default function ({ getService }: FtrProviderContext) { } await ml.dataVisualizerIndexBased.assertViewInDiscoverCard(testUser.discoverAvailable); - // @TODO: Re-enable in follow up - // await ml.testExecution.logTestStep('should display job cards'); - // await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardExists(); - // await ml.dataVisualizerIndexBased.assertRecognizerCardExists(ecExpectedModuleId); - // await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardExists(); + await ml.testExecution.logTestStep('should display job cards'); + await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardExists(); + await ml.dataVisualizerIndexBased.assertRecognizerCardExists(ecExpectedModuleId); + await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardExists(); }); it('should display elements on File Data Visualizer page correctly', async () => { diff --git a/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts b/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts index a53ed2fafe30c..920d82ed381c0 100644 --- a/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts +++ b/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts @@ -94,7 +94,6 @@ export default function ({ getService }: FtrProviderContext) { const ecIndexPattern = 'ft_module_sample_ecommerce'; const ecExpectedTotalCount = '287'; - // const ecExpectedModuleId = 'sample_data_ecommerce'; const uploadFilePath = path.join( __dirname, @@ -357,11 +356,9 @@ export default function ({ getService }: FtrProviderContext) { } await ml.dataVisualizerIndexBased.assertViewInDiscoverCard(testUser.discoverAvailable); - // @TODO: Re-enable in follow up - // await ml.testExecution.logTestStep('should not display job cards'); - // await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists(); - // await ml.dataVisualizerIndexBased.assertRecognizerCardNotExists(ecExpectedModuleId); - // await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardNotExists(); + await ml.testExecution.logTestStep('should not display job cards'); + await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists(); + await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardNotExists(); }); it('should display elements on File Data Visualizer page correctly', async () => { diff --git a/x-pack/test/functional/services/ml/data_visualizer_file_based.ts b/x-pack/test/functional/services/ml/data_visualizer_file_based.ts index 291e5a8964553..783be207baf22 100644 --- a/x-pack/test/functional/services/ml/data_visualizer_file_based.ts +++ b/x-pack/test/functional/services/ml/data_visualizer_file_based.ts @@ -139,5 +139,10 @@ export function MachineLearningDataVisualizerFileBasedProvider( await testSubjects.click('fileDataVisFilebeatConfigLink'); await testSubjects.existOrFail('fileDataVisFilebeatConfigPanel'); }, + + async closeCreateFilebeatConfig() { + await testSubjects.click('fileBeatConfigFlyoutCloseButton'); + await testSubjects.missingOrFail('fileDataVisFilebeatConfigPanel'); + }, }; } diff --git a/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts b/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts index aff1402f5567e..901744719144c 100644 --- a/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts +++ b/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts @@ -25,7 +25,6 @@ export default function ({ getService }: FtrProviderContext) { describe(`(${testUser.user})`, function () { const ecIndexPattern = 'ft_module_sample_ecommerce'; const ecExpectedTotalCount = '287'; - // const ecExpectedModuleId = 'sample_data_ecommerce'; const uploadFilePath = path.join( __dirname, @@ -134,11 +133,9 @@ export default function ({ getService }: FtrProviderContext) { } await ml.dataVisualizerIndexBased.assertViewInDiscoverCard(testUser.discoverAvailable); - // @TODO: Re-enable in follow up - // await ml.testExecution.logTestStep('should not display job cards'); - // await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists(); - // await ml.dataVisualizerIndexBased.assertRecognizerCardNotExists(ecExpectedModuleId); - // await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardNotExists(); + await ml.testExecution.logTestStep('should not display job cards'); + await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists(); + await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardNotExists(); }); it('should display elements on File Data Visualizer page correctly', async () => { diff --git a/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts b/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts index 2e5216d722518..0f271719a0d0f 100644 --- a/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts +++ b/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts @@ -25,8 +25,6 @@ export default function ({ getService }: FtrProviderContext) { describe(`(${testUser.user})`, function () { const ecIndexPattern = 'ft_module_sample_ecommerce'; const ecExpectedTotalCount = '287'; - // @TODO: Re-enable in follow up - // const ecExpectedModuleId = 'sample_data_ecommerce'; const uploadFilePath = path.join( __dirname, @@ -135,11 +133,9 @@ export default function ({ getService }: FtrProviderContext) { } await ml.dataVisualizerIndexBased.assertViewInDiscoverCard(testUser.discoverAvailable); - // @TODO: Re-enable in follow up - // await ml.testExecution.logTestStep('should not display job cards'); - // await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists(); - // await ml.dataVisualizerIndexBased.assertRecognizerCardNotExists(ecExpectedModuleId); - // await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardNotExists(); + await ml.testExecution.logTestStep('should not display job cards'); + await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists(); + await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardNotExists(); }); it('should display elements on File Data Visualizer page correctly', async () => { From 2097f0b5909719e3c8d65734672a615f55dad9f2 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 1 Jul 2021 18:06:36 +0100 Subject: [PATCH 5/7] fixing typo --- .../common/components/results_links/results_links.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx index 2d62dd386aef5..d6ea67e0ae908 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx @@ -270,7 +270,7 @@ export const ResultsLinks: FC = ({ } - data-test-subj="fileDataVisLink-" + data-test-subj="fileDataVisLink" title={link.title} description={link.description} href={generatedLinks[link.id]} From 04879a8338c105b30f2662c8a3652234e5263407 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 5 Jul 2021 13:28:24 +0100 Subject: [PATCH 6/7] adding check for non time based index --- .../results_links/results_links.tsx | 2 +- .../actions_panel/actions_panel.tsx | 2 +- .../file_based/file_datavisualizer.tsx | 19 ++++++++++++++++--- .../index_based/index_data_visualizer.tsx | 18 +++++++++++++++--- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx index d6ea67e0ae908..24918432601b6 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx @@ -118,7 +118,7 @@ export const ResultsLinks: FC = ({ Promise.all( additionalLinks.map(async ({ canDisplay, getUrl }) => { - if ((await canDisplay()) === false) { + if ((await canDisplay({ indexPatternId })) === false) { return null; } return getUrl({ globalState, indexPatternId }); diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx index 32b0327d49218..48410aff54577 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx @@ -86,7 +86,7 @@ export const ActionsPanel: FC = ({ Promise.all( additionalLinks.map(async ({ canDisplay, getUrl }) => { - if ((await canDisplay()) === false) { + if ((await canDisplay({ indexPatternId })) === false) { return null; } return getUrl({ globalState, indexPatternId }); diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx index 6adb4ad2bd9fc..8b32336704e84 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx @@ -26,7 +26,13 @@ interface GetUrlParams { export const FileDataVisualizerPage: FC = () => { useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); const { - services: { docLinks, dataVisualizer }, + services: { + docLinks, + dataVisualizer, + data: { + indexPatterns: { get: getIndexPattern }, + }, + }, } = useMlKibana(); const mlUrlGenerator = useMlUrlGenerator(); getMlNodeCount(); @@ -52,8 +58,15 @@ export const FileDataVisualizerPage: FC = () => { }, }); }, - canDisplay: async () => { - return isFullLicense() && checkPermission('canCreateJob') && mlNodesAvailable(); + canDisplay: async ({ indexPatternId }) => { + const { timeFieldName } = await getIndexPattern(indexPatternId); + + return ( + isFullLicense() && + timeFieldName !== undefined && + checkPermission('canCreateJob') && + mlNodesAvailable() + ); }, }, { diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx index 15a80bdc51c9f..86ad497ef0b2c 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx @@ -25,7 +25,13 @@ interface GetUrlParams { export const IndexDataVisualizerPage: FC = () => { useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); const { - services: { docLinks, dataVisualizer }, + services: { + docLinks, + dataVisualizer, + data: { + indexPatterns: { get: getIndexPattern }, + }, + }, } = useMlKibana(); const mlUrlGenerator = useMlUrlGenerator(); getMlNodeCount(); @@ -66,8 +72,14 @@ export const IndexDataVisualizerPage: FC = () => { }, }); }, - canDisplay: async () => { - return isFullLicense() && checkPermission('canCreateJob') && mlNodesAvailable(); + canDisplay: async ({ indexPatternId }) => { + const { timeFieldName } = await getIndexPattern(indexPatternId); + return ( + isFullLicense() && + timeFieldName !== undefined && + checkPermission('canCreateJob') && + mlNodesAvailable() + ); }, dataTestSubj: 'dataVisualizerCreateAdvancedJobCard', }, From e8b8d1ebcf79980b7321c6052866c86d2627ad5f Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 5 Jul 2021 13:37:34 +0100 Subject: [PATCH 7/7] catching possible error when getting index pattern --- .../file_based/file_datavisualizer.tsx | 19 +++++++++++-------- .../index_based/index_data_visualizer.tsx | 18 +++++++++++------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx index 8b32336704e84..37fd0a20865f7 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx @@ -59,14 +59,17 @@ export const FileDataVisualizerPage: FC = () => { }); }, canDisplay: async ({ indexPatternId }) => { - const { timeFieldName } = await getIndexPattern(indexPatternId); - - return ( - isFullLicense() && - timeFieldName !== undefined && - checkPermission('canCreateJob') && - mlNodesAvailable() - ); + try { + const { timeFieldName } = await getIndexPattern(indexPatternId); + return ( + isFullLicense() && + timeFieldName !== undefined && + checkPermission('canCreateJob') && + mlNodesAvailable() + ); + } catch (error) { + return false; + } }, }, { diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx index 86ad497ef0b2c..60b6c90370b61 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx @@ -73,13 +73,17 @@ export const IndexDataVisualizerPage: FC = () => { }); }, canDisplay: async ({ indexPatternId }) => { - const { timeFieldName } = await getIndexPattern(indexPatternId); - return ( - isFullLicense() && - timeFieldName !== undefined && - checkPermission('canCreateJob') && - mlNodesAvailable() - ); + try { + const { timeFieldName } = await getIndexPattern(indexPatternId); + return ( + isFullLicense() && + timeFieldName !== undefined && + checkPermission('canCreateJob') && + mlNodesAvailable() + ); + } catch (error) { + return false; + } }, dataTestSubj: 'dataVisualizerCreateAdvancedJobCard', },