From 865462a259050d1666e0e24502eda9a090611dbf Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 7 Jan 2020 10:46:32 -0500 Subject: [PATCH 01/83] [ML] DF Analytics job creation: Add 'excludes' input field to form (#53856) * Add exclude fields input to df analytics creation form * rename explain api endpoint to general explainDataFrameAnalytics * wip: use explain api for exclude fields * show error message if classification depVar has cardinality of > 2 * update types * updates after conflict resolution * prevent creation if more than 2 distinct classes for class job. create form field validation file --- .../data_frame_analytics/common/analytics.ts | 17 ++ .../create_analytics_form.test.tsx | 2 +- .../create_analytics_form.tsx | 272 +++++++++++++----- .../form_options_validation.ts | 43 +++ .../create_analytics_form/job_type.tsx | 6 +- .../use_create_analytics_form/reducer.ts | 29 +- .../hooks/use_create_analytics_form/state.ts | 23 +- .../ml_api_service/data_frame_analytics.js | 2 +- .../services/ml_api_service/index.d.ts | 4 +- .../ml/server/client/elasticsearch_ml.js | 2 +- .../ml/server/routes/data_frame_analytics.ts | 2 +- 11 files changed, 316 insertions(+), 86 deletions(-) create mode 100644 x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/form_options_validation.ts diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index cadc1f01c6dda3..3dd98395ef701d 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -58,6 +58,23 @@ export enum INDEX_STATUS { ERROR, } +export interface FieldSelectionItem { + name: string; + mappings_types: string[]; + is_included: boolean; + is_required: boolean; + feature_type?: string; + reason?: string; +} + +export interface DfAnalyticsExplainResponse { + field_selection: FieldSelectionItem[]; + memory_estimation: { + expected_memory_without_disk: string; + expected_memory_with_disk: string; + }; +} + export interface Eval { meanSquaredError: number | string; rSquared: number | string; diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.test.tsx b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.test.tsx index 0d4daee373b137..d01bae96167084 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.test.tsx +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.test.tsx @@ -40,7 +40,7 @@ describe('Data Frame Analytics: ', () => { ); const euiFormRows = wrapper.find('EuiFormRow'); - expect(euiFormRows.length).toBe(8); + expect(euiFormRows.length).toBe(9); const row1 = euiFormRows.at(0); expect(row1.find('label').text()).toBe('Job type'); diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx index 0815b8dbd8d3de..e68523733254e7 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx @@ -8,6 +8,7 @@ import React, { Fragment, FC, useEffect } from 'react'; import { EuiComboBox, + EuiComboBoxOptionProps, EuiForm, EuiFieldText, EuiFormRow, @@ -22,8 +23,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { metadata } from 'ui/metadata'; import { ml } from '../../../../../services/ml_api_service'; -import { Field, EVENT_RATE_FIELD_ID } from '../../../../../../../common/types/fields'; - +import { Field } from '../../../../../../../common/types/fields'; import { newJobCapsService } from '../../../../../services/new_job_capabilities_service'; import { useKibanaContext } from '../../../../../contexts/kibana'; import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; @@ -41,22 +41,8 @@ import { IndexPattern, indexPatterns, } from '../../../../../../../../../../../src/plugins/data/public'; - -const NUMERICAL_FIELD_TYPES = new Set([ - 'long', - 'integer', - 'short', - 'byte', - 'double', - 'float', - 'half_float', - 'scaled_float', -]); - -const SUPPORTED_CLASSIFICATION_FIELD_TYPES = new Set(['boolean', 'text', 'keyword', 'ip']); - -// List of system fields we want to ignore for the numeric field check. -const OMIT_FIELDS: string[] = ['_source', '_type', '_index', '_id', '_version', '_score']; +import { DfAnalyticsExplainResponse, FieldSelectionItem } from '../../../../common/analytics'; +import { shouldAddAsDepVarOption, OMIT_FIELDS } from './form_options_validation'; export const CreateAnalyticsForm: FC = ({ actions, state }) => { const { setFormState } = actions; @@ -74,15 +60,22 @@ export const CreateAnalyticsForm: FC = ({ actions, sta destinationIndexNameExists, destinationIndexNameValid, destinationIndexPatternTitleExists, + excludes, + excludesOptions, + fieldOptionsFetchFail, jobId, jobIdEmpty, jobIdExists, jobIdValid, jobIdInvalidMaxLength, jobType, - loadingDepFieldOptions, + loadingDepVarOptions, + loadingFieldOptions, + maxDistinctValuesError, modelMemoryLimit, modelMemoryLimitUnitValid, + previousJobType, + previousSourceIndex, sourceIndex, sourceIndexNameEmpty, sourceIndexNameValid, @@ -92,6 +85,9 @@ export const CreateAnalyticsForm: FC = ({ actions, sta } = form; const characterList = indexPatterns.ILLEGAL_CHARACTERS_VISIBLE.join(', '); + const isJobTypeWithDepVar = + jobType === JOB_TYPES.REGRESSION || jobType === JOB_TYPES.CLASSIFICATION; + // Find out if index pattern contain numeric fields. Provides a hint in the form // that an analytics jobs is not able to identify outliers if there are no numeric fields present. const validateSourceIndexFields = async () => { @@ -114,42 +110,99 @@ export const CreateAnalyticsForm: FC = ({ actions, sta } }; - // Regression supports numeric fields. Classification supports numeric, boolean, text, keyword and ip. - const shouldAddFieldOption = (field: Field) => { - if (field.id === EVENT_RATE_FIELD_ID) return false; + const onCreateOption = (searchValue: string, flattenedOptions: EuiComboBoxOptionProps[]) => { + const normalizedSearchValue = searchValue.trim().toLowerCase(); + + if (!normalizedSearchValue) { + return; + } - const isNumerical = NUMERICAL_FIELD_TYPES.has(field.type); - const isSupportedByClassification = - isNumerical || SUPPORTED_CLASSIFICATION_FIELD_TYPES.has(field.type); + const newOption = { + label: searchValue, + }; - if (jobType === JOB_TYPES.REGRESSION) return isNumerical; - if (jobType === JOB_TYPES.CLASSIFICATION) return isNumerical || isSupportedByClassification; + // Create the option if it doesn't exist. + if ( + !flattenedOptions.some( + (option: EuiComboBoxOptionProps) => + option.label.trim().toLowerCase() === normalizedSearchValue + ) + ) { + excludesOptions.push(newOption); + setFormState({ excludes: [...excludes, newOption.label] }); + } }; - const debouncedMmlEstimateLoad = debounce(async () => { + const debouncedGetExplainData = debounce(async () => { + // Reset if sourceIndex or jobType changes (jobType requires dependent_variable to be set - + // which won't be the case if switching from outlier detection) + if (previousSourceIndex !== sourceIndex || previousJobType !== jobType) { + setFormState({ + loadingFieldOptions: true, + }); + } + try { const jobConfig = getJobConfigFromFormState(form); delete jobConfig.dest; delete jobConfig.model_memory_limit; - const resp = await ml.dataFrameAnalytics.estimateDataFrameAnalyticsMemoryUsage(jobConfig); - setFormState({ - modelMemoryLimit: resp.memory_estimation?.expected_memory_without_disk, - }); + delete jobConfig.analyzed_fields; + const resp: DfAnalyticsExplainResponse = await ml.dataFrameAnalytics.explainDataFrameAnalytics( + jobConfig + ); + + // If sourceIndex has changed load analysis field options again + if (previousSourceIndex !== sourceIndex || previousJobType !== jobType) { + const analyzedFieldsOptions: EuiComboBoxOptionProps[] = []; + + if (resp.field_selection) { + resp.field_selection.forEach((selectedField: FieldSelectionItem) => { + if (selectedField.is_included === true && selectedField.name !== dependentVariable) { + analyzedFieldsOptions.push({ label: selectedField.name }); + } + }); + } + + setFormState({ + modelMemoryLimit: resp.memory_estimation?.expected_memory_without_disk, + excludesOptions: analyzedFieldsOptions, + loadingFieldOptions: false, + fieldOptionsFetchFail: false, + maxDistinctValuesError: undefined, + }); + } else { + setFormState({ + modelMemoryLimit: resp.memory_estimation?.expected_memory_without_disk, + }); + } } catch (e) { + let errorMessage; + if ( + jobType === JOB_TYPES.CLASSIFICATION && + e.message !== undefined && + e.message.includes('status_exception') && + e.message.includes('must have at most') + ) { + errorMessage = e.message; + } setFormState({ + fieldOptionsFetchFail: true, + maxDistinctValuesError: errorMessage, + loadingFieldOptions: false, modelMemoryLimit: jobType !== undefined ? DEFAULT_MODEL_MEMORY_LIMIT[jobType] : DEFAULT_MODEL_MEMORY_LIMIT.outlier_detection, }); } - }, 500); + }, 400); - const loadDependentFieldOptions = async () => { + const loadDepVarOptions = async () => { setFormState({ - loadingDepFieldOptions: true, + loadingDepVarOptions: true, + // clear when the source index changes dependentVariable: '', - // Reset outlier detection sourceIndex checks to default values if we've switched to regression + maxDistinctValuesError: undefined, sourceIndexFieldsCheckFailed: false, sourceIndexContainsNumericalFields: true, }); @@ -162,22 +215,23 @@ export const CreateAnalyticsForm: FC = ({ actions, sta await newJobCapsService.initializeFromIndexPattern(indexPattern); // Get fields and filter for supported types for job type const { fields } = newJobCapsService; - const options: Array<{ label: string }> = []; + + const depVarOptions: EuiComboBoxOptionProps[] = []; fields.forEach((field: Field) => { - if (shouldAddFieldOption(field)) { - options.push({ label: field.id }); + if (shouldAddAsDepVarOption(field, jobType)) { + depVarOptions.push({ label: field.id }); } }); setFormState({ - dependentVariableOptions: options, - loadingDepFieldOptions: false, + dependentVariableOptions: depVarOptions, + loadingDepVarOptions: false, dependentVariableFetchFail: false, }); } } catch (e) { - setFormState({ loadingDepFieldOptions: false, dependentVariableFetchFail: true }); + setFormState({ loadingDepVarOptions: false, dependentVariableFetchFail: true }); } }; @@ -209,13 +263,21 @@ export const CreateAnalyticsForm: FC = ({ actions, sta return errors; }; + const onSourceIndexChange = (selectedOptions: EuiComboBoxOptionProps[]) => { + setFormState({ + excludes: [], + excludesOptions: [], + previousSourceIndex: sourceIndex, + sourceIndex: selectedOptions[0].label || '', + }); + }; + useEffect(() => { - if ( - (jobType === JOB_TYPES.REGRESSION || jobType === JOB_TYPES.CLASSIFICATION) && - sourceIndexNameEmpty === false - ) { - loadDependentFieldOptions(); - } else if (jobType === JOB_TYPES.OUTLIER_DETECTION && sourceIndexNameEmpty === false) { + if (isJobTypeWithDepVar && sourceIndexNameEmpty === false) { + loadDepVarOptions(); + } + + if (jobType === JOB_TYPES.OUTLIER_DETECTION && sourceIndexNameEmpty === false) { validateSourceIndexFields(); } }, [sourceIndex, jobType, sourceIndexNameEmpty]); @@ -223,21 +285,18 @@ export const CreateAnalyticsForm: FC = ({ actions, sta useEffect(() => { const hasBasicRequiredFields = jobType !== undefined && sourceIndex !== '' && sourceIndexNameValid === true; - const jobTypesWithDepVar = - jobType === JOB_TYPES.REGRESSION || jobType === JOB_TYPES.CLASSIFICATION; const hasRequiredAnalysisFields = - (jobTypesWithDepVar && dependentVariable !== '' && trainingPercent !== undefined) || - jobType === JOB_TYPES.OUTLIER_DETECTION; + (isJobTypeWithDepVar && dependentVariable !== '') || jobType === JOB_TYPES.OUTLIER_DETECTION; if (hasBasicRequiredFields && hasRequiredAnalysisFields) { - debouncedMmlEstimateLoad(); + debouncedGetExplainData(); } return () => { - debouncedMmlEstimateLoad.cancel(); + debouncedGetExplainData.cancel(); }; - }, [jobType, sourceIndex, dependentVariable, trainingPercent]); + }, [jobType, sourceIndex, sourceIndexNameEmpty, dependentVariable, trainingPercent]); return ( @@ -354,9 +413,7 @@ export const CreateAnalyticsForm: FC = ({ actions, sta selectedOptions={ indexPatternsMap[sourceIndex] !== undefined ? [{ label: sourceIndex }] : [] } - onChange={selectedOptions => - setFormState({ sourceIndex: selectedOptions[0].label || '' }) - } + onChange={onSourceIndexChange} isClearable={false} data-test-subj="mlAnalyticsCreateJobFlyoutSourceIndexSelect" /> @@ -430,6 +487,27 @@ export const CreateAnalyticsForm: FC = ({ actions, sta {(jobType === JOB_TYPES.REGRESSION || jobType === JOB_TYPES.CLASSIFICATION) && ( + + {i18n.translate( + 'xpack.ml.dataframe.analytics.create.dependentVariableMaxDistictValuesError', + { + defaultMessage: 'Invalid. {message}', + values: { message: maxDistinctValuesError }, + } + )} + , + ] + : []), + ]} + > + + = ({ actions, sta } ) } - error={ - dependentVariableFetchFail === true && [ - - {i18n.translate( - 'xpack.ml.dataframe.analytics.create.dependentVariableOptionsFetchError', - { - defaultMessage: - 'There was a problem fetching fields. Please refresh the page and try again.', - } - )} - , - ] - } + isInvalid={maxDistinctValuesError !== undefined} + error={[ + ...(dependentVariableFetchFail === true + ? [ + + {i18n.translate( + 'xpack.ml.dataframe.analytics.create.dependentVariableOptionsFetchError', + { + defaultMessage: + 'There was a problem fetching fields. Please refresh the page and try again.', + } + )} + , + ] + : []), + ]} > = ({ actions, sta } )} isDisabled={isJobCreated} - isLoading={loadingDepFieldOptions} + isLoading={loadingDepVarOptions} singleSelection={true} options={dependentVariableOptions} selectedOptions={dependentVariable ? [{ label: dependentVariable }] : []} onChange={selectedOptions => - setFormState({ dependentVariable: selectedOptions[0].label || '' }) + setFormState({ + dependentVariable: selectedOptions[0].label || '', + }) } isClearable={false} isInvalid={dependentVariable === ''} @@ -508,6 +591,49 @@ export const CreateAnalyticsForm: FC = ({ actions, sta )} + + ({ + label: field, + }))} + onCreateOption={onCreateOption} + onChange={selectedOptions => + setFormState({ excludes: selectedOptions.map(option => option.label) }) + } + isClearable={true} + data-test-subj="mlAnalyticsCreateJobFlyoutExcludesSelect" + /> + { + if (field.id === EVENT_RATE_FIELD_ID) return false; + + const isBasicNumerical = BASIC_NUMERICAL_TYPES.has(field.type); + + const isSupportedByClassification = + isBasicNumerical || CATEGORICAL_TYPES.has(field.type) || field.type === ES_FIELD_TYPES.BOOLEAN; + + if (jobType === JOB_TYPES.REGRESSION) { + return isBasicNumerical || EXTENDED_NUMERICAL_TYPES.has(field.type); + } + if (jobType === JOB_TYPES.CLASSIFICATION) return isSupportedByClassification; +}; diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_type.tsx b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_type.tsx index 5d8a74bd10ab61..988daac528fd77 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_type.tsx +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_type.tsx @@ -64,7 +64,11 @@ export const JobType: FC = ({ type, setFormState }) => { hasNoInitialSelection={true} onChange={e => { const value = e.target.value as AnalyticsJobType; - setFormState({ jobType: value }); + setFormState({ + previousJobType: type, + jobType: value, + excludes: [], + }); }} data-test-subj="mlAnalyticsCreateJobFlyoutJobTypeSelect" /> diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts index 8498b0e5a9e9e1..f35fa6aa2f451c 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts @@ -54,7 +54,15 @@ const getSourceIndexString = (state: State) => { }; export const validateAdvancedEditor = (state: State): State => { - const { jobIdEmpty, jobIdValid, jobIdExists, jobType, createIndexPattern } = state.form; + const { + jobIdEmpty, + jobIdValid, + jobIdExists, + jobType, + createIndexPattern, + excludes, + maxDistinctValuesError, + } = state.form; const { jobConfig } = state; state.advancedEditorMessages = []; @@ -90,6 +98,7 @@ export const validateAdvancedEditor = (state: State): State => { } let dependentVariableEmpty = false; + let excludesValid = true; if ( jobConfig.analysis === undefined && @@ -104,6 +113,20 @@ export const validateAdvancedEditor = (state: State): State => { ) { const dependentVariableName = getDependentVar(jobConfig.analysis) || ''; dependentVariableEmpty = dependentVariableName === ''; + + if (!dependentVariableEmpty && excludes.includes(dependentVariableName)) { + excludesValid = false; + + state.advancedEditorMessages.push({ + error: i18n.translate( + 'xpack.ml.dataframe.analytics.create.advancedEditorMessage.excludesInvalid', + { + defaultMessage: 'The dependent variable cannot be excluded.', + } + ), + message: '', + }); + } } if (sourceIndexNameEmpty) { @@ -182,6 +205,8 @@ export const validateAdvancedEditor = (state: State): State => { } state.isValid = + maxDistinctValuesError === undefined && + excludesValid && state.form.modelMemoryLimitUnitValid && !jobIdEmpty && jobIdValid && @@ -210,6 +235,7 @@ const validateForm = (state: State): State => { destinationIndexPatternTitleExists, createIndexPattern, dependentVariable, + maxDistinctValuesError, modelMemoryLimit, } = state.form; @@ -225,6 +251,7 @@ const validateForm = (state: State): State => { } state.isValid = + maxDistinctValuesError === undefined && !jobTypeEmpty && state.form.modelMemoryLimitUnitValid && !jobIdEmpty && diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts index d29291f8795afd..282f9ff45d0ee0 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { EuiComboBoxOptionProps } from '@elastic/eui'; import { DeepPartial } from '../../../../../../../common/types/common'; import { checkPermission } from '../../../../../privilege/check_privilege'; import { mlNodesAvailable } from '../../../../../ml_nodes_check/check_ml_nodes'; @@ -45,22 +46,29 @@ export interface State { createIndexPattern: boolean; dependentVariable: DependentVariable; dependentVariableFetchFail: boolean; - dependentVariableOptions: Array<{ label: DependentVariable }> | []; + dependentVariableOptions: EuiComboBoxOptionProps[] | []; description: string; destinationIndex: EsIndexName; destinationIndexNameExists: boolean; destinationIndexNameEmpty: boolean; destinationIndexNameValid: boolean; destinationIndexPatternTitleExists: boolean; + excludes: string[]; + excludesOptions: EuiComboBoxOptionProps[]; + fieldOptionsFetchFail: boolean; jobId: DataFrameAnalyticsId; jobIdExists: boolean; jobIdEmpty: boolean; jobIdInvalidMaxLength: boolean; jobIdValid: boolean; jobType: AnalyticsJobType; - loadingDepFieldOptions: boolean; + loadingDepVarOptions: boolean; + loadingFieldOptions: boolean; + maxDistinctValuesError: string | undefined; modelMemoryLimit: string | undefined; modelMemoryLimitUnitValid: boolean; + previousJobType: null | AnalyticsJobType; + previousSourceIndex: EsIndexName | undefined; sourceIndex: EsIndexName; sourceIndexNameEmpty: boolean; sourceIndexNameValid: boolean; @@ -96,15 +104,22 @@ export const getInitialState = (): State => ({ destinationIndexNameEmpty: true, destinationIndexNameValid: false, destinationIndexPatternTitleExists: false, + excludes: [], + fieldOptionsFetchFail: false, + excludesOptions: [], jobId: '', jobIdExists: false, jobIdEmpty: true, jobIdInvalidMaxLength: false, jobIdValid: false, jobType: undefined, - loadingDepFieldOptions: false, + loadingDepVarOptions: false, + loadingFieldOptions: false, + maxDistinctValuesError: undefined, modelMemoryLimit: undefined, modelMemoryLimitUnitValid: true, + previousJobType: null, + previousSourceIndex: undefined, sourceIndex: '', sourceIndexNameEmpty: true, sourceIndexNameValid: false, @@ -146,7 +161,7 @@ export const getJobConfigFromFormState = ( index: formState.destinationIndex, }, analyzed_fields: { - excludes: [], + excludes: formState.excludes, }, analysis: { outlier_detection: {}, diff --git a/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/data_frame_analytics.js b/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/data_frame_analytics.js index 2645e0e3f9c420..6ff0b45454abf6 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/data_frame_analytics.js +++ b/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/data_frame_analytics.js @@ -45,7 +45,7 @@ export const dataFrameAnalytics = { data: evaluateConfig, }); }, - estimateDataFrameAnalyticsMemoryUsage(jobConfig) { + explainDataFrameAnalytics(jobConfig) { return http({ url: `${basePath}/data_frame/analytics/_explain`, method: 'POST', diff --git a/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts b/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts index 39c69d4bbbeba5..58692754d95d70 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts +++ b/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts @@ -90,9 +90,7 @@ declare interface Ml { getDataFrameAnalyticsStats(analyticsId?: string): Promise; createDataFrameAnalytics(analyticsId: string, analyticsConfig: any): Promise; evaluateDataFrameAnalytics(evaluateConfig: any): Promise; - estimateDataFrameAnalyticsMemoryUsage( - jobConfig: DeepPartial - ): Promise; + explainDataFrameAnalytics(jobConfig: DeepPartial): Promise; deleteDataFrameAnalytics(analyticsId: string): Promise; startDataFrameAnalytics(analyticsId: string): Promise; stopDataFrameAnalytics( diff --git a/x-pack/legacy/plugins/ml/server/client/elasticsearch_ml.js b/x-pack/legacy/plugins/ml/server/client/elasticsearch_ml.js index 5d38de4a6ba87c..2ca21efb0bd6ae 100644 --- a/x-pack/legacy/plugins/ml/server/client/elasticsearch_ml.js +++ b/x-pack/legacy/plugins/ml/server/client/elasticsearch_ml.js @@ -168,7 +168,7 @@ export const elasticsearchJsPlugin = (Client, config, components) => { method: 'POST', }); - ml.estimateDataFrameAnalyticsMemoryUsage = ca({ + ml.explainDataFrameAnalytics = ca({ urls: [ { fmt: '/_ml/data_frame/analytics/_explain', diff --git a/x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts b/x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts index 2f8db45d9739e4..7b855e5f87cbf6 100644 --- a/x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts +++ b/x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts @@ -164,7 +164,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser( - 'ml.estimateDataFrameAnalyticsMemoryUsage', + 'ml.explainDataFrameAnalytics', { body: request.body, } From c02531a494a3c61a59393832995823b9e39b58e8 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 7 Jan 2020 16:53:16 +0100 Subject: [PATCH 02/83] NP Migration: Move doc views registry and existing doc views into discover plugin (#53465) --- .../core_plugins/kbn_doc_views/index.js | 26 ------- .../core_plugins/kbn_doc_views/package.json | 4 -- .../kbn_doc_views/public/kbn_doc_views.js | 21 ------ .../kbn_doc_views/public/views/json.tsx | 33 --------- .../kbn_doc_views/public/views/table.ts | 31 --------- .../kibana/public/discover/build_services.ts | 21 ++++-- .../kibana/public/discover/index.ts | 18 +++-- .../kibana/public/discover/kibana_services.ts | 8 +-- .../np_ready/components/doc/doc.test.tsx | 4 +- .../components/doc/use_es_doc_search.test.tsx | 8 +-- .../components/doc_viewer/doc_viewer.test.tsx | 42 +++++------ .../components/doc_viewer/doc_viewer.tsx | 3 +- .../doc_viewer/doc_viewer_render_tab.test.tsx | 2 +- .../doc_viewer/doc_viewer_render_tab.tsx | 2 +- .../components/doc_viewer/doc_viewer_tab.tsx | 2 +- .../json_code_block.test.tsx.snap | 0 .../json_code_block}/json_code_block.test.tsx | 2 +- .../json_code_block}/json_code_block.tsx | 4 +- .../np_ready/components}/table/table.test.tsx | 2 +- .../np_ready/components}/table/table.tsx | 2 +- .../components}/table/table_helper.test.ts | 0 .../components}/table/table_helper.tsx | 0 .../np_ready/components}/table/table_row.tsx | 6 +- .../table/table_row_btn_collapse.tsx | 2 +- .../table/table_row_btn_filter_add.tsx | 6 +- .../table/table_row_btn_filter_exists.tsx | 15 ++-- .../table/table_row_btn_filter_remove.tsx | 6 +- .../table/table_row_btn_toggle_column.tsx | 20 ++++-- .../table/table_row_icon_no_mapping.tsx | 20 ++++-- .../table/table_row_icon_underscore.tsx | 4 +- .../np_ready/doc_views}/doc_views_helpers.tsx | 12 ++-- .../np_ready/doc_views/doc_views_registry.ts | 50 ++++++++++++++ .../np_ready/doc_views}/doc_views_types.ts | 2 +- .../kibana/public/discover/plugin.ts | 41 +++++++++-- src/legacy/ui/public/registry/doc_views.ts | 69 ------------------- .../translations/translations/ja-JP.json | 40 +++++------ .../translations/translations/zh-CN.json | 40 +++++------ 37 files changed, 244 insertions(+), 324 deletions(-) delete mode 100644 src/legacy/core_plugins/kbn_doc_views/index.js delete mode 100644 src/legacy/core_plugins/kbn_doc_views/package.json delete mode 100644 src/legacy/core_plugins/kbn_doc_views/public/kbn_doc_views.js delete mode 100644 src/legacy/core_plugins/kbn_doc_views/public/views/json.tsx delete mode 100644 src/legacy/core_plugins/kbn_doc_views/public/views/table.ts rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components/json_code_block}/__snapshots__/json_code_block.test.tsx.snap (100%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components/json_code_block}/json_code_block.test.tsx (94%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components/json_code_block}/json_code_block.tsx (88%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table.test.tsx (98%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table.tsx (97%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table_helper.test.ts (100%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table_helper.tsx (100%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table_row.tsx (96%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table_row_btn_collapse.tsx (94%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table_row_btn_filter_add.tsx (87%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table_row_btn_filter_exists.tsx (80%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table_row_btn_filter_remove.tsx (87%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table_row_btn_toggle_column.tsx (79%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table_row_icon_no_mapping.tsx (74%) rename src/legacy/core_plugins/{kbn_doc_views/public/views => kibana/public/discover/np_ready/components}/table/table_row_icon_underscore.tsx (89%) rename src/legacy/{ui/public/registry => core_plugins/kibana/public/discover/np_ready/doc_views}/doc_views_helpers.tsx (92%) create mode 100644 src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_registry.ts rename src/legacy/{ui/public/registry => core_plugins/kibana/public/discover/np_ready/doc_views}/doc_views_types.ts (97%) delete mode 100644 src/legacy/ui/public/registry/doc_views.ts diff --git a/src/legacy/core_plugins/kbn_doc_views/index.js b/src/legacy/core_plugins/kbn_doc_views/index.js deleted file mode 100644 index 9078a82d633811..00000000000000 --- a/src/legacy/core_plugins/kbn_doc_views/index.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default function(kibana) { - return new kibana.Plugin({ - uiExports: { - docViews: ['plugins/kbn_doc_views/kbn_doc_views'], - }, - }); -} diff --git a/src/legacy/core_plugins/kbn_doc_views/package.json b/src/legacy/core_plugins/kbn_doc_views/package.json deleted file mode 100644 index efad9ec42f1f29..00000000000000 --- a/src/legacy/core_plugins/kbn_doc_views/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "kbn_doc_views", - "version": "kibana" -} diff --git a/src/legacy/core_plugins/kbn_doc_views/public/kbn_doc_views.js b/src/legacy/core_plugins/kbn_doc_views/public/kbn_doc_views.js deleted file mode 100644 index 2608e60e70742f..00000000000000 --- a/src/legacy/core_plugins/kbn_doc_views/public/kbn_doc_views.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import './views/table'; -import './views/json'; diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/json.tsx b/src/legacy/core_plugins/kbn_doc_views/public/views/json.tsx deleted file mode 100644 index 73167b56bddeaa..00000000000000 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/json.tsx +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { addDocView } from 'ui/registry/doc_views'; -import { i18n } from '@kbn/i18n'; -import { JsonCodeBlock } from './json_code_block'; - -/* - * Registration of the the doc view: json - * - used to display an ES hit as pretty printed JSON at Discover - */ -addDocView({ - title: i18n.translate('kbnDocViews.json.jsonTitle', { - defaultMessage: 'JSON', - }), - order: 20, - component: JsonCodeBlock, -}); diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table.ts b/src/legacy/core_plugins/kbn_doc_views/public/views/table.ts deleted file mode 100644 index f90840f1950039..00000000000000 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/table.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import { addDocView } from 'ui/registry/doc_views'; -import { i18n } from '@kbn/i18n'; -import { DocViewTable } from './table/table'; - -addDocView({ - title: i18n.translate('kbnDocViews.table.tableTitle', { - defaultMessage: 'Table', - }), - order: 10, - component: DocViewTable, -}); diff --git a/src/legacy/core_plugins/kibana/public/discover/build_services.ts b/src/legacy/core_plugins/kibana/public/discover/build_services.ts index aaacde7e4060f7..1fb8b4abb21c4d 100644 --- a/src/legacy/core_plugins/kibana/public/discover/build_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/build_services.ts @@ -24,24 +24,27 @@ import { ToastsStart, IUiSettingsClient, } from 'kibana/public'; -import * as docViewsRegistry from 'ui/registry/doc_views'; -import { FilterManager, TimefilterContract, IndexPatternsContract } from 'src/plugins/data/public'; +import { + FilterManager, + TimefilterContract, + IndexPatternsContract, + DataPublicPluginStart, +} from 'src/plugins/data/public'; import { createSavedSearchesService } from './saved_searches'; -// @ts-ignore import { DiscoverStartPlugins } from './plugin'; -import { DataStart } from '../../../data/public'; import { EuiUtilsStart } from '../../../../../plugins/eui_utils/public'; import { SharePluginStart } from '../../../../../plugins/share/public'; import { SavedSearch } from './np_ready/types'; +import { DocViewsRegistry } from './np_ready/doc_views/doc_views_registry'; export interface DiscoverServices { addBasePath: (path: string) => string; capabilities: Capabilities; chrome: ChromeStart; core: CoreStart; - data: DataStart; + data: DataPublicPluginStart; docLinks: DocLinksStart; - docViewsRegistry: docViewsRegistry.DocViewsRegistry; + docViewsRegistry: DocViewsRegistry; eui_utils: EuiUtilsStart; filterManager: FilterManager; indexPatterns: IndexPatternsContract; @@ -54,7 +57,11 @@ export interface DiscoverServices { getSavedSearchUrlById: (id: string) => Promise; uiSettings: IUiSettingsClient; } -export async function buildServices(core: CoreStart, plugins: DiscoverStartPlugins) { +export async function buildServices( + core: CoreStart, + plugins: DiscoverStartPlugins, + docViewsRegistry: DocViewsRegistry +): Promise { const services = { savedObjectsClient: core.savedObjects.client, indexPatterns: plugins.data.indexPatterns, diff --git a/src/legacy/core_plugins/kibana/public/discover/index.ts b/src/legacy/core_plugins/kibana/public/discover/index.ts index 347f545dea4c95..7bde30e0d0f0ef 100644 --- a/src/legacy/core_plugins/kibana/public/discover/index.ts +++ b/src/legacy/core_plugins/kibana/public/discover/index.ts @@ -16,20 +16,24 @@ * specific language governing permissions and limitations * under the License. */ -import { PluginInitializer, PluginInitializerContext } from 'kibana/public'; +import chrome from 'ui/chrome'; +import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { DiscoverPlugin, DiscoverSetup, DiscoverStart } from './plugin'; +import { DiscoverPlugin } from './plugin'; // Core will be looking for this when loading our plugin in the new platform -export const plugin: PluginInitializer = () => { +export const plugin = (context: PluginInitializerContext) => { return new DiscoverPlugin(); }; // Legacy compatiblity part - to be removed at cutover, replaced by a kibana.json file export const pluginInstance = plugin({} as PluginInitializerContext); -(async () => { - pluginInstance.setup(npSetup.core, npSetup.plugins); - pluginInstance.start(npStart.core, npStart.plugins); -})(); +export const setup = pluginInstance.setup(npSetup.core, { + ...npSetup.plugins, + __LEGACY: { + chrome, + }, +}); +export const start = pluginInstance.start(npStart.core, npStart.plugins); export { createSavedSearchesService } from './saved_searches/saved_searches'; diff --git a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts index ca169e5f803ab6..d2eefba2cecdd9 100644 --- a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts @@ -94,11 +94,11 @@ export { IndexPatternsContract, IIndexPattern, IndexPattern, + indexPatterns, IFieldType, } from '../../../../../plugins/data/public'; -export { ElasticSearchHit } from 'ui/registry/doc_views_types'; -export { DocViewRenderProps, DocViewRenderFn } from 'ui/registry/doc_views'; +export { ElasticSearchHit } from './np_ready/doc_views/doc_views_types'; export { Adapters } from 'ui/inspector/types'; -export { DocView, DocViewInput } from 'ui/registry/doc_views_types'; +export { Chrome, IInjector } from 'ui/chrome'; export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router'; -export { IInjector } from 'ui/chrome'; +export { FieldName } from 'ui/directives/field_name/field_name'; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc/doc.test.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc/doc.test.tsx index 656e8598aa12ff..e09f26311e4e32 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc/doc.test.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc/doc.test.tsx @@ -25,7 +25,7 @@ import { findTestSubject } from '@elastic/eui/lib/test'; import { Doc, DocProps } from './doc'; jest.mock('../doc_viewer/doc_viewer', () => ({ - DocViewer: 'test', + DocViewer: () => null, })); jest.mock('../../../kibana_services', () => { @@ -67,7 +67,7 @@ async function mountDoc(search: () => void, update = false, indexPatternGetter: indexPatternService, } as DocProps; let comp!: ReactWrapper; - act(() => { + await act(async () => { comp = mountWithIntl(); if (update) comp.update(); }); diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc/use_es_doc_search.test.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc/use_es_doc_search.test.tsx index 2420eb2cd22bb7..a8fe8de833315a 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc/use_es_doc_search.test.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc/use_es_doc_search.test.tsx @@ -43,7 +43,7 @@ describe('Test of helper / hook', () => { `); }); - test('useEsDocSearch', () => { + test('useEsDocSearch', async () => { const indexPattern = { getComputedFields: () => [], }; @@ -53,16 +53,16 @@ describe('Test of helper / hook', () => { const props = { id: '1', index: 'index1', - esClient: { search: jest.fn() }, + esClient: { search: jest.fn(() => new Promise(() => {})) }, indexPatternId: 'xyz', indexPatternService, } as DocProps; let hook; - act(() => { + await act(async () => { hook = renderHook((p: DocProps) => useEsDocSearch(p), { initialProps: props }); }); // @ts-ignore - expect(hook.result.current).toEqual([ElasticRequestState.Loading, null, null]); + expect(hook.result.current).toEqual([ElasticRequestState.Loading, null, indexPattern]); expect(indexPatternService.get).toHaveBeenCalled(); }); }); diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer.test.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer.test.tsx index c0644a6458694b..15f0f40700abc7 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer.test.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer.test.tsx @@ -21,23 +21,23 @@ import { mount, shallow } from 'enzyme'; import { DocViewer } from './doc_viewer'; // @ts-ignore import { findTestSubject } from '@elastic/eui/lib/test'; -import { DocViewRenderProps, DocViewInput, getServices } from '../../../kibana_services'; +import { getServices } from '../../../kibana_services'; +import { DocViewRenderProps } from '../../doc_views/doc_views_types'; jest.mock('../../../kibana_services', () => { - const docViews: DocViewInput[] = []; - - function addDocView(docView: DocViewInput) { - docViews.push(docView); - } - + let registry: any[] = []; return { getServices: () => ({ docViewsRegistry: { - getDocViewsSorted: () => { - return docViews; + addDocView(view: any) { + registry.push(view); + }, + getDocViewsSorted() { + return registry; }, - addDocView, - docViews, + }, + resetRegistry: () => { + registry = []; }, }), formatMsg: (x: any) => String(x), @@ -45,23 +45,16 @@ jest.mock('../../../kibana_services', () => { }; }); -const { - docViewsRegistry: { docViews, addDocView }, -} = getServices(); - -function emptyDocViews() { - docViews.length = 0; -} - beforeEach(() => { - emptyDocViews(); + (getServices() as any).resetRegistry(); jest.clearAllMocks(); }); test('Render with 3 different tabs', () => { - addDocView({ order: 10, title: 'Render function', render: jest.fn() }); - addDocView({ order: 20, title: 'React component', component: () =>
test
}); - addDocView({ order: 30, title: 'Invalid doc view' }); + const registry = getServices().docViewsRegistry; + registry.addDocView({ order: 10, title: 'Render function', render: jest.fn() }); + registry.addDocView({ order: 20, title: 'React component', component: () =>
test
}); + registry.addDocView({ order: 30, title: 'Invalid doc view' }); const renderProps = { hit: {} } as DocViewRenderProps; @@ -76,7 +69,8 @@ test('Render with 1 tab displaying error message', () => { return null; } - addDocView({ + const registry = getServices().docViewsRegistry; + registry.addDocView({ order: 10, title: 'React component', component: SomeComponent, diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer.tsx index 00926d70db25c3..a177d8c29304c4 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer.tsx @@ -18,8 +18,9 @@ */ import React from 'react'; import { EuiTabbedContent } from '@elastic/eui'; -import { getServices, DocViewRenderProps, DocView } from '../../../kibana_services'; +import { getServices } from '../../../kibana_services'; import { DocViewerTab } from './doc_viewer_tab'; +import { DocView, DocViewRenderProps } from '../../doc_views/doc_views_types'; /** * Rendering tabs with different views of 1 Elasticsearch hit in Discover. diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_tab.test.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_tab.test.tsx index c100e71b5f2b52..79f185452164ff 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_tab.test.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_tab.test.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { mount } from 'enzyme'; import { DocViewRenderTab } from './doc_viewer_render_tab'; -import { DocViewRenderProps } from '../../../kibana_services'; +import { DocViewRenderProps } from '../../doc_views/doc_views_types'; test('Mounting and unmounting DocViewerRenderTab', () => { const unmountFn = jest.fn(); diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_tab.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_tab.tsx index 31a8808a3a1c92..0b1a02f1987c24 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_tab.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_tab.tsx @@ -17,7 +17,7 @@ * under the License. */ import React, { useRef, useEffect } from 'react'; -import { DocViewRenderFn, DocViewRenderProps } from '../../../kibana_services'; +import { DocViewRenderFn, DocViewRenderProps } from '../../doc_views/doc_views_types'; interface Props { render: DocViewRenderFn; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_tab.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_tab.tsx index e08b0b2323d813..0c21fafc91d69a 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_tab.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_tab.tsx @@ -18,9 +18,9 @@ */ import React from 'react'; import { I18nProvider } from '@kbn/i18n/react'; -import { DocViewRenderProps, DocViewRenderFn } from '../../../kibana_services'; import { DocViewRenderTab } from './doc_viewer_render_tab'; import { DocViewerError } from './doc_viewer_render_error'; +import { DocViewRenderFn, DocViewRenderProps } from '../../doc_views/doc_views_types'; interface Props { component?: React.ComponentType; diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/__snapshots__/json_code_block.test.tsx.snap b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/json_code_block/__snapshots__/json_code_block.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kbn_doc_views/public/views/__snapshots__/json_code_block.test.tsx.snap rename to src/legacy/core_plugins/kibana/public/discover/np_ready/components/json_code_block/__snapshots__/json_code_block.test.tsx.snap diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/json_code_block.test.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/json_code_block/json_code_block.test.tsx similarity index 94% rename from src/legacy/core_plugins/kbn_doc_views/public/views/json_code_block.test.tsx rename to src/legacy/core_plugins/kibana/public/discover/np_ready/components/json_code_block/json_code_block.test.tsx index ea11ea7b7df108..9cab7974c9eb28 100644 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/json_code_block.test.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/json_code_block/json_code_block.test.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { JsonCodeBlock } from './json_code_block'; -import { IndexPattern } from '../../../../../plugins/data/public'; +import { IndexPattern } from '../../../kibana_services'; it('returns the `JsonCodeEditor` component', () => { const props = { diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/json_code_block.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/json_code_block/json_code_block.tsx similarity index 88% rename from src/legacy/core_plugins/kbn_doc_views/public/views/json_code_block.tsx rename to src/legacy/core_plugins/kibana/public/discover/np_ready/components/json_code_block/json_code_block.tsx index 3f412b05005235..3331969e351ab2 100644 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/json_code_block.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/json_code_block/json_code_block.tsx @@ -19,10 +19,10 @@ import React from 'react'; import { EuiCodeBlock } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { DocViewRenderProps } from 'ui/registry/doc_views'; +import { DocViewRenderProps } from '../../doc_views/doc_views_types'; export function JsonCodeBlock({ hit }: DocViewRenderProps) { - const label = i18n.translate('kbnDocViews.json.codeEditorAriaLabel', { + const label = i18n.translate('kbn.discover.docViews.json.codeEditorAriaLabel', { defaultMessage: 'Read only JSON view of an elasticsearch document', }); return ( diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table.test.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.test.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_doc_views/public/views/table/table.test.tsx rename to src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.test.tsx index 91b98865a02079..f816b33bcd0ae3 100644 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table.test.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.test.tsx @@ -22,7 +22,7 @@ import { mount } from 'enzyme'; import { findTestSubject } from '@elastic/eui/lib/test'; import { DocViewTable } from './table'; -import { IndexPattern, indexPatterns } from '../../../../../../plugins/data/public'; +import { IndexPattern, indexPatterns } from '../../../kibana_services'; jest.mock('ui/new_platform'); diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx similarity index 97% rename from src/legacy/core_plugins/kbn_doc_views/public/views/table/table.tsx rename to src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx index 7158739e5d4375..4bb2f83016c22e 100644 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx @@ -17,9 +17,9 @@ * under the License. */ import React, { useState } from 'react'; -import { DocViewRenderProps } from 'ui/registry/doc_views'; import { DocViewTableRow } from './table_row'; import { arrayContainsObjects, trimAngularSpan } from './table_helper'; +import { DocViewRenderProps } from '../../doc_views/doc_views_types'; const COLLAPSE_LINE_LENGTH = 350; diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_helper.test.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_helper.test.ts similarity index 100% rename from src/legacy/core_plugins/kbn_doc_views/public/views/table/table_helper.test.ts rename to src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_helper.test.ts diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_helper.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_helper.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_doc_views/public/views/table/table_helper.tsx rename to src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_helper.tsx diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_row.tsx similarity index 96% rename from src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx rename to src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_row.tsx index 045e8093124a6c..ffcb20f0767364 100644 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_row.tsx @@ -16,10 +16,10 @@ * specific language governing permissions and limitations * under the License. */ -import React, { ReactNode } from 'react'; -import { FieldName } from 'ui/directives/field_name/field_name'; -import { FieldMapping, DocViewFilterFn } from 'ui/registry/doc_views_types'; import classNames from 'classnames'; +import React, { ReactNode } from 'react'; +import { FieldName } from '../../../kibana_services'; +import { FieldMapping, DocViewFilterFn } from '../../doc_views/doc_views_types'; import { DocViewTableRowBtnFilterAdd } from './table_row_btn_filter_add'; import { DocViewTableRowBtnFilterRemove } from './table_row_btn_filter_remove'; import { DocViewTableRowBtnToggleColumn } from './table_row_btn_toggle_column'; diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row_btn_collapse.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_row_btn_collapse.tsx similarity index 94% rename from src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row_btn_collapse.tsx rename to src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_row_btn_collapse.tsx index cb6b522ba95592..e59f607329d4ae 100644 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row_btn_collapse.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_row_btn_collapse.tsx @@ -26,7 +26,7 @@ export interface Props { } export function DocViewTableRowBtnCollapse({ onClick, isCollapsed }: Props) { - const label = i18n.translate('kbnDocViews.table.toggleFieldDetails', { + const label = i18n.translate('kbn.discover.docViews.table.toggleFieldDetails', { defaultMessage: 'Toggle field details', }); return ( diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row_btn_filter_add.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_row_btn_filter_add.tsx similarity index 87% rename from src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row_btn_filter_add.tsx rename to src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_row_btn_filter_add.tsx index df4572c5bb53be..8e2668e26cf080 100644 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row_btn_filter_add.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table_row_btn_filter_add.tsx @@ -29,12 +29,12 @@ export interface Props { export function DocViewTableRowBtnFilterAdd({ onClick, disabled = false }: Props) { const tooltipContent = disabled ? ( ) : ( ); @@ -42,7 +42,7 @@ export function DocViewTableRowBtnFilterAdd({ onClick, disabled = false }: Props return ( ) : ( ) ) : ( ); @@ -54,9 +54,12 @@ export function DocViewTableRowBtnFilterExists({ return ( ) : ( ); @@ -42,7 +42,7 @@ export function DocViewTableRowBtnFilterRemove({ onClick, disabled = false }: Pr return ( } > Index Patterns page', - }); + const ariaLabel = i18n.translate( + 'kbn.discover.docViews.table.noCachedMappingForThisFieldAriaLabel', + { + defaultMessage: 'Warning', + } + ); + const tooltipContent = i18n.translate( + 'kbn.discover.docViews.table.noCachedMappingForThisFieldTooltip', + { + defaultMessage: + 'No cached mapping for this field. Refresh field list from the Management > Index Patterns page', + } + ); return ( void> { const $injector = await chrome.dangerouslyGetActiveInjector(); const rootScope: AngularScope = $injector.get('$rootScope'); @@ -68,7 +69,7 @@ export async function injectAngularElement( * Converts a given legacy angular directive to a render function * for usage in a react component. Note that the rendering is async */ -export function convertDirectiveToRenderFn(directive: AngularDirective) { +export function convertDirectiveToRenderFn(directive: AngularDirective, chrome: Chrome) { return (domNode: Element, props: DocViewRenderProps) => { let rejected = false; @@ -76,7 +77,8 @@ export function convertDirectiveToRenderFn(directive: AngularDirective) { domNode, directive.template, props, - directive.controller + directive.controller, + chrome ); cleanupFnPromise.catch(e => { rejected = true; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_registry.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_registry.ts new file mode 100644 index 00000000000000..1952ec3af2f6cd --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_registry.ts @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { convertDirectiveToRenderFn } from './doc_views_helpers'; +import { DocView, DocViewInput, ElasticSearchHit, DocViewInputFn } from './doc_views_types'; +import { Chrome } from '../../kibana_services'; + +export class DocViewsRegistry { + private docViews: DocView[] = []; + + constructor(private legacyChrome: Chrome) {} + + /** + * Extends and adds the given doc view to the registry array + */ + addDocView(docViewRaw: DocViewInput | DocViewInputFn) { + const docView = typeof docViewRaw === 'function' ? docViewRaw() : docViewRaw; + if (docView.directive) { + // convert angular directive to render function for backwards compatibility + docView.render = convertDirectiveToRenderFn(docView.directive, this.legacyChrome); + } + if (typeof docView.shouldShow !== 'function') { + docView.shouldShow = () => true; + } + this.docViews.push(docView as DocView); + } + /** + * Returns a sorted array of doc_views for rendering tabs + */ + getDocViewsSorted(hit: ElasticSearchHit) { + return this.docViews + .filter(docView => docView.shouldShow(hit)) + .sort((a, b) => (Number(a.order) > Number(b.order) ? 1 : -1)); + } +} diff --git a/src/legacy/ui/public/registry/doc_views_types.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_types.ts similarity index 97% rename from src/legacy/ui/public/registry/doc_views_types.ts rename to src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_types.ts index eb2a5bdc4b3b75..92e18e7ea7b888 100644 --- a/src/legacy/ui/public/registry/doc_views_types.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_types.ts @@ -18,7 +18,7 @@ */ import { ComponentType } from 'react'; import { IScope } from 'angular'; -import { IndexPattern } from '../../../../plugins/data/public'; +import { IndexPattern } from '../../kibana_services'; export interface AngularDirective { controller: (scope: AngularScope) => void; diff --git a/src/legacy/core_plugins/kibana/public/discover/plugin.ts b/src/legacy/core_plugins/kibana/public/discover/plugin.ts index 0cff1e66f3636c..8f1eb7ef755597 100644 --- a/src/legacy/core_plugins/kibana/public/discover/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/discover/plugin.ts @@ -16,20 +16,25 @@ * specific language governing permissions and limitations * under the License. */ +import { i18n } from '@kbn/i18n'; import { AppMountParameters, CoreSetup, CoreStart, Plugin } from 'kibana/public'; import angular from 'angular'; -import { IUiActionsStart } from 'src/plugins/ui_actions/public'; +import { IUiActionsSetup, IUiActionsStart } from 'src/plugins/ui_actions/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { registerFeature } from './np_ready/register_feature'; import './kibana_services'; import { IEmbeddableStart, IEmbeddableSetup } from '../../../../../plugins/embeddable/public'; import { getInnerAngularModule, getInnerAngularModuleEmbeddable } from './get_inner_angular'; -import { setAngularModule, setServices } from './kibana_services'; +import { Chrome, setAngularModule, setServices } from './kibana_services'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; import { EuiUtilsStart } from '../../../../../plugins/eui_utils/public'; import { buildServices } from './build_services'; import { SharePluginStart } from '../../../../../plugins/share/public'; import { KibanaLegacySetup } from '../../../../../plugins/kibana_legacy/public'; +import { DocViewsRegistry } from './np_ready/doc_views/doc_views_registry'; +import { DocViewInput, DocViewInputFn } from './np_ready/doc_views/doc_views_types'; +import { DocViewTable } from './np_ready/components/table/table'; +import { JsonCodeBlock } from './np_ready/components/json_code_block/json_code_block'; import { HomePublicPluginSetup } from '../../../../../plugins/home/public'; /** @@ -37,12 +42,17 @@ import { HomePublicPluginSetup } from '../../../../../plugins/home/public'; * for other plugins to use in _their_ `SetupDeps`/`StartDeps` interfaces. * @public */ -export type DiscoverSetup = void; +export interface DiscoverSetup { + addDocView(docViewRaw: DocViewInput | DocViewInputFn): void; +} export type DiscoverStart = void; export interface DiscoverSetupPlugins { - uiActions: IUiActionsStart; + uiActions: IUiActionsSetup; embeddable: IEmbeddableSetup; kibana_legacy: KibanaLegacySetup; + __LEGACY: { + chrome: Chrome; + }; home: HomePublicPluginSetup; } export interface DiscoverStartPlugins { @@ -65,13 +75,30 @@ const embeddableAngularName = 'app/discoverEmbeddable'; export class DiscoverPlugin implements Plugin { private servicesInitialized: boolean = false; private innerAngularInitialized: boolean = false; + private docViewsRegistry: DocViewsRegistry | null = null; /** * why are those functions public? they are needed for some mocha tests * can be removed once all is Jest */ public initializeInnerAngular?: () => void; public initializeServices?: () => void; + setup(core: CoreSetup, plugins: DiscoverSetupPlugins): DiscoverSetup { + this.docViewsRegistry = new DocViewsRegistry(plugins.__LEGACY.chrome); + this.docViewsRegistry.addDocView({ + title: i18n.translate('kbn.discover.docViews.table.tableTitle', { + defaultMessage: 'Table', + }), + order: 10, + component: DocViewTable, + }); + this.docViewsRegistry.addDocView({ + title: i18n.translate('kbn.discover.docViews.json.jsonTitle', { + defaultMessage: 'JSON', + }), + order: 20, + component: JsonCodeBlock, + }); plugins.kibana_legacy.registerLegacyApp({ id: 'discover', title: 'Discover', @@ -91,6 +118,10 @@ export class DiscoverPlugin implements Plugin { }, }); registerFeature(plugins.home); + + return { + addDocView: this.docViewsRegistry.addDocView.bind(this.docViewsRegistry), + }; } start(core: CoreStart, plugins: DiscoverStartPlugins): DiscoverStart { @@ -112,7 +143,7 @@ export class DiscoverPlugin implements Plugin { if (this.servicesInitialized) { return; } - const services = await buildServices(core, plugins); + const services = await buildServices(core, plugins, this.docViewsRegistry!); setServices(services); this.servicesInitialized = true; }; diff --git a/src/legacy/ui/public/registry/doc_views.ts b/src/legacy/ui/public/registry/doc_views.ts deleted file mode 100644 index bf1e8416ae66d8..00000000000000 --- a/src/legacy/ui/public/registry/doc_views.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { convertDirectiveToRenderFn } from './doc_views_helpers'; -import { DocView, DocViewInput, ElasticSearchHit, DocViewInputFn } from './doc_views_types'; - -export { DocViewRenderProps, DocView, DocViewRenderFn } from './doc_views_types'; - -export interface DocViewsRegistry { - docViews: DocView[]; - addDocView: (docView: DocViewInput) => void; - getDocViewsSorted: (hit: ElasticSearchHit) => DocView[]; -} - -export const docViews: DocView[] = []; - -/** - * Extends and adds the given doc view to the registry array - */ -export function addDocView(docView: DocViewInput) { - if (docView.directive) { - // convert angular directive to render function for backwards compatibility - docView.render = convertDirectiveToRenderFn(docView.directive); - } - if (typeof docView.shouldShow !== 'function') { - docView.shouldShow = () => true; - } - docViews.push(docView as DocView); -} - -/** - * Empty array of doc views for testing - */ -export function emptyDocViews() { - docViews.length = 0; -} - -/** - * Returns a sorted array of doc_views for rendering tabs - */ -export function getDocViewsSorted(hit: ElasticSearchHit): DocView[] { - return docViews - .filter(docView => docView.shouldShow(hit)) - .sort((a, b) => (Number(a.order) > Number(b.order) ? 1 : -1)); -} -/** - * Provider for compatibility with 3rd Party plugins - */ -export const DocViewsRegistryProvider = { - register: (docViewRaw: DocViewInput | DocViewInputFn) => { - const docView = typeof docViewRaw === 'function' ? docViewRaw() : docViewRaw; - addDocView(docView); - }, -}; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index af43110a8ba5e8..09d71814e5bf09 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -1850,6 +1850,25 @@ "kbn.discover.discoverDescription": "ドキュメントにクエリをかけたりフィルターを適用することで、データをインタラクティブに閲覧できます。", "kbn.discover.discoverTitle": "ディスカバー", "kbn.discover.documentsAriaLabel": "ドキュメント", + "kbn.discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedTooltip": "{underscoreSign} で始まるフィールド名はサポートされていません", + "kbn.discover.docViews.table.filterForFieldPresentButtonAriaLabel": "現在のフィールドのフィルター", + "kbn.discover.docViews.table.filterForFieldPresentButtonTooltip": "現在のフィールドのフィルター", + "kbn.discover.docViews.table.filterForValueButtonAriaLabel": "値でフィルタリング", + "kbn.discover.docViews.table.filterForValueButtonTooltip": "値でフィルタリング", + "kbn.discover.docViews.table.filterOutValueButtonAriaLabel": "値を除外", + "kbn.discover.docViews.table.filterOutValueButtonTooltip": "値を除外します", + "kbn.discover.docViews.table.noCachedMappingForThisFieldTooltip": "このフィールドのキャッシュされたマッピングがありません。管理 > インデックスパターンページからフィールドリストを更新してください", + "kbn.discover.docViews.table.tableTitle": "表", + "kbn.discover.docViews.table.toggleColumnInTableButtonAriaLabel": "表の列を切り替える", + "kbn.discover.docViews.table.toggleColumnInTableButtonTooltip": "表の列を切り替える", + "kbn.discover.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "メタフィールドの有無でフィルタリングできません", + "kbn.discover.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "スクリプトフィールドの有無でフィルタリングできません", + "kbn.discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "インデックスされていないフィールドは検索できません", + "kbn.discover.docViews.json.codeEditorAriaLabel": "Elasticsearch ドキュメントの JSON ビューのみを読み込む", + "kbn.discover.docViews.json.jsonTitle": "JSON", + "kbn.discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedAriaLabel": "警告", + "kbn.discover.docViews.table.noCachedMappingForThisFieldAriaLabel": "警告", + "kbn.discover.docViews.table.toggleFieldDetails": "フィールド詳細を切り替える", "kbn.discover.errorLoadingData": "データの読み込み中にエラーが発生", "kbn.discover.fetchError.howToAddressErrorDescription": "このエラーは、{scriptedFields} タブにある {managementLink} の {fetchErrorScript} フィールドを編集することで解決できます。", "kbn.discover.fetchError.managmentLinkText": "管理 > インデックスパターン", @@ -2834,25 +2853,6 @@ "kbn.advancedSettings.courier.batchSearchesText": "無効の場合、ダッシュボードパネルは個々に読み込まれ、検索リクエストはユーザーが移動するか\n クエリを更新すると停止します。有効の場合、ダッシュボードパネルはすべてのデータが読み込まれると同時に読み込まれ、\n 検索は停止しません。", "kbn.doc.couldNotFindDocumentsDescription": "その ID に一致するドキュメントがありません。", "kbn.doc.somethingWentWrongDescription": "{indexName} が欠けています。", - "kbnDocViews.table.fieldNamesBeginningWithUnderscoreUnsupportedTooltip": "{underscoreSign} で始まるフィールド名はサポートされていません", - "kbnDocViews.table.filterForFieldPresentButtonAriaLabel": "現在のフィールドのフィルター", - "kbnDocViews.table.filterForFieldPresentButtonTooltip": "現在のフィールドのフィルター", - "kbnDocViews.table.filterForValueButtonAriaLabel": "値でフィルタリング", - "kbnDocViews.table.filterForValueButtonTooltip": "値でフィルタリング", - "kbnDocViews.table.filterOutValueButtonAriaLabel": "値を除外", - "kbnDocViews.table.filterOutValueButtonTooltip": "値を除外します", - "kbnDocViews.table.noCachedMappingForThisFieldTooltip": "このフィールドのキャッシュされたマッピングがありません。管理 > インデックスパターンページからフィールドリストを更新してください", - "kbnDocViews.table.tableTitle": "表", - "kbnDocViews.table.toggleColumnInTableButtonAriaLabel": "表の列を切り替える", - "kbnDocViews.table.toggleColumnInTableButtonTooltip": "表の列を切り替える", - "kbnDocViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "メタフィールドの有無でフィルタリングできません", - "kbnDocViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "スクリプトフィールドの有無でフィルタリングできません", - "kbnDocViews.table.unindexedFieldsCanNotBeSearchedTooltip": "インデックスされていないフィールドは検索できません", - "kbnDocViews.json.codeEditorAriaLabel": "Elasticsearch ドキュメントの JSON ビューのみを読み込む", - "kbnDocViews.json.jsonTitle": "JSON", - "kbnDocViews.table.fieldNamesBeginningWithUnderscoreUnsupportedAriaLabel": "警告", - "kbnDocViews.table.noCachedMappingForThisFieldAriaLabel": "警告", - "kbnDocViews.table.toggleFieldDetails": "フィールド詳細を切り替える", "kbnVislibVisTypes.area.areaDescription": "折れ線グラフの下の数量を強調します。", "kbnVislibVisTypes.area.areaTitle": "エリア", "kbnVislibVisTypes.area.groupTitle": "系列を分割", @@ -12702,4 +12702,4 @@ "xpack.licensing.welcomeBanner.licenseIsExpiredDescription.updateYourLicenseLinkText": "ライセンスを更新", "xpack.licensing.welcomeBanner.licenseIsExpiredTitle": "ご使用の {licenseType} ライセンスは期限切れです" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 0306edcabd67d2..e221cba874bcdb 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -1851,6 +1851,25 @@ "kbn.discover.discoverDescription": "通过查询和筛选原始文档来以交互方式浏览您的数据。", "kbn.discover.discoverTitle": "Discover", "kbn.discover.documentsAriaLabel": "文档", + "kbn.discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedTooltip": "不支持以 {underscoreSign} 开头的字段名称", + "kbn.discover.docViews.table.filterForFieldPresentButtonAriaLabel": "筛留存在的字段", + "kbn.discover.docViews.table.filterForFieldPresentButtonTooltip": "筛留存在的字段", + "kbn.discover.docViews.table.filterForValueButtonAriaLabel": "筛留值", + "kbn.discover.docViews.table.filterForValueButtonTooltip": "筛留值", + "kbn.discover.docViews.table.filterOutValueButtonAriaLabel": "筛除值", + "kbn.discover.docViews.table.filterOutValueButtonTooltip": "筛除值", + "kbn.discover.docViews.table.noCachedMappingForThisFieldTooltip": "此字段没有任何已缓存映射。从“管理”>“索引模式”页面刷新字段列表", + "kbn.discover.docViews.table.tableTitle": "表", + "kbn.discover.docViews.table.toggleColumnInTableButtonAriaLabel": "在表中切换列", + "kbn.discover.docViews.table.toggleColumnInTableButtonTooltip": "在表中切换列", + "kbn.discover.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "无法筛留元数据字段", + "kbn.discover.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "无法筛留脚本字段", + "kbn.discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "无法搜索未索引字段", + "kbn.discover.docViews.json.codeEditorAriaLabel": "Elasticsearch 文档的只读 JSON 视图", + "kbn.discover.docViews.json.jsonTitle": "JSON", + "kbn.discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedAriaLabel": "警告", + "kbn.discover.docViews.table.noCachedMappingForThisFieldAriaLabel": "警告", + "kbn.discover.docViews.table.toggleFieldDetails": "切换字段详细信息", "kbn.discover.errorLoadingData": "加载数据时出错", "kbn.discover.fetchError.howToAddressErrorDescription": "您可以通过编辑 “{scriptedFields}” 选项卡下 “{managementLink}” 中的 “{fetchErrorScript}” 字段来解决此错误。", "kbn.discover.fetchError.managmentLinkText": "管理 > 索引模式", @@ -2835,25 +2854,6 @@ "kbn.advancedSettings.courier.batchSearchesText": "禁用时,仪表板面板将分别加载,用户离开时或更新查询时,\n 搜索请求将终止。启用时,仪表板面板将一起加载并加载所有数据,\n 搜索将不会终止。", "kbn.doc.couldNotFindDocumentsDescription": "无文档匹配该 ID。", "kbn.doc.somethingWentWrongDescription": "{indexName} 缺失。", - "kbnDocViews.table.fieldNamesBeginningWithUnderscoreUnsupportedTooltip": "不支持以 {underscoreSign} 开头的字段名称", - "kbnDocViews.table.filterForFieldPresentButtonAriaLabel": "筛留存在的字段", - "kbnDocViews.table.filterForFieldPresentButtonTooltip": "筛留存在的字段", - "kbnDocViews.table.filterForValueButtonAriaLabel": "筛留值", - "kbnDocViews.table.filterForValueButtonTooltip": "筛留值", - "kbnDocViews.table.filterOutValueButtonAriaLabel": "筛除值", - "kbnDocViews.table.filterOutValueButtonTooltip": "筛除值", - "kbnDocViews.table.noCachedMappingForThisFieldTooltip": "此字段没有任何已缓存映射。从“管理”>“索引模式”页面刷新字段列表", - "kbnDocViews.table.tableTitle": "表", - "kbnDocViews.table.toggleColumnInTableButtonAriaLabel": "在表中切换列", - "kbnDocViews.table.toggleColumnInTableButtonTooltip": "在表中切换列", - "kbnDocViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "无法筛留元数据字段", - "kbnDocViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "无法筛留脚本字段", - "kbnDocViews.table.unindexedFieldsCanNotBeSearchedTooltip": "无法搜索未索引字段", - "kbnDocViews.json.codeEditorAriaLabel": "Elasticsearch 文档的只读 JSON 视图", - "kbnDocViews.json.jsonTitle": "JSON", - "kbnDocViews.table.fieldNamesBeginningWithUnderscoreUnsupportedAriaLabel": "警告", - "kbnDocViews.table.noCachedMappingForThisFieldAriaLabel": "警告", - "kbnDocViews.table.toggleFieldDetails": "切换字段详细信息", "kbnVislibVisTypes.area.areaDescription": "突出折线图下方的数量", "kbnVislibVisTypes.area.areaTitle": "面积图", "kbnVislibVisTypes.area.groupTitle": "拆分序列", @@ -12791,4 +12791,4 @@ "xpack.licensing.welcomeBanner.licenseIsExpiredDescription.updateYourLicenseLinkText": "更新您的许可", "xpack.licensing.welcomeBanner.licenseIsExpiredTitle": "您的{licenseType}许可已过期" } -} \ No newline at end of file +} From 28b6efa260e6170bd46e8d898fc1698b0437bde9 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Tue, 7 Jan 2020 11:31:15 -0500 Subject: [PATCH 03/83] Fix linting issues (#54068) Co-authored-by: Elastic Machine --- .eslintrc.js | 21 ------------------- x-pack/legacy/plugins/monitoring/index.js | 2 +- .../public/components/chart/chart_target.js | 2 +- .../components/chart/chart_target.test.js | 4 ++-- .../shard_allocation/components/assigned.js | 3 +++ .../pipeline_viewer/views/detail_drawer.js | 6 +++--- .../public/services/executor_provider.js | 2 +- .../public/views/elasticsearch/nodes/index.js | 1 + .../views/logstash/node/pipelines/index.js | 1 + .../public/views/logstash/pipelines/index.js | 1 + .../monitoring/server/cloud/cloud_service.js | 2 +- .../lib/metrics/elasticsearch/classes.js | 2 +- .../server/lib/metrics/logstash/classes.js | 4 ++-- 13 files changed, 18 insertions(+), 33 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 03a674993ab507..5892d20e61e8ce 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -177,12 +177,6 @@ module.exports = { 'react-hooks/exhaustive-deps': 'off', }, }, - { - files: ['x-pack/legacy/plugins/monitoring/**/*.{js,ts,tsx}'], - rules: { - 'jsx-a11y/click-events-have-key-events': 'off', - }, - }, { files: ['x-pack/legacy/plugins/snapshot_restore/**/*.{js,ts,tsx}'], rules: { @@ -814,21 +808,6 @@ module.exports = { }, }, - /** - * Monitoring overrides - */ - { - files: ['x-pack/legacy/plugins/monitoring/**/*.js'], - rules: { - 'no-unused-vars': ['error', { args: 'all', argsIgnorePattern: '^_' }], - 'no-else-return': 'error', - }, - }, - { - files: ['x-pack/legacy/plugins/monitoring/public/**/*.js'], - env: { browser: true }, - }, - /** * Canvas overrides */ diff --git a/x-pack/legacy/plugins/monitoring/index.js b/x-pack/legacy/plugins/monitoring/index.js index 3d98b11c2045b1..8e0201bea710bc 100644 --- a/x-pack/legacy/plugins/monitoring/index.js +++ b/x-pack/legacy/plugins/monitoring/index.js @@ -22,7 +22,7 @@ export const monitoring = kibana => id: 'monitoring', configPrefix: 'xpack.monitoring', publicDir: resolve(__dirname, 'public'), - init(server, _options) { + init(server) { const configs = [ 'xpack.monitoring.ui.enabled', 'xpack.monitoring.kibana.collection.enabled', diff --git a/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.js b/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.js index c3ca241c73cc02..5c9cddf9c29022 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.js +++ b/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.js @@ -46,7 +46,7 @@ export class ChartTarget extends React.Component { return seriesToShow.some(id => id.toLowerCase() === metric.id.toLowerCase()); }; } - return _metric => true; + return () => true; } UNSAFE_componentWillReceiveProps(newProps) { diff --git a/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.test.js b/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.test.js index bf0d5fdd248792..56eb52fa862350 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.test.js +++ b/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.test.js @@ -38,8 +38,8 @@ const props = { max: 1562962539851, }, hasLegend: true, - onBrush: _ => void 0, - tickFormatter: _ => void 0, + onBrush: () => void 0, + tickFormatter: () => void 0, updateLegend: () => void 0, }; diff --git a/x-pack/legacy/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/assigned.js b/x-pack/legacy/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/assigned.js index 012bc81135e341..897c20edc3f74a 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/assigned.js +++ b/x-pack/legacy/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/assigned.js @@ -46,6 +46,8 @@ export class Assigned extends React.Component { // TODO: redesign for shard allocation, possibly giving shard display the // ability to use the euiLink CSS class (blue link text instead of white link text) + // Disabling eslint because EuiKeyboardAccessible does it for us + /* eslint-disable jsx-a11y/click-events-have-key-events */ const name = ( @@ -53,6 +55,7 @@ export class Assigned extends React.Component { ); + /* eslint-enable jsx-a11y/click-events-have-key-events */ const master = data.node_type === 'master' ? : null; const shards = sortBy(data.children, 'shard').map(this.createShard); diff --git a/x-pack/legacy/plugins/monitoring/public/components/logstash/pipeline_viewer/views/detail_drawer.js b/x-pack/legacy/plugins/monitoring/public/components/logstash/pipeline_viewer/views/detail_drawer.js index cd9fe5229b6408..73faa81af7b55c 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/logstash/pipeline_viewer/views/detail_drawer.js +++ b/x-pack/legacy/plugins/monitoring/public/components/logstash/pipeline_viewer/views/detail_drawer.js @@ -164,7 +164,7 @@ function renderPluginBasicStats(vertex, timeseriesTooltipXValueFormatter) { ); } -function renderIfBasicStats(_vertex) { +function renderIfBasicStats() { return (

{ + _api; // to fix eslint const $http = $injector.get('$http'); const globalState = $injector.get('globalState'); const timeBounds = timefilter.getBounds(); diff --git a/x-pack/legacy/plugins/monitoring/public/views/logstash/node/pipelines/index.js b/x-pack/legacy/plugins/monitoring/public/views/logstash/node/pipelines/index.js index bc5ac75931fce5..7bfcddf8f283a6 100644 --- a/x-pack/legacy/plugins/monitoring/public/views/logstash/node/pipelines/index.js +++ b/x-pack/legacy/plugins/monitoring/public/views/logstash/node/pipelines/index.js @@ -23,6 +23,7 @@ import { DetailStatus } from '../../../../components/logstash/detail_status'; import { CODE_PATH_LOGSTASH } from '../../../../../common/constants'; const getPageData = ($injector, _api = undefined, routeOptions = {}) => { + _api; // fixing eslint const $route = $injector.get('$route'); const $http = $injector.get('$http'); const globalState = $injector.get('globalState'); diff --git a/x-pack/legacy/plugins/monitoring/public/views/logstash/pipelines/index.js b/x-pack/legacy/plugins/monitoring/public/views/logstash/pipelines/index.js index ce49fc2fac97bf..03cf7383d1d023 100644 --- a/x-pack/legacy/plugins/monitoring/public/views/logstash/pipelines/index.js +++ b/x-pack/legacy/plugins/monitoring/public/views/logstash/pipelines/index.js @@ -23,6 +23,7 @@ import { CODE_PATH_LOGSTASH } from '../../../../common/constants'; */ const getPageData = ($injector, _api = undefined, routeOptions = {}) => { + _api; // to fix eslint const $http = $injector.get('$http'); const globalState = $injector.get('globalState'); const Private = $injector.get('Private'); diff --git a/x-pack/legacy/plugins/monitoring/server/cloud/cloud_service.js b/x-pack/legacy/plugins/monitoring/server/cloud/cloud_service.js index dcc8ad8fc8b64d..2a408f5295aef8 100644 --- a/x-pack/legacy/plugins/monitoring/server/cloud/cloud_service.js +++ b/x-pack/legacy/plugins/monitoring/server/cloud/cloud_service.js @@ -48,7 +48,7 @@ export class CloudService { * @param {Object} _request 'request' HTTP handler. * @return {Promise} Never {@code null} {@code CloudServiceResponse}. */ - _checkIfService(_request) { + _checkIfService() { return Promise.reject(new Error('not implemented')); } diff --git a/x-pack/legacy/plugins/monitoring/server/lib/metrics/elasticsearch/classes.js b/x-pack/legacy/plugins/monitoring/server/lib/metrics/elasticsearch/classes.js index 755b89a0409d02..d3a43ed6518278 100644 --- a/x-pack/legacy/plugins/monitoring/server/lib/metrics/elasticsearch/classes.js +++ b/x-pack/legacy/plugins/monitoring/server/lib/metrics/elasticsearch/classes.js @@ -116,7 +116,7 @@ export class LatencyMetric extends ElasticsearchMetric { }, }; - this.calculation = (bucket, _key, _metric, _bucketSizeInSeconds) => { + this.calculation = bucket => { const timeInMillisDeriv = _.get(bucket, 'event_time_in_millis_deriv.normalized_value', null); const totalEventsDeriv = _.get(bucket, 'event_total_deriv.normalized_value', null); diff --git a/x-pack/legacy/plugins/monitoring/server/lib/metrics/logstash/classes.js b/x-pack/legacy/plugins/monitoring/server/lib/metrics/logstash/classes.js index c76edf90613963..eddcfabe83b1be 100644 --- a/x-pack/legacy/plugins/monitoring/server/lib/metrics/logstash/classes.js +++ b/x-pack/legacy/plugins/monitoring/server/lib/metrics/logstash/classes.js @@ -90,7 +90,7 @@ export class LogstashEventsLatencyClusterMetric extends LogstashClusterMetric { }, }; - this.calculation = (bucket, _key, _metric, _bucketSizeInSeconds) => { + this.calculation = bucket => { const timeInMillisDeriv = _.get(bucket, 'events_time_in_millis_deriv.normalized_value', null); const totalEventsDeriv = _.get(bucket, 'events_total_deriv.normalized_value', null); @@ -189,7 +189,7 @@ export class LogstashEventsLatencyMetric extends LogstashMetric { }, }; - this.calculation = (bucket, _key, _metric, _bucketSizeInSeconds) => { + this.calculation = bucket => { const timeInMillisDeriv = _.get(bucket, 'events_time_in_millis_deriv.normalized_value', null); const totalEventsDeriv = _.get(bucket, 'events_total_deriv.normalized_value', null); From cca454f7aa11e894c0c12c3aca8d96c2bcb759a2 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Tue, 7 Jan 2020 16:36:18 +0000 Subject: [PATCH 04/83] Changing background color to align with EUI color (#54060) * Changing background color to align with EUI color * Removing background-color from theme --- src/core/server/rendering/views/styles.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/core/server/rendering/views/styles.tsx b/src/core/server/rendering/views/styles.tsx index f41627bcfe07ff..dfcb4213d90f71 100644 --- a/src/core/server/rendering/views/styles.tsx +++ b/src/core/server/rendering/views/styles.tsx @@ -28,8 +28,6 @@ interface Props { } export const Styles: FunctionComponent = ({ darkMode }) => { - const themeBackground = darkMode ? '#25262e' : '#f5f7fa'; - return (