From cc6f29811102382c29c218ea870bca58cdb0bbc7 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 5 Dec 2019 17:48:26 +0000 Subject: [PATCH] fixing saved searches --- .../legacy/plugins/ml/common/types/kibana.ts | 11 +++ .../data_recognizer/data_recognizer.d.ts | 3 +- .../data_recognizer/recognized_result.js | 2 +- .../contexts/kibana/__mocks__/saved_search.ts | 27 ++++--- .../contexts/kibana/kibana_context.ts | 7 +- .../file_based/file_datavisualizer.tsx | 4 +- .../datavisualizer/index_based/page.tsx | 7 +- .../job_creator/advanced_job_creator.ts | 8 +- .../new_job/common/job_creator/job_creator.ts | 10 ++- .../common/job_creator/job_creator_factory.ts | 4 +- .../job_creator/multi_metric_job_creator.ts | 8 +- .../job_creator/population_job_creator.ts | 8 +- .../job_creator/single_metric_job_creator.ts | 8 +- .../jobs/new_job/pages/job_type/page.tsx | 40 +++++----- .../jobs/new_job/pages/new_job/page.tsx | 2 +- .../new_job/pages/new_job/wizard_steps.tsx | 4 +- .../jobs/new_job/recognize/page.tsx | 8 +- .../jobs/new_job/utils/new_job_utils.ts | 38 ++++++---- .../public/application/routing/resolvers.ts | 3 +- .../ml/public/application/routing/router.tsx | 31 ++++---- .../routing/routes/access_denied.tsx | 2 +- .../analytics_job_exploration.tsx | 2 +- .../analytics_jobs_list.tsx | 2 +- .../routes/datavisualizer/datavisualizer.tsx | 3 +- .../routes/datavisualizer/file_based.tsx | 3 +- .../routes/datavisualizer/index_based.tsx | 4 +- .../application/routing/routes/explorer.tsx | 2 +- .../application/routing/routes/jobs_list.tsx | 2 +- .../routes/new_job/index_or_search.tsx | 2 +- .../routing/routes/new_job/job_type.tsx | 4 +- .../routing/routes/new_job/recognize.tsx | 6 +- .../routing/routes/new_job/wizard.tsx | 6 +- .../application/routing/routes/overview.tsx | 2 +- .../routing/routes/settings/calendar_list.tsx | 2 +- .../routes/settings/calendar_new_edit.tsx | 2 +- .../routing/routes/settings/filter_list.tsx | 2 +- .../routes/settings/filter_list_new_edit.tsx | 2 +- .../routing/routes/settings/settings.tsx | 2 +- .../routing/routes/timeseriesexplorer.tsx | 2 +- .../services/new_job_capabilities_service.ts | 18 ++--- .../ml/public/application/util/index_utils.ts | 74 ++++++++++++++----- .../models/job_service/new_job/line_chart.ts | 4 + 42 files changed, 237 insertions(+), 144 deletions(-) diff --git a/x-pack/legacy/plugins/ml/common/types/kibana.ts b/x-pack/legacy/plugins/ml/common/types/kibana.ts index 86db2ce59d7e78b..d647bd882162b7b 100644 --- a/x-pack/legacy/plugins/ml/common/types/kibana.ts +++ b/x-pack/legacy/plugins/ml/common/types/kibana.ts @@ -6,6 +6,8 @@ // custom edits or fixes for default kibana types which are incomplete +import { SavedObjectAttributes, SimpleSavedObject } from 'kibana/public'; + export type IndexPatternTitle = string; export type callWithRequestType = (action: string, params?: any) => Promise; @@ -14,3 +16,12 @@ export interface Route { id: string; k7Breadcrumbs: () => any; } + +export type IndexPatternSavedObject = SimpleSavedObject; +export type SavedSearchSavedObject = SimpleSavedObject; + +export function isSavedSearchSavedObject( + ss: SavedSearchSavedObject | null +): ss is SavedSearchSavedObject { + return ss !== null; +} diff --git a/x-pack/legacy/plugins/ml/public/application/components/data_recognizer/data_recognizer.d.ts b/x-pack/legacy/plugins/ml/public/application/components/data_recognizer/data_recognizer.d.ts index e7d191a31e034e8..771d2e02c9d05ac 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/data_recognizer/data_recognizer.d.ts +++ b/x-pack/legacy/plugins/ml/public/application/components/data_recognizer/data_recognizer.d.ts @@ -8,10 +8,11 @@ import { FC } from 'react'; import { IndexPattern } from 'ui/index_patterns'; import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; +import { SavedSearchSavedObject } from '../../../../common/types/kibana'; declare const DataRecognizer: FC<{ indexPattern: IndexPattern; - savedSearch?: SavedSearch; + savedSearch?: SavedSearchSavedObject | null; results: { count: number; onChange?: Function; diff --git a/x-pack/legacy/plugins/ml/public/application/components/data_recognizer/recognized_result.js b/x-pack/legacy/plugins/ml/public/application/components/data_recognizer/recognized_result.js index 6f511abf89e310e..79b1b501c3829fe 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/data_recognizer/recognized_result.js +++ b/x-pack/legacy/plugins/ml/public/application/components/data_recognizer/recognized_result.js @@ -20,7 +20,7 @@ export const RecognizedResult = ({ indexPattern, savedSearch }) => { - const id = (savedSearch === undefined || savedSearch.id === undefined) ? + const id = (savedSearch === null) ? `index=${indexPattern.id}` : `savedSearchId=${savedSearch.id}`; diff --git a/x-pack/legacy/plugins/ml/public/application/contexts/kibana/__mocks__/saved_search.ts b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/__mocks__/saved_search.ts index 2bff760ed3711dd..cbbdaf410445e0f 100644 --- a/x-pack/legacy/plugins/ml/public/application/contexts/kibana/__mocks__/saved_search.ts +++ b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/__mocks__/saved_search.ts @@ -4,14 +4,23 @@ * you may not use this file except in compliance with the Elastic License. */ -import { searchSourceMock } from '../../../../../../../../../src/legacy/ui/public/courier/search_source/mocks'; -import { SearchSourceContract } from '../../../../../../../../../src/legacy/ui/public/courier'; - -export const savedSearchMock = { +export const savedSearchMock: any = { id: 'the-saved-search-id', - title: 'the-saved-search-title', - searchSource: searchSourceMock as SearchSourceContract, - columns: [], - sort: [], - destroy: () => {}, + type: 'search', + attributes: { + title: 'the-saved-search-title', + kibanaSavedObjectMeta: { + searchSourceJSON: + '{"highlightAll":true,"version":true,"query":{"query":"foo : \\"bar\\" ","language":"kuery"},"filter":[],"indexRefName":"kibanaSavedObjectMeta.searchSourceJSON.index"}', + }, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: 'the-index-pattern-id', + }, + ], + migrationVersion: { search: '7.5.0' }, + error: undefined, }; diff --git a/x-pack/legacy/plugins/ml/public/application/contexts/kibana/kibana_context.ts b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/kibana_context.ts index aed230a53f62a1b..ae4468799ae0e24 100644 --- a/x-pack/legacy/plugins/ml/public/application/contexts/kibana/kibana_context.ts +++ b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/kibana_context.ts @@ -7,9 +7,8 @@ import React from 'react'; import { KibanaConfig } from 'src/legacy/server/kbn_server'; -import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; - import { IndexPattern, IndexPatterns } from 'ui/index_patterns'; +import { SavedSearchSavedObject } from '../../../../common/types/kibana'; // set() method is missing in original d.ts export interface KibanaConfigTypeFix extends KibanaConfig { @@ -18,8 +17,8 @@ export interface KibanaConfigTypeFix extends KibanaConfig { export interface KibanaContextValue { combinedQuery: any; - currentIndexPattern: IndexPattern; - currentSavedSearch: SavedSearch; + currentIndexPattern: IndexPattern; // TODO this should be or null + currentSavedSearch: SavedSearchSavedObject | null; indexPatterns: IndexPatterns; kibanaConfig: KibanaConfigTypeFix; } diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx index 5a61e05479067eb..149e3d1818e642c 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx @@ -9,7 +9,7 @@ import { timefilter } from 'ui/timefilter'; import { KibanaConfigTypeFix } from '../../contexts/kibana'; import { NavigationMenu } from '../../components/navigation_menu'; -import { getFullIndexPatterns } from '../../util/index_utils'; +import { getIndexPatternsContract } from '../../util/index_utils'; // @ts-ignore import { FileDataVisualizerView } from './components/file_datavisualizer_view/index'; @@ -21,7 +21,7 @@ export interface FileDataVisualizerPageProps { export const FileDataVisualizerPage: FC = ({ kibanaConfig }) => { timefilter.disableTimeRangeSelector(); timefilter.disableAutoRefreshSelector(); - const indexPatterns = getFullIndexPatterns(); + const indexPatterns = getIndexPatternsContract(); return ( diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx index 99e128e95410302..898c852fe50a533 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx @@ -31,7 +31,7 @@ import { FullTimeRangeSelector } from '../../components/full_time_range_selector import { mlTimefilterRefresh$ } from '../../services/timefilter_refresh_service'; import { useKibanaContext, SavedSearchQuery } from '../../contexts/kibana'; import { kbnTypeToMLJobType } from '../../util/field_types_utils'; -import { timeBasedIndexCheck } from '../../util/index_utils'; +import { timeBasedIndexCheck, getQueryFromSavedSearch } from '../../util/index_utils'; import { TimeBuckets } from '../../util/time_buckets'; import { FieldRequestConfig, FieldVisConfig } from './common'; import { ActionsPanel } from './components/actions_panel'; @@ -173,9 +173,8 @@ export const Page: FC = () => { useEffect(() => { // Check for a saved search being passed in. - const searchSource = currentSavedSearch.searchSource; - const query = searchSource.getField('query'); - if (query !== undefined) { + if (currentSavedSearch !== null) { + const { query } = getQueryFromSavedSearch(currentSavedSearch); const queryLanguage = query.language as SEARCH_QUERY_LANGUAGE; const qryString = query.query; let qry; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts index 22aebc2b88a8864..f5dfba2315a1f66 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; import { IndexPattern } from 'ui/index_patterns'; +import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { JobCreator } from './job_creator'; import { Field, Aggregation, SplitField } from '../../../../../../common/types/fields'; @@ -32,7 +32,11 @@ export class AdvancedJobCreator extends JobCreator { private _richDetectors: RichDetector[] = []; private _queryString: string; - constructor(indexPattern: IndexPattern, savedSearch: SavedSearch, query: object) { + constructor( + indexPattern: IndexPattern, + savedSearch: SavedSearchSavedObject | null, + query: object + ) { super(indexPattern, savedSearch, query); this._queryString = JSON.stringify(this._datafeed_config.query); diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts index e11cebe0383cd20..690350f8011637d 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; import { IndexPattern } from 'ui/index_patterns'; +import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { UrlConfig } from '../../../../../../common/types/custom_urls'; import { IndexPatternTitle } from '../../../../../../common/types/kibana'; import { ML_JOB_AGGREGATION } from '../../../../../../common/constants/aggregation_types'; @@ -24,7 +24,7 @@ import { mlCalendarService } from '../../../../services/calendar_service'; export class JobCreator { protected _type: JOB_TYPE = JOB_TYPE.SINGLE_METRIC; protected _indexPattern: IndexPattern; - protected _savedSearch: SavedSearch; + protected _savedSearch: SavedSearchSavedObject | null; protected _indexPatternTitle: IndexPatternTitle = ''; protected _job_config: Job; protected _calendars: Calendar[]; @@ -44,7 +44,11 @@ export class JobCreator { stop: boolean; } = { stop: false }; - constructor(indexPattern: IndexPattern, savedSearch: SavedSearch, query: object) { + constructor( + indexPattern: IndexPattern, + savedSearch: SavedSearchSavedObject | null, + query: object + ) { this._indexPattern = indexPattern; this._savedSearch = savedSearch; this._indexPatternTitle = indexPattern.title; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator_factory.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator_factory.ts index 375e112ed46faff..abeb12fddb15969 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator_factory.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator_factory.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; import { IndexPattern } from 'ui/index_patterns'; +import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { SingleMetricJobCreator } from './single_metric_job_creator'; import { MultiMetricJobCreator } from './multi_metric_job_creator'; import { PopulationJobCreator } from './population_job_creator'; @@ -15,7 +15,7 @@ import { JOB_TYPE } from './util/constants'; export const jobCreatorFactory = (jobType: JOB_TYPE) => ( indexPattern: IndexPattern, - savedSearch: SavedSearch, + savedSearch: SavedSearchSavedObject | null, query: object ) => { let jc; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts index fea328acb58b3cc..4e61c853b1639e4 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; import { IndexPattern } from 'ui/index_patterns'; +import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { JobCreator } from './job_creator'; import { Field, @@ -26,7 +26,11 @@ export class MultiMetricJobCreator extends JobCreator { private _lastEstimatedModelMemoryLimit = DEFAULT_MODEL_MEMORY_LIMIT; protected _type: JOB_TYPE = JOB_TYPE.MULTI_METRIC; - constructor(indexPattern: IndexPattern, savedSearch: SavedSearch, query: object) { + constructor( + indexPattern: IndexPattern, + savedSearch: SavedSearchSavedObject | null, + query: object + ) { super(indexPattern, savedSearch, query); this.createdBy = CREATED_BY_LABEL.MULTI_METRIC; } diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts index 9e9ccf8ab63e42d..4e4bea0995bc711 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; import { IndexPattern } from 'ui/index_patterns'; +import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { JobCreator } from './job_creator'; import { Field, @@ -25,7 +25,11 @@ export class PopulationJobCreator extends JobCreator { private _byFields: SplitField[] = []; protected _type: JOB_TYPE = JOB_TYPE.POPULATION; - constructor(indexPattern: IndexPattern, savedSearch: SavedSearch, query: object) { + constructor( + indexPattern: IndexPattern, + savedSearch: SavedSearchSavedObject | null, + query: object + ) { super(indexPattern, savedSearch, query); this.createdBy = CREATED_BY_LABEL.POPULATION; } diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts index 5f3f6ff310d289d..ddd9a98c143d754 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; import { IndexPattern } from 'ui/index_patterns'; +import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { parseInterval } from '../../../../../../common/util/parse_interval'; import { JobCreator } from './job_creator'; import { Field, Aggregation, AggFieldPair } from '../../../../../../common/types/fields'; @@ -21,7 +21,11 @@ import { getRichDetectors } from './util/general'; export class SingleMetricJobCreator extends JobCreator { protected _type: JOB_TYPE = JOB_TYPE.SINGLE_METRIC; - constructor(indexPattern: IndexPattern, savedSearch: SavedSearch, query: object) { + constructor( + indexPattern: IndexPattern, + savedSearch: SavedSearchSavedObject | null, + query: object + ) { super(indexPattern, savedSearch, query); this.createdBy = CREATED_BY_LABEL.SINGLE_METRIC; } diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx index 4991039ffa28868..dbae1948cbe0f61 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx @@ -19,6 +19,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { useKibanaContext } from '../../../../contexts/kibana'; +import { isSavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { DataRecognizer } from '../../../../components/data_recognizer'; import { addItemToRecentlyAccessed } from '../../../../util/recently_accessed'; import { timeBasedIndexCheck } from '../../../../util/index_utils'; @@ -32,33 +33,33 @@ export const Page: FC = () => { const isTimeBasedIndex = timeBasedIndexCheck(currentIndexPattern); const indexWarningTitle = - !isTimeBasedIndex && currentSavedSearch.id === undefined - ? i18n.translate('xpack.ml.newJob.wizard.jobType.indexPatternNotTimeBasedMessage', { - defaultMessage: 'Index pattern {indexPatternTitle} is not time based', - values: { indexPatternTitle: currentIndexPattern.title }, - }) - : i18n.translate( + !isTimeBasedIndex && isSavedSearchSavedObject(currentSavedSearch) + ? i18n.translate( 'xpack.ml.newJob.wizard.jobType.indexPatternFromSavedSearchNotTimeBasedMessage', { defaultMessage: '{savedSearchTitle} uses index pattern {indexPatternTitle} which is not time based', values: { - savedSearchTitle: currentSavedSearch.title, + savedSearchTitle: currentSavedSearch.attributes.title as string, indexPatternTitle: currentIndexPattern.title, }, } - ); - const pageTitleLabel = - currentSavedSearch.id !== undefined - ? i18n.translate('xpack.ml.newJob.wizard.jobType.savedSearchPageTitleLabel', { - defaultMessage: 'saved search {savedSearchTitle}', - values: { savedSearchTitle: currentSavedSearch.title }, - }) - : i18n.translate('xpack.ml.newJob.wizard.jobType.indexPatternPageTitleLabel', { - defaultMessage: 'index pattern {indexPatternTitle}', + ) + : i18n.translate('xpack.ml.newJob.wizard.jobType.indexPatternNotTimeBasedMessage', { + defaultMessage: 'Index pattern {indexPatternTitle} is not time based', values: { indexPatternTitle: currentIndexPattern.title }, }); + const pageTitleLabel = isSavedSearchSavedObject(currentSavedSearch) + ? i18n.translate('xpack.ml.newJob.wizard.jobType.savedSearchPageTitleLabel', { + defaultMessage: 'saved search {savedSearchTitle}', + values: { savedSearchTitle: currentSavedSearch.attributes.title as string }, + }) + : i18n.translate('xpack.ml.newJob.wizard.jobType.indexPatternPageTitleLabel', { + defaultMessage: 'index pattern {indexPatternTitle}', + values: { indexPatternTitle: currentIndexPattern.title }, + }); + const recognizerResults = { count: 0, onChange() { @@ -67,14 +68,15 @@ export const Page: FC = () => { }; const getUrl = (basePath: string) => { - return currentSavedSearch.id === undefined + return !isSavedSearchSavedObject(currentSavedSearch) ? `${basePath}?index=${currentIndexPattern.id}` : `${basePath}?savedSearchId=${currentSavedSearch.id}`; }; const addSelectionToRecentlyAccessed = () => { - const title = - currentSavedSearch.id === undefined ? currentIndexPattern.title : currentSavedSearch.title; + const title = !isSavedSearchSavedObject(currentSavedSearch) + ? currentIndexPattern.title + : (currentSavedSearch.attributes.title as string); const url = getUrl(''); addItemToRecentlyAccessed('jobs/new_job/datavisualizer', title, url); diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/page.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/page.tsx index e086b2b8aad7f0b..e80781ab04d716d 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/page.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/page.tsx @@ -104,7 +104,7 @@ export const Page: FC = ({ existingJobsAndGroups, jobType }) => { jobCreator.modelPlot = true; } - if (kibanaContext.currentSavedSearch.id !== undefined) { + if (kibanaContext.currentSavedSearch !== null) { // Jobs created from saved searches cannot be cloned in the wizard as the // ML job config holds no reference to the saved search ID. jobCreator.createdBy = null; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard_steps.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard_steps.tsx index 0f4eae230acfd81..8e81c05092c98b3 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard_steps.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard_steps.tsx @@ -34,10 +34,10 @@ export const WizardSteps: FC = ({ currentStep, setCurrentStep }) => { const [additionalExpanded, setAdditionalExpanded] = useState(false); function getSummaryStepTitle() { - if (kibanaContext.currentSavedSearch.id !== undefined) { + if (kibanaContext.currentSavedSearch !== null) { return i18n.translate('xpack.ml.newJob.wizard.stepComponentWrapper.summaryTitleSavedSearch', { defaultMessage: 'New job from saved search {title}', - values: { title: kibanaContext.currentSavedSearch.title }, + values: { title: kibanaContext.currentSavedSearch.attributes.title as string }, }); } else if (kibanaContext.currentIndexPattern.id !== undefined) { return i18n.translate( diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx index 11b2a8f01342dbf..141ed5d1bbb8ff4 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx @@ -85,17 +85,17 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => { combinedQuery, } = useKibanaContext(); const pageTitle = - savedSearch.id !== undefined + savedSearch !== null ? i18n.translate('xpack.ml.newJob.recognize.savedSearchPageTitle', { defaultMessage: 'saved search {savedSearchTitle}', - values: { savedSearchTitle: savedSearch.title }, + values: { savedSearchTitle: savedSearch.attributes.title as string }, }) : i18n.translate('xpack.ml.newJob.recognize.indexPatternPageTitle', { defaultMessage: 'index pattern {indexPatternTitle}', values: { indexPatternTitle: indexPattern.title }, }); - const displayQueryWarning = savedSearch.id !== undefined; - const tempQuery = savedSearch.id === undefined ? undefined : combinedQuery; + const displayQueryWarning = savedSearch !== null; + const tempQuery = savedSearch === null ? undefined : combinedQuery; /** * Loads recognizer module configuration. diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.ts index 455fac9b532d61e..38bf260794420c7 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.ts @@ -5,14 +5,22 @@ */ import { IndexPattern } from 'ui/index_patterns'; -import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; +import { + esQuery, + Query, + IIndexPattern, + esKuery, +} from '../../../../../../../../../src/plugins/data/public'; +import { SavedSearch } from '../../../../../../../../../src/legacy/core_plugins/kibana/public/discover/types'; import { KibanaConfigTypeFix } from '../../../contexts/kibana'; -import { esQuery, Query, IIndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import { SEARCH_QUERY_LANGUAGE } from '../../../../../common/constants/search'; +import { SavedSearchSavedObject } from '../../../../../common/types/kibana'; +import { getQueryFromSavedSearch } from '../../../util/index_utils'; export interface SearchItems { indexPattern: IIndexPattern; savedSearch: SavedSearch; - query: any; + query: Query; combinedQuery: any; } @@ -22,7 +30,7 @@ export interface SearchItems { export function createSearchItems( kibanaConfig: KibanaConfigTypeFix, indexPattern: IndexPattern, - savedSearch: SavedSearch + savedSearch: SavedSearchSavedObject | null ) { // query is only used by the data visualizer as it needs // a lucene query_string. @@ -43,22 +51,24 @@ export function createSearchItems( }, }; - if (indexPattern.id === undefined && savedSearch.id !== undefined) { - const searchSource = savedSearch.searchSource; - indexPattern = searchSource.getField('index')!; + if (savedSearch !== null) { + const data = getQueryFromSavedSearch(savedSearch); - query = searchSource.getField('query')!; - const fs = searchSource.getField('filter'); + query = data.query; + const filter = data.filter; - const filters = Array.isArray(fs) ? fs : []; + const filters = Array.isArray(filter) ? filter : []; - const esQueryConfigs = esQuery.getEsQueryConfig(kibanaConfig); - combinedQuery = esQuery.buildEsQuery(indexPattern, [query], filters, esQueryConfigs); + if (query.language === SEARCH_QUERY_LANGUAGE.KUERY) { + const ast = esKuery.fromKueryExpression(query.query); + combinedQuery = esKuery.toElasticsearchQuery(ast, indexPattern); + } else { + const esQueryConfigs = esQuery.getEsQueryConfig(kibanaConfig); + combinedQuery = esQuery.buildEsQuery(indexPattern, [query], filters, esQueryConfigs); + } } return { - indexPattern, - savedSearch, query, combinedQuery, }; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/resolvers.ts b/x-pack/legacy/plugins/ml/public/application/routing/resolvers.ts index 658804025a83a20..fb6eaec6b230016 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/resolvers.ts +++ b/x-pack/legacy/plugins/ml/public/application/routing/resolvers.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { loadIndexPatterns } from '../util/index_utils'; +import { loadIndexPatterns, loadSavedSearches } from '../util/index_utils'; import { checkFullLicense } from '../license/check_license'; import { checkGetJobsPrivilege } from '../privilege/check_privilege'; import { getMlNodeCount } from '../ml_nodes_check/check_ml_nodes'; @@ -24,5 +24,6 @@ export const basicResolvers = (deps: PageDependencies): Resolvers => ({ loadMlServerInfo, loadIndexPatterns: () => loadIndexPatterns(deps.indexPatterns), checkGetJobsPrivilege, + loadSavedSearches, // getJobManagementBreadcrumbs(), }); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/router.tsx b/x-pack/legacy/plugins/ml/public/application/routing/router.tsx index d22bba69ad7f3b0..c6aed5cd504ac55 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/router.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/router.tsx @@ -8,10 +8,15 @@ import React, { FC, useEffect, useState } from 'react'; import { BrowserRouter as Router, Route, RouteProps } from 'react-router-dom'; import { Location } from 'history'; import { I18nContext } from 'ui/i18n'; -import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; +// import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/types'; import { IndexPatterns } from 'ui/index_patterns'; -import { getIndexPatternById, getFullIndexPatterns } from '../util/index_utils'; +// import { SavedObjectAttributes, SimpleSavedObject } from 'kibana/public'; +import { + getIndexPatternById, + getIndexPatternsContract, + getIndexPatternAndSavedSearch, +} from '../util/index_utils'; import { createSearchItems } from '../jobs/new_job/utils/new_job_utils'; import { ResolverResults, Resolvers } from './resolvers'; import { KibanaContext, KibanaConfigTypeFix, KibanaContextValue } from '../contexts/kibana'; @@ -74,7 +79,8 @@ export const MlRouter: FC<{ }; export const useResolver = ( - index: string | undefined, + indexPatternId: string | undefined, + savedSearchId: string | undefined, config: KibanaConfigTypeFix, resolvers: Resolvers ): { context: KibanaContextValue; results: ResolverResults } => { @@ -95,24 +101,19 @@ export const useResolver = ( res.forEach((r, i) => (tempResults[funcNames[i]] = r)); setResults(tempResults); - const stubbedSavedSearch = ({ - searchSource: { - getField() {}, - }, - } as never) as SavedSearch; + if (indexPatternId !== undefined || savedSearchId !== undefined) { + const { indexPattern, savedSearch } = + savedSearchId !== undefined + ? await getIndexPatternAndSavedSearch(savedSearchId) + : { savedSearch: null, indexPattern: await getIndexPatternById(indexPatternId!) }; - if (index !== undefined) { - const { indexPattern, savedSearch, combinedQuery } = createSearchItems( - config, - await getIndexPatternById(index), - stubbedSavedSearch - ); + const { combinedQuery } = createSearchItems(config, indexPattern!, savedSearch); setContext({ combinedQuery, currentIndexPattern: indexPattern, currentSavedSearch: savedSearch, - indexPatterns: getFullIndexPatterns()!, + indexPatterns: getIndexPatternsContract()!, kibanaConfig: config, }); } else { diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/access_denied.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/access_denied.tsx index 949d75dca4199ed..fca9dd319637045 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/access_denied.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/access_denied.tsx @@ -25,7 +25,7 @@ export const accessDeniedRoute: MlRoute = { }; const PageWrapper: FC = ({ config }) => { - const { context } = useResolver(undefined, config, {}); + const { context } = useResolver(undefined, undefined, config, {}); return ( diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_exploration.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_exploration.tsx index aab38115c0d25e3..ce426f75ea45260 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_exploration.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_exploration.tsx @@ -34,7 +34,7 @@ export const analyticsJobExplorationRoute: MlRoute = { }; const PageWrapper: FC = ({ location, config, deps }) => { - const { context } = useResolver('', config, basicResolvers(deps)); + const { context } = useResolver('', undefined, config, basicResolvers(deps)); const { _g } = queryString.parse(location.search); let globalState: any = null; try { diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_jobs_list.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_jobs_list.tsx index 32b4809ba7ec9f3..530e9a8afc7f442 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_jobs_list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_jobs_list.tsx @@ -29,7 +29,7 @@ export const analyticsJobsListRoute: MlRoute = { }; const PageWrapper: FC = ({ location, config, deps }) => { - const { context } = useResolver('', config, basicResolvers(deps)); + const { context } = useResolver('', undefined, config, basicResolvers(deps)); return ( diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/datavisualizer.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/datavisualizer.tsx index 0ea733171b459e6..4d9859d7de2ec9c 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/datavisualizer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/datavisualizer.tsx @@ -29,8 +29,7 @@ export const selectorRoute: MlRoute = { }; const PageWrapper: FC = ({ location, config }) => { - const { index } = queryString.parse(location.search); - const { context } = useResolver(index, config, { + const { context } = useResolver('', undefined, config, { checkBasicLicense, checkFindFileStructurePrivilege, }); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/file_based.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/file_based.tsx index 7fbd3a72d7ba0d5..1fcf22c6800b0b6 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/file_based.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/file_based.tsx @@ -42,8 +42,7 @@ export const fileBasedRoute: MlRoute = { }; const PageWrapper: FC = ({ location, config, deps }) => { - const { index } = queryString.parse(location.search); - const { context } = useResolver(index, config, { + const { context } = useResolver('', undefined, config, { checkBasicLicense, loadIndexPatterns: () => loadIndexPatterns(deps.indexPatterns), checkFindFileStructurePrivilege, diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx index d8dd72ac9e95d66..1bc900de14bb0bb 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx @@ -36,8 +36,8 @@ export const indexBasedRoute: MlRoute = { }; const PageWrapper: FC = ({ location, config, deps }) => { - const { index } = queryString.parse(location.search); - const { context } = useResolver(index, config, { + const { index, savedSearchId } = queryString.parse(location.search); + const { context } = useResolver(index, savedSearchId, config, { checkBasicLicense, loadIndexPatterns: () => loadIndexPatterns(deps.indexPatterns), checkGetJobsPrivilege, diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx index 060289e3e847014..7fd64405074c1e2 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx @@ -47,7 +47,7 @@ export const explorerRoute: MlRoute = { const PageWrapper: FC = ({ location, config, deps }) => { const { index } = queryString.parse(location.search); - const { context } = useResolver(index, config, { + const { context } = useResolver(index, undefined, config, { ...basicResolvers(deps), jobs: mlJobService.loadJobsWrapper, }); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/jobs_list.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/jobs_list.tsx index 87090184028ada3..14e8375108c0a41 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/jobs_list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/jobs_list.tsx @@ -31,7 +31,7 @@ export const jobListRoute: MlRoute = { }; const PageWrapper: FC = ({ config, deps }) => { - const { context } = useResolver(undefined, config, basicResolvers(deps)); + const { context } = useResolver(undefined, undefined, config, basicResolvers(deps)); return ( diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx index 83554f9690708d2..bc0e295ca855654 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx @@ -44,7 +44,7 @@ const PageWrapper: FC<{ nextStepPath: string; deps: PageDependencies; }> = ({ config, nextStepPath, deps }) => { - const { context } = useResolver(undefined, config, { + const { context } = useResolver(undefined, undefined, config, { ...basicResolvers(deps), preConfiguredJobRedirect, }); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/job_type.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/job_type.tsx index 1cee91ec02a3ff6..10649907214537d 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/job_type.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/job_type.tsx @@ -32,8 +32,8 @@ export const jobTypeRoute: MlRoute = { }; const PageWrapper: FC = ({ location, config, deps }) => { - const { index } = queryString.parse(location.search); - const { context } = useResolver(index, config, basicResolvers(deps)); + const { index, savedSearchId } = queryString.parse(location.search); + const { context } = useResolver(index, savedSearchId, config, basicResolvers(deps)); return ( diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/recognize.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/recognize.tsx index 6302e26b303226f..d4e2115ac774178 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/recognize.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/recognize.tsx @@ -42,8 +42,8 @@ export const checkViewOrCreateRoute: MlRoute = { }; const PageWrapper: FC = ({ location, config, deps }) => { - const { id, index } = queryString.parse(location.search); - const { context, results } = useResolver(index, config, { + const { id, index, savedSearchId } = queryString.parse(location.search); + const { context, results } = useResolver(index, savedSearchId, config, { ...basicResolvers(deps), existingJobsAndGroups: mlJobService.getJobAndGroupIds, }); @@ -58,7 +58,7 @@ const PageWrapper: FC = ({ location, config, deps }) => { const CheckViewOrCreateWrapper: FC = ({ location, config, deps }) => { const { id: moduleId, index: indexPatternId } = queryString.parse(location.search); // the single resolver checkViewOrCreateJobs redirects only. so will always reject - useResolver(undefined, config, { + useResolver(undefined, undefined, config, { checkViewOrCreateJobs: () => checkViewOrCreateJobs(moduleId, indexPatternId), }); return null; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/wizard.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/wizard.tsx index 7e8fc8d4047c129..3908b2f96fce99f 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/wizard.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/wizard.tsx @@ -97,11 +97,11 @@ export const advancedRoute: MlRoute = { }; const PageWrapper: FC = ({ location, config, jobType, deps }) => { - const { index } = queryString.parse(location.search); - const { context, results } = useResolver(index, config, { + const { index, savedSearchId } = queryString.parse(location.search); + const { context, results } = useResolver(index, savedSearchId, config, { ...basicResolvers(deps), privileges: checkCreateJobsPrivilege, - jobCaps: () => loadNewJobCapabilities(index, '', deps.indexPatterns, {}), + jobCaps: () => loadNewJobCapabilities(index, savedSearchId, deps.indexPatterns), existingJobsAndGroups: mlJobService.getJobAndGroupIds, }); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx index 5eb50e0c0965add..b06659a13f58a11 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx @@ -34,7 +34,7 @@ export const overviewRoute: MlRoute = { }; const PageWrapper: FC = ({ config }) => { - const { context } = useResolver(undefined, config, { + const { context } = useResolver(undefined, undefined, config, { checkFullLicense, checkGetJobsPrivilege, getMlNodeCount, diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx index 2340dcf55295809..88a67d182f7eff6 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx @@ -38,7 +38,7 @@ export const calendarListRoute: MlRoute = { }; const PageWrapper: FC = ({ config }) => { - const { context } = useResolver(undefined, config, { + const { context } = useResolver(undefined, undefined, config, { checkFullLicense, checkGetJobsPrivilege, getMlNodeCount, diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx index 75d157c994ee823..f0ed0ecb6db8838 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx @@ -76,7 +76,7 @@ const PageWrapper: FC = ({ location, config, mode }) => { calendarId = pathMatch && pathMatch.length > 1 ? pathMatch[1] : undefined; } - const { context } = useResolver(undefined, config, { + const { context } = useResolver(undefined, undefined, config, { checkFullLicense, checkGetJobsPrivilege, checkMlNodesAvailable, diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx index 88d94ad3b42cd31..0ed641862a7c0bf 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx @@ -39,7 +39,7 @@ export const filterListRoute: MlRoute = { }; const PageWrapper: FC = ({ config }) => { - const { context } = useResolver(undefined, config, { + const { context } = useResolver(undefined, undefined, config, { checkFullLicense, checkGetJobsPrivilege, getMlNodeCount, diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx index 2be9ebc995142a4..ba57778c9e69db5 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx @@ -76,7 +76,7 @@ const PageWrapper: FC = ({ location, config, mode }) => { filterId = pathMatch && pathMatch.length > 1 ? pathMatch[1] : undefined; } - const { context } = useResolver(undefined, config, { + const { context } = useResolver(undefined, undefined, config, { checkFullLicense, checkGetJobsPrivilege, checkMlNodesAvailable, diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx index c270ce665ad70a7..1fceaefa0d57454 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx @@ -28,7 +28,7 @@ export const settingsRoute: MlRoute = { }; const PageWrapper: FC = ({ config }) => { - const { context } = useResolver(undefined, config, { + const { context } = useResolver(undefined, undefined, config, { checkFullLicense, checkGetJobsPrivilege, getMlNodeCount, diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx index 0d00a5c61b396ee..31793e7215edde3 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx @@ -39,7 +39,7 @@ export const timeSeriesExplorerRoute: MlRoute = { }; const PageWrapper: FC = ({ location, config, deps }) => { - const { context } = useResolver('', config, { + const { context } = useResolver('', undefined, config, { ...basicResolvers(deps), jobs: mlJobService.loadJobsWrapper, }); diff --git a/x-pack/legacy/plugins/ml/public/application/services/new_job_capabilities_service.ts b/x-pack/legacy/plugins/ml/public/application/services/new_job_capabilities_service.ts index dcff4d1357ffbfd..13dbb923070ba37 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/new_job_capabilities_service.ts +++ b/x-pack/legacy/plugins/ml/public/application/services/new_job_capabilities_service.ts @@ -5,8 +5,6 @@ */ import { IndexPattern, IndexPatterns } from 'ui/index_patterns'; -// import { SavedSearchLoader } from 'src/legacy/core_plugins/kibana/public/discover/types'; -// import { start as data } from '../../../../../../../src/legacy/core_plugins/data/public/legacy'; import { Field, @@ -18,18 +16,15 @@ import { } from '../../../common/types/fields'; import { ES_FIELD_TYPES } from '../../../../../../../src/plugins/data/public'; import { ml } from './ml_api_service'; +import { getIndexPatternAndSavedSearch } from '../util/index_utils'; // called in the angular routing resolve block to initialize the // newJobCapsService with the currently selected index pattern export function loadNewJobCapabilities( - // savedSearches: SavedSearchLoader, indexPatternId: string, savedSearchId: string, - indexPatterns: IndexPatterns, - savedSearches: any + indexPatterns: IndexPatterns ) { - // const indexPatterns = data.indexPatterns.indexPatterns; - // const savedSearches = data.indexPatterns.indexPatterns; return new Promise(async (resolve, reject) => { if (indexPatternId !== undefined) { // index pattern is being used @@ -39,8 +34,13 @@ export function loadNewJobCapabilities( } else if (savedSearchId !== undefined) { // saved search is being used // load the index pattern from the saved search - const savedSearch = await savedSearches.get(savedSearchId); - const indexPattern = savedSearch.searchSource.getField('index')!; + const { indexPattern } = await getIndexPatternAndSavedSearch(savedSearchId); + if (indexPattern === null) { + // eslint-disable-next-line no-console + console.error('Cannot retrieve index pattern from saved search'); + reject(); + return; + } await newJobCapsService.initializeFromIndexPattern(indexPattern); resolve(newJobCapsService.newJobCaps); } else { diff --git a/x-pack/legacy/plugins/ml/public/application/util/index_utils.ts b/x-pack/legacy/plugins/ml/public/application/util/index_utils.ts index 1d6e14c73f2c9f5..afdec2969916891 100644 --- a/x-pack/legacy/plugins/ml/public/application/util/index_utils.ts +++ b/x-pack/legacy/plugins/ml/public/application/util/index_utils.ts @@ -7,18 +7,17 @@ import { toastNotifications } from 'ui/notify'; import { i18n } from '@kbn/i18n'; import { IndexPattern, IndexPatterns } from 'ui/index_patterns'; -import { SavedObjectAttributes, SimpleSavedObject } from 'kibana/public'; import chrome from 'ui/chrome'; -import { SavedSearchLoader } from '../../../../../../../src/legacy/core_plugins/kibana/public/discover/types'; +import { Query } from 'src/plugins/data/public'; import { start as data } from '../../../../../../../src/legacy/core_plugins/data/public/legacy'; // this should be shimmed - -type IndexPatternSavedObject = SimpleSavedObject; +import { IndexPatternSavedObject, SavedSearchSavedObject } from '../../../common/types/kibana'; let indexPatternCache: IndexPatternSavedObject[] = []; -let fullIndexPatterns: IndexPatterns | null = null; +let savedSearchesCache: SavedSearchSavedObject[] = []; +let indexPatternsContract: IndexPatterns | null = null; export function loadIndexPatterns(indexPatterns?: IndexPatterns) { - fullIndexPatterns = + indexPatternsContract = indexPatterns !== undefined ? indexPatterns : data.indexPatterns.indexPatterns; // NP TODO - remove this check, indexPatterns should always be passed in const savedObjectsClient = chrome.getSavedObjectsClient(); return savedObjectsClient @@ -33,12 +32,31 @@ export function loadIndexPatterns(indexPatterns?: IndexPatterns) { }); } +export function loadSavedSearches() { + const savedObjectsClient = chrome.getSavedObjectsClient(); + return savedObjectsClient + .find({ + type: 'search', + perPage: 10000, + }) + .then(response => { + savedSearchesCache = response.savedObjects; + return savedSearchesCache; + }); +} + +export async function loadSavedSearchById(id: string) { + const savedObjectsClient = chrome.getSavedObjectsClient(); + const ss = await savedObjectsClient.get('search', id); + return ss.error === undefined ? ss : null; +} + export function getIndexPatterns() { return indexPatternCache; } -export function getFullIndexPatterns() { - return fullIndexPatterns; +export function getIndexPatternsContract() { + return indexPatternsContract; } export function getIndexPatternNames() { @@ -54,24 +72,44 @@ export function getIndexPatternIdFromName(name: string) { return null; } -export function loadCurrentIndexPattern(indexPatterns: IndexPatterns, $route: Record) { - fullIndexPatterns = indexPatterns; - return fullIndexPatterns.get($route.current.params.index); +export async function getIndexPatternAndSavedSearch(savedSearchId: string) { + const resp: { savedSearch: SavedSearchSavedObject | null; indexPattern: IndexPattern | null } = { + savedSearch: null, + indexPattern: null, + }; + + if (savedSearchId === undefined) { + return resp; + } + + const ss = await loadSavedSearchById(savedSearchId); + if (ss === null) { + return resp; + } + const indexPatternId = ss.references.find(r => r.type === 'index-pattern')?.id; + resp.indexPattern = await getIndexPatternById(indexPatternId!); + resp.savedSearch = ss; + return resp; +} + +export function getQueryFromSavedSearch(savedSearch: SavedSearchSavedObject) { + const search = savedSearch.attributes.kibanaSavedObjectMeta as { searchSourceJSON: string }; + return JSON.parse(search.searchSourceJSON) as { + query: Query; + filter: any[]; + }; } export function getIndexPatternById(id: string): Promise { - if (fullIndexPatterns !== null) { - return fullIndexPatterns.get(id); + if (indexPatternsContract !== null) { + return indexPatternsContract.get(id); } else { throw new Error('Index patterns are not initialized!'); } } -export function loadCurrentSavedSearch( - savedSearches: SavedSearchLoader, - $route: Record -) { - return savedSearches.get($route.current.params.savedSearchId); +export function getSavedSearchById(id: string): SavedSearchSavedObject | undefined { + return savedSearchesCache.find(s => s.id === id); } /** diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/line_chart.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/line_chart.ts index eb2f50b8e92509e..6aa2f148a2ae305 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/line_chart.ts +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/line_chart.ts @@ -128,6 +128,10 @@ function getSearchJsonFromConfig( }, }; + if (query.bool.must === undefined) { + query.bool.must = []; + } + query.bool.must.push({ range: { [timeField]: {