From 2bfae1d1cb9cef36b2445a36cd06a9908ab2c015 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 18 Oct 2019 10:22:37 +0100 Subject: [PATCH 01/29] [ML] Fixing missing advanced job summary items (#48537) * [ML] Fixing missing advanced job summary items * updating translations --- .../common/job_creator/util/constants.ts | 1 + .../query_delay/query_delay_input.tsx | 3 +- .../scroll_size/scroll_size_input.tsx | 2 +- .../advanced_view/advanced_view.tsx | 22 +++-- .../advanced_view/detector_list.tsx | 3 +- .../advanced_view/metric_selection.tsx | 2 +- .../metric_selection_summary.tsx | 13 +++ .../multi_metric_view/multi_metric_view.tsx | 6 +- .../population_view/population_view.tsx | 6 +- .../single_metric_view/single_metric_view.tsx | 6 +- .../pick_fields_step/pick_fields.tsx | 4 +- .../summary_step/components/common.tsx | 51 +++++++++++ .../datafeed_details/datafeed_details.tsx | 88 +++++++++++++++++++ .../components/datafeed_details/index.ts | 6 ++ .../detector_chart}/detector_chart.tsx | 12 +-- .../components/detector_chart/index.ts | 7 ++ .../components/job_details/index.ts | 6 ++ .../job_details}/job_details.tsx | 72 ++++++++++----- .../pages/components/summary_step/summary.tsx | 20 ++++- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 21 files changed, 276 insertions(+), 58 deletions(-) create mode 100644 x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/metric_selection_summary.tsx create mode 100644 x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/common.tsx create mode 100644 x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/datafeed_details/datafeed_details.tsx create mode 100644 x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/datafeed_details/index.ts rename x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/{ => components/detector_chart}/detector_chart.tsx (55%) create mode 100644 x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/detector_chart/index.ts create mode 100644 x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/index.ts rename x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/{ => components/job_details}/job_details.tsx (75%) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/constants.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/constants.ts index f00877b1d1bef..004824bef1c9d 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/constants.ts +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/constants.ts @@ -19,5 +19,6 @@ export enum CREATED_BY_LABEL { export const DEFAULT_MODEL_MEMORY_LIMIT = '10MB'; export const DEFAULT_BUCKET_SPAN = '15m'; +export const DEFAULT_QUERY_DELAY = '60s'; export const SHARED_RESULTS_INDEX_NAME = 'shared'; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/query_delay/query_delay_input.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/query_delay/query_delay_input.tsx index 65601562b22ad..097050fd829c9 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/query_delay/query_delay_input.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/query_delay/query_delay_input.tsx @@ -9,8 +9,7 @@ import { EuiFieldText } from '@elastic/eui'; import { JobCreatorContext } from '../../../job_creator_context'; import { Description } from './description'; import { useStringifiedValue } from '../hooks'; - -const DEFAULT_QUERY_DELAY = '60s'; +import { DEFAULT_QUERY_DELAY } from '../../../../../common/job_creator/util/constants'; export const QueryDelayInput: FC = () => { const { jobCreator, jobCreatorUpdate, jobValidator, jobValidatorUpdated } = useContext( diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/scroll_size/scroll_size_input.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/scroll_size/scroll_size_input.tsx index bc3b90688a78a..da6a19434135c 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/scroll_size/scroll_size_input.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/scroll_size/scroll_size_input.tsx @@ -6,7 +6,7 @@ import React, { FC, useState, useContext, useEffect } from 'react'; import { EuiFieldNumber } from '@elastic/eui'; -import { newJobDefaults } from '../../../../../../new_job_new/utils/new_job_defaults'; +import { newJobDefaults } from '../../../../../utils/new_job_defaults'; import { JobCreatorContext } from '../../../job_creator_context'; import { Description } from './description'; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/advanced_view.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/advanced_view.tsx index 9e087dc4bd3e4..044bb7e83e941 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/advanced_view.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/advanced_view.tsx @@ -8,14 +8,16 @@ import React, { Fragment, FC, useEffect, useState } from 'react'; import { EuiHorizontalRule } from '@elastic/eui'; import { AdvancedDetectors } from './metric_selection'; +import { AdvancedDetectorsSummary } from './metric_selection_summary'; import { AdvancedSettings } from './settings'; import { ExtraSettings } from './extra'; interface Props { + isActive: boolean; setCanProceed?: (proceed: boolean) => void; } -export const AdvancedView: FC = ({ setCanProceed }) => { +export const AdvancedView: FC = ({ isActive, setCanProceed }) => { const [metricsValid, setMetricValid] = useState(false); const [settingsValid, setSettingsValid] = useState(false); @@ -27,13 +29,17 @@ export const AdvancedView: FC = ({ setCanProceed }) => { return ( - - - - - - - + {isActive === false ? ( + + ) : ( + + + + + + + + )} ); }; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx index d824e18d39d36..2500cf79535d9 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx @@ -25,11 +25,12 @@ import { AdvancedJobCreator } from '../../../../../common/job_creator'; import { detectorToString } from '../../../../../../../util/string_utils'; interface Props { + isActive: boolean; onEditJob: (i: number) => void; onDeleteJob: (i: number) => void; } -export const DetectorList: FC = ({ onEditJob, onDeleteJob }) => { +export const DetectorList: FC = ({ isActive, onEditJob, onDeleteJob }) => { const { jobCreator: jc, jobCreatorUpdated } = useContext(JobCreatorContext); const jobCreator = jc as AdvancedJobCreator; const [detectors, setDetectors] = useState(jobCreator.detectors); diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/metric_selection.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/metric_selection.tsx index 42d6d4db8c665..a57858515b955 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/metric_selection.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/metric_selection.tsx @@ -85,7 +85,7 @@ export const AdvancedDetectors: FC = ({ setIsValid }) => { return ( - + ( + {}} onDeleteJob={() => {}} /> +); diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/multi_metric_view/multi_metric_view.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/multi_metric_view/multi_metric_view.tsx index 7ee5b88f70862..c17c1bb8c7cc4 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/multi_metric_view/multi_metric_view.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/multi_metric_view/multi_metric_view.tsx @@ -28,9 +28,9 @@ export const MultiMetricView: FC = ({ isActive, setCanProceed }) => { return ( - {isActive === false && } - - {isActive === true && ( + {isActive === false ? ( + + ) : ( diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/population_view/population_view.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/population_view/population_view.tsx index 7f6736d953022..4bb80bca959c1 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/population_view/population_view.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/population_view/population_view.tsx @@ -28,9 +28,9 @@ export const PopulationView: FC = ({ isActive, setCanProceed }) => { return ( - {isActive === false && } - - {isActive === true && ( + {isActive === false ? ( + + ) : ( {metricsValid && ( diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/single_metric_view/single_metric_view.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/single_metric_view/single_metric_view.tsx index bbd31d77748fc..f30770f2c2cd4 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/single_metric_view/single_metric_view.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/single_metric_view/single_metric_view.tsx @@ -28,9 +28,9 @@ export const SingleMetricView: FC = ({ isActive, setCanProceed }) => { return ( - {isActive === false && } - - {isActive === true && ( + {isActive === false ? ( + + ) : ( {metricsValid && ( diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/pick_fields.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/pick_fields.tsx index a96d84c482c9b..bdb2076086fd5 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/pick_fields.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/pick_fields.tsx @@ -47,7 +47,9 @@ export const PickFieldsStep: FC = ({ setCurrentStep, isCurrentStep }) {jobType === JOB_TYPE.POPULATION && ( )} - {jobType === JOB_TYPE.ADVANCED && } + {jobType === JOB_TYPE.ADVANCED && ( + + )} setCurrentStep( diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/common.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/common.tsx new file mode 100644 index 0000000000000..bbd30c7e32eea --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/common.tsx @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiTitle } from '@elastic/eui'; + +export interface ListItems { + title: string; + description: string | JSX.Element; +} + +export const trueLabel = i18n.translate('xpack.ml.newJob.wizard.summaryStep.trueLabel', { + defaultMessage: 'True', +}); + +export const falseLabel = i18n.translate('xpack.ml.newJob.wizard.summaryStep.falseLabel', { + defaultMessage: 'False', +}); + +export const defaultLabel = i18n.translate('xpack.ml.newJob.wizard.summaryStep.defaultString', { + defaultMessage: 'default', +}); + +export const JobSectionTitle: FC = () => ( + +

+ +

+
+); + +export const DatafeedSectionTitle: FC = () => ( + +

+ +

+
+); + +export const Italic: FC = ({ children }) => {children}; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/datafeed_details/datafeed_details.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/datafeed_details/datafeed_details.tsx new file mode 100644 index 0000000000000..1927fc430abcb --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/datafeed_details/datafeed_details.tsx @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC, useContext } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiFlexGroup, EuiFlexItem, EuiDescriptionList, EuiFormRow } from '@elastic/eui'; +import { JobCreatorContext } from '../../../job_creator_context'; +import { MLJobEditor } from '../../../../../../jobs_list/components/ml_job_editor'; +import { calculateDatafeedFrequencyDefaultSeconds } from '../../../../../../../../common/util/job_utils'; +import { DEFAULT_QUERY_DELAY } from '../../../../../common/job_creator/util/constants'; +import { newJobDefaults } from '../../../../../utils/new_job_defaults'; +import { ListItems, defaultLabel, Italic } from '../common'; + +const EDITOR_HEIGHT = '200px'; + +export const DatafeedDetails: FC = () => { + const { jobCreator } = useContext(JobCreatorContext); + const { datafeeds } = newJobDefaults(); + + const queryString = JSON.stringify(jobCreator.query, null, 2); + const defaultFrequency = calculateDatafeedFrequencyDefaultSeconds(jobCreator.bucketSpanMs / 1000); + const scrollSizeDefault = datafeeds.scroll_size || ''; + + const queryDelay = jobCreator.queryDelay || ( + {`${DEFAULT_QUERY_DELAY} (${defaultLabel})`} + ); + const frequency = jobCreator.frequency || ( + {`${defaultFrequency} (${defaultLabel})`} + ); + const scrollSize = + jobCreator.scrollSize !== null ? ( + `${jobCreator.scrollSize}` + ) : ( + {`${scrollSizeDefault} (${defaultLabel})`} + ); + + const datafeedDetails: ListItems[] = [ + { + title: i18n.translate('xpack.ml.newJob.wizard.summaryStep.datafeedDetails.timeField.title', { + defaultMessage: 'Time field', + }), + description: jobCreator.timeFieldName, + }, + { + title: i18n.translate('xpack.ml.newJob.wizard.summaryStep.datafeedDetails.queryDelay.title', { + defaultMessage: 'Query delay', + }), + description: queryDelay, + }, + + { + title: i18n.translate('xpack.ml.newJob.wizard.summaryStep.datafeedDetails.frequency.title', { + defaultMessage: 'Frequency', + }), + description: frequency, + }, + + { + title: i18n.translate('xpack.ml.newJob.wizard.summaryStep.datafeedDetails.scrollSize.title', { + defaultMessage: 'Scroll size', + }), + description: scrollSize, + }, + ]; + + const queryTitle = i18n.translate( + 'xpack.ml.newJob.wizard.summaryStep.datafeedDetails.query.title', + { + defaultMessage: 'Scroll size', + } + ); + + return ( + + + + + + + + + + + ); +}; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/datafeed_details/index.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/datafeed_details/index.ts new file mode 100644 index 0000000000000..86890e94768e2 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/datafeed_details/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +export { DatafeedDetails } from './datafeed_details'; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/detector_chart.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/detector_chart/detector_chart.tsx similarity index 55% rename from x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/detector_chart.tsx rename to x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/detector_chart/detector_chart.tsx index 93517b1fc6645..bf60eda2e81c3 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/detector_chart.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/detector_chart/detector_chart.tsx @@ -5,11 +5,12 @@ */ import React, { Fragment, FC, useContext } from 'react'; -import { JobCreatorContext } from '../job_creator_context'; -import { JOB_TYPE } from '../../../common/job_creator/util/constants'; -import { SingleMetricView } from '../pick_fields_step/components/single_metric_view'; -import { MultiMetricView } from '../pick_fields_step/components/multi_metric_view'; -import { PopulationView } from '../pick_fields_step/components/population_view'; +import { JobCreatorContext } from '../../../job_creator_context'; +import { JOB_TYPE } from '../../../../../common/job_creator/util/constants'; +import { SingleMetricView } from '../../../pick_fields_step/components/single_metric_view'; +import { MultiMetricView } from '../../../pick_fields_step/components/multi_metric_view'; +import { PopulationView } from '../../../pick_fields_step/components/population_view'; +import { AdvancedView } from '../../../pick_fields_step/components/advanced_view'; export const DetectorChart: FC = () => { const { jobCreator } = useContext(JobCreatorContext); @@ -19,6 +20,7 @@ export const DetectorChart: FC = () => { {jobCreator.type === JOB_TYPE.SINGLE_METRIC && } {jobCreator.type === JOB_TYPE.MULTI_METRIC && } {jobCreator.type === JOB_TYPE.POPULATION && } + {jobCreator.type === JOB_TYPE.ADVANCED && }
); }; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/detector_chart/index.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/detector_chart/index.ts new file mode 100644 index 0000000000000..8a8e2ee9c01ae --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/detector_chart/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { DetectorChart } from './detector_chart'; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/index.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/index.ts new file mode 100644 index 0000000000000..0f0677b5999f8 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +export { JobDetails } from './job_details'; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/job_details.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/job_details.tsx similarity index 75% rename from x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/job_details.tsx rename to x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/job_details.tsx index f475556977e2c..885ba92e5e0de 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/job_details.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/job_details.tsx @@ -8,16 +8,26 @@ import React, { FC, useContext } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlexGroup, EuiFlexItem, EuiDescriptionList } from '@elastic/eui'; -import { JobCreatorContext } from '../job_creator_context'; -import { isMultiMetricJobCreator, isPopulationJobCreator } from '../../../common/job_creator'; +import { JobCreatorContext } from '../../../job_creator_context'; +import { + isMultiMetricJobCreator, + isPopulationJobCreator, + isAdvancedJobCreator, +} from '../../../../../common/job_creator'; +import { newJobDefaults } from '../../../../../utils/new_job_defaults'; +import { ListItems, falseLabel, trueLabel, defaultLabel, Italic } from '../common'; export const JobDetails: FC = () => { const { jobCreator } = useContext(JobCreatorContext); + const { anomaly_detectors: anomalyDetectors } = newJobDefaults(); - interface ListItems { - title: string; - description: string | JSX.Element; - } + const modelMemoryLimitDefault = anomalyDetectors.model_memory_limit || ''; + const modelMemoryLimit = + jobCreator.modelMemoryLimit !== null ? ( + jobCreator.modelMemoryLimit + ) : ( + {`${modelMemoryLimitDefault} (${defaultLabel})`} + ); const jobDetails: ListItems[] = [ { @@ -34,12 +44,12 @@ export const JobDetails: FC = () => { jobCreator.description.length > 0 ? ( jobCreator.description ) : ( - + - + ), }, { @@ -50,12 +60,12 @@ export const JobDetails: FC = () => { jobCreator.groups.length > 0 ? ( jobCreator.groups.join(', ') ) : ( - + - + ), }, ]; @@ -78,12 +88,12 @@ export const JobDetails: FC = () => { isMultiMetricJobCreator(jobCreator) && jobCreator.splitField !== null ? ( jobCreator.splitField.name ) : ( - + - + ), }); } @@ -107,6 +117,30 @@ export const JobDetails: FC = () => { }); } + if (isAdvancedJobCreator(jobCreator) && jobCreator.categorizationFieldName !== null) { + detectorDetails.push({ + title: i18n.translate( + 'xpack.ml.newJob.wizard.summaryStep.jobDetails.categorizationField.title', + { + defaultMessage: 'Categorization field', + } + ), + description: jobCreator.categorizationFieldName, + }); + } + + if (isAdvancedJobCreator(jobCreator) && jobCreator.summaryCountFieldName !== null) { + detectorDetails.push({ + title: i18n.translate( + 'xpack.ml.newJob.wizard.summaryStep.jobDetails.summaryCountField.title', + { + defaultMessage: 'Summary count field', + } + ), + description: jobCreator.summaryCountFieldName, + }); + } + detectorDetails.push({ title: i18n.translate('xpack.ml.newJob.wizard.summaryStep.jobDetails.influencers.title', { defaultMessage: 'Influencers', @@ -115,23 +149,15 @@ export const JobDetails: FC = () => { jobCreator.influencers.length > 0 ? ( jobCreator.influencers.join(', ') ) : ( - + - + ), }); - const trueLabel = i18n.translate('xpack.ml.newJob.wizard.summaryStep.jobDetails.trueLabel', { - defaultMessage: 'True', - }); - - const falseLabel = i18n.translate('xpack.ml.newJob.wizard.summaryStep.jobDetails.falseLabel', { - defaultMessage: 'False', - }); - const advancedDetails: ListItems[] = [ { title: i18n.translate('xpack.ml.newJob.wizard.summaryStep.jobDetails.enableModelPlot.title', { @@ -155,7 +181,7 @@ export const JobDetails: FC = () => { defaultMessage: 'Model memory limit', } ), - description: jobCreator.modelMemoryLimit !== null ? jobCreator.modelMemoryLimit : '', + description: modelMemoryLimit, }, ]; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/summary.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/summary.tsx index ba63242042156..3f241f21a75e5 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/summary.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/summary.tsx @@ -24,9 +24,10 @@ import { mlJobService } from '../../../../../services/job_service'; import { JsonEditorFlyout, EDITOR_MODE } from '../common/json_editor_flyout'; import { DatafeedPreviewFlyout } from '../common/datafeed_preview_flyout'; import { JOB_TYPE } from '../../../common/job_creator/util/constants'; -import { isSingleMetricJobCreator } from '../../../common/job_creator'; -import { JobDetails } from './job_details'; -import { DetectorChart } from './detector_chart'; +import { isSingleMetricJobCreator, isAdvancedJobCreator } from '../../../common/job_creator'; +import { JobDetails } from './components/job_details'; +import { DatafeedDetails } from './components/datafeed_details'; +import { DetectorChart } from './components/detector_chart'; import { JobProgress } from './components/job_progress'; import { PostSaveOptions } from './components/post_save_options'; import { @@ -34,6 +35,7 @@ import { resetJob, advancedStartDatafeed, } from '../../../common/job_creator/util/general'; +import { JobSectionTitle, DatafeedSectionTitle } from './components/common'; export const SummaryStep: FC = ({ setCurrentStep, isCurrentStep }) => { const { jobCreator, jobValidator, jobValidatorUpdated, resultsLoader } = useContext( @@ -44,6 +46,8 @@ export const SummaryStep: FC = ({ setCurrentStep, isCurrentStep }) => const [isValid, setIsValid] = useState(jobValidator.validationSummary.basic); const [jobRunner, setJobRunner] = useState(null); + const isAdvanced = isAdvancedJobCreator(jobCreator); + useEffect(() => { jobCreator.subscribeToProgress(setProgress); }, []); @@ -117,12 +121,22 @@ export const SummaryStep: FC = ({ setCurrentStep, isCurrentStep }) => {isCurrentStep && ( + {isAdvanced && } + {isAdvanced && ( + + + + + + + )} + {progress < 100 && ( diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 1f48155128e17..351ebc3cb0e5f 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6895,7 +6895,6 @@ "xpack.ml.newJob.wizard.summaryStep.createJobError": "ジョブの作成エラー", "xpack.ml.newJob.wizard.summaryStep.jobDetails.bucketSpan.title": "バケットスパン", "xpack.ml.newJob.wizard.summaryStep.jobDetails.enableModelPlot.title": "モデルプロットを有効にする", - "xpack.ml.newJob.wizard.summaryStep.jobDetails.falseLabel": "False", "xpack.ml.newJob.wizard.summaryStep.jobDetails.groups.placeholder": "グループが選択されていません", "xpack.ml.newJob.wizard.summaryStep.jobDetails.groups.title": "グループ", "xpack.ml.newJob.wizard.summaryStep.jobDetails.influencers.placeholder": "影響因子が選択されていません", @@ -6908,7 +6907,6 @@ "xpack.ml.newJob.wizard.summaryStep.jobDetails.populationField.title": "集団フィールド", "xpack.ml.newJob.wizard.summaryStep.jobDetails.splitField.placeholder": "分割フィールドが選択されていません", "xpack.ml.newJob.wizard.summaryStep.jobDetails.splitField.title": "分割フィールド", - "xpack.ml.newJob.wizard.summaryStep.jobDetails.trueLabel": "True", "xpack.ml.newJob.wizard.summaryStep.jobDetails.useDedicatedIndex.title": "専用インデックスを使用", "xpack.ml.newJob.wizard.summaryStep.postSaveOptions.createWatch": "ウォッチを作成", "xpack.ml.newJob.wizard.summaryStep.postSaveOptions.startJobInRealTime": "リアルタイムで実行中のジョブを開始", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 9fe5ca801919f..7251a8931b78c 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6990,7 +6990,6 @@ "xpack.ml.newJob.wizard.summaryStep.createJobError": "作业创建错误", "xpack.ml.newJob.wizard.summaryStep.jobDetails.bucketSpan.title": "存储桶跨度", "xpack.ml.newJob.wizard.summaryStep.jobDetails.enableModelPlot.title": "启用模型绘图", - "xpack.ml.newJob.wizard.summaryStep.jobDetails.falseLabel": "False", "xpack.ml.newJob.wizard.summaryStep.jobDetails.groups.placeholder": "未选择组", "xpack.ml.newJob.wizard.summaryStep.jobDetails.groups.title": "组", "xpack.ml.newJob.wizard.summaryStep.jobDetails.influencers.placeholder": "未选择影响因素", @@ -7003,7 +7002,6 @@ "xpack.ml.newJob.wizard.summaryStep.jobDetails.populationField.title": "群体字段", "xpack.ml.newJob.wizard.summaryStep.jobDetails.splitField.placeholder": "未选择分割字段", "xpack.ml.newJob.wizard.summaryStep.jobDetails.splitField.title": "分割字段", - "xpack.ml.newJob.wizard.summaryStep.jobDetails.trueLabel": "True", "xpack.ml.newJob.wizard.summaryStep.jobDetails.useDedicatedIndex.title": "使用专用索引", "xpack.ml.newJob.wizard.summaryStep.postSaveOptions.createWatch": "创建监视", "xpack.ml.newJob.wizard.summaryStep.postSaveOptions.startJobInRealTime": "启动实时运行的作业", From 3c68b0b71d714547802008f16becd377d53f636f Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 18 Oct 2019 10:37:35 +0100 Subject: [PATCH 02/29] [ML] Fixing empty validation list in wizards (#48553) * [ML] Fixing empty validation list in wizards * updating translations * updating snapshot --- .../validate_job_view.test.js.snap | 26 ++++++----- .../validate_job/validate_job_view.js | 45 ++++++++++++++----- .../plugins/ml/public/services/job_service.js | 1 - 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/components/validate_job/__snapshots__/validate_job_view.test.js.snap b/x-pack/legacy/plugins/ml/public/components/validate_job/__snapshots__/validate_job_view.test.js.snap index 0968b42b92b48..9ba92a3aa1677 100644 --- a/x-pack/legacy/plugins/ml/public/components/validate_job/__snapshots__/validate_job_view.test.js.snap +++ b/x-pack/legacy/plugins/ml/public/components/validate_job/__snapshots__/validate_job_view.test.js.snap @@ -32,16 +32,18 @@ exports[`ValidateJob renders button and modal with a message 1`] = ` /> } > - @@ -130,6 +132,10 @@ exports[`ValidateJob renders the button and modal with a success message 1`] = ` /> } > + { + const callouts = messages + .filter(m => idFilterList.includes(m.id) === false) + .map((m, i) => ( + + )); + + // there could be no error or success messages due to the + // idFilterList being applied. so rather than showing nothing, + // show a message saying all passed + const allPassedCallout = (); + + return ( + + {callouts.length ? callouts : allPassedCallout} + + ); +}; +MessageList.propTypes = { + messages: PropTypes.array, + idFilterList: PropTypes.array, +}; + const Callout = ({ message }) => ( @@ -272,11 +302,8 @@ export class ValidateJob extends Component { values={{ title: this.state.title }} />} > - { - this.state.data.messages - .filter(m => idFilterList.includes(m.id) === false) - .map((m, i) => ) - } + + } {embedded === true && -
- { - this.state.data.messages - .filter(m => idFilterList.includes(m.id) === false) - .map((m, i) => ) - } -
+ }
); diff --git a/x-pack/legacy/plugins/ml/public/services/job_service.js b/x-pack/legacy/plugins/ml/public/services/job_service.js index bea6631a6a2c4..3d5f04fd627a9 100644 --- a/x-pack/legacy/plugins/ml/public/services/job_service.js +++ b/x-pack/legacy/plugins/ml/public/services/job_service.js @@ -404,7 +404,6 @@ class JobService { // return the promise chain return ml.validateJob(obj) .then((messages) => { - console.log('validate job', messages); return { success: true, messages }; }).catch((err) => { msgs.error(i18n.translate('xpack.ml.jobService.jobValidationErrorMessage', { From 7c18a02e6903e0a5fa1d15d774c9e22ae04eba69 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2019 12:07:49 +0200 Subject: [PATCH 03/29] Update dependency @elastic/charts to ^13.5.4 (#47939) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 1a24266ac3684..e61d757195438 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "dependencies": { "@babel/core": "^7.5.5", "@babel/register": "^7.5.5", - "@elastic/charts": "^13.5.1", + "@elastic/charts": "^13.5.4", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", "@elastic/eui": "14.5.0", diff --git a/yarn.lock b/yarn.lock index 35fa03470254a..0b5e829a80ff8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1064,10 +1064,10 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@elastic/charts@^13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-13.5.1.tgz#feba462fa1699430db60b55827fea52444b34df1" - integrity sha512-kIwZ5q+8pBdISJZJYwZWvK5ZGYj7+GHnCWE7YFi68pZ99MTsmE1UEEXbDM9iYa+ru2/ALkcVr2zg72sjEsbeyA== +"@elastic/charts@^13.5.4": + version "13.5.4" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-13.5.4.tgz#b958639d485ed58d116ac66a16e4accef97919e0" + integrity sha512-F+aE4VgJ7xvl9RmWtJiHZwADQT9FwBSWgQS1IR1VQ5wLyOI9LUwrDGZXMtLR56M7wjPWbk0228n5xPgjsuBcdg== dependencies: "@types/d3-shape" "^1.3.1" "@types/luxon" "^1.11.1" From 906c06754aef1466ab5ca93f05b343addfd7e210 Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Fri, 18 Oct 2019 14:22:29 +0300 Subject: [PATCH 04/29] Fix angular stack overflow by changing apply filters popover directive implementation (#48559) --- .../apply_filters/apply_filters_popover.tsx | 5 +- .../public/shim/apply_filter_directive.html | 8 --- .../data/public/shim/legacy_module.ts | 68 ++++++++++++------- .../dashboard/dashboard_app_controller.tsx | 26 +++---- 4 files changed, 60 insertions(+), 47 deletions(-) delete mode 100644 src/legacy/core_plugins/data/public/shim/apply_filter_directive.html diff --git a/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx b/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx index 6270dee72ab05..ab1ed8bfb9841 100644 --- a/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx +++ b/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx @@ -36,6 +36,7 @@ import React, { Component } from 'react'; import { IndexPattern } from '../../index_patterns'; import { getDisplayValueFromFilter } from '../filter_bar/filter_editor/lib/filter_editor_utils'; import { getFilterDisplayText } from '../filter_bar/filter_editor/lib/get_filter_display_text'; +import { mapAndFlattenFilters } from '../filter_manager/lib/map_and_flatten_filters'; interface Props { filters: Filter[]; @@ -70,9 +71,11 @@ export class ApplyFiltersPopover extends Component { return ''; } + const mappedFilters = mapAndFlattenFilters(this.props.filters); + const form = ( - {this.props.filters.map((filter, i) => ( + {mappedFilters.map((filter, i) => ( diff --git a/src/legacy/core_plugins/data/public/shim/legacy_module.ts b/src/legacy/core_plugins/data/public/shim/legacy_module.ts index 9ce35e6d2fa9e..0b5ca72599208 100644 --- a/src/legacy/core_plugins/data/public/shim/legacy_module.ts +++ b/src/legacy/core_plugins/data/public/shim/legacy_module.ts @@ -20,13 +20,11 @@ import { once } from 'lodash'; import { wrapInI18nContext } from 'ui/i18n'; -import { Filter } from '@kbn/es-query'; // @ts-ignore import { uiModules } from 'ui/modules'; import { npStart } from 'ui/new_platform'; import { FilterBar, ApplyFiltersPopover } from '../filter'; -import template from './apply_filter_directive.html'; // @ts-ignore import { mapAndFlattenFilters } from '../filter/filter_manager/lib/map_and_flatten_filters'; @@ -76,35 +74,53 @@ export const initLegacyModule = once((): void => { ['pluginDataStart', { watchDepth: 'reference' }], ]); }) - .directive('applyFiltersPopoverComponent', (reactDirective: any) => - reactDirective(wrapInI18nContext(ApplyFiltersPopover)) - ) .directive('applyFiltersPopover', () => { return { - template, restrict: 'E', - scope: { - filters: '=', - onCancel: '=', - onSubmit: '=', - indexPatterns: '=', - }, - link($scope: any) { - $scope.state = {}; - - // Each time the new filters change we want to rebuild (not just re-render) the "apply filters" - // popover, because it has to reset its state whenever the new filters change. Setting a `key` - // property on the component accomplishes this due to how React handles the `key` property. - $scope.$watch('filters', (filters: any) => { - const mappedFilters: Filter[] = mapAndFlattenFilters(filters); - $scope.state = { - filters: mappedFilters, - key: Date.now(), - }; - }); + template: '', + compile: (elem: any) => { + const child = document.createElement('apply-filters-popover-helper'); + + // Copy attributes to the child directive + for (const attr of elem[0].attributes) { + child.setAttribute(attr.name, attr.value); + } + + // Add a key attribute that will force a full rerender every time that + // a filter changes. + child.setAttribute('key', 'key'); + + // Append helper directive + elem.append(child); + + const linkFn = ($scope: any, _: any, $attr: any) => { + // Watch only for filter changes to update key. + $scope.$watch( + () => { + return $scope.$eval($attr.filters) || []; + }, + (newVal: any) => { + $scope.key = Date.now(); + }, + true + ); + }; + + return linkFn; }, }; - }); + }) + .directive('applyFiltersPopoverHelper', (reactDirective: any) => + reactDirective(wrapInI18nContext(ApplyFiltersPopover), [ + ['filters', { watchDepth: 'collection' }], + ['onCancel', { watchDepth: 'reference' }], + ['onSubmit', { watchDepth: 'reference' }], + ['indexPatterns', { watchDepth: 'collection' }], + + // Key is needed to trigger a full rerender of the component + 'key', + ]) + ); const module = uiModules.get('kibana/index_patterns'); let _service: any; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx index 488736da8456b..abf7b22a6e48c 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx @@ -422,19 +422,21 @@ export class DashboardAppController { }; $scope.onApplyFilters = filters => { - // All filters originated from one visualization. - const indexPatternId = filters[0].meta.index; - const indexPattern = _.find( - $scope.indexPatterns, - (p: IndexPattern) => p.id === indexPatternId - ); - if (indexPattern && indexPattern.timeFieldName) { - const { timeRangeFilter, restOfFilters } = extractTimeFilter( - indexPattern.timeFieldName, - filters + if (filters.length) { + // All filters originated from one visualization. + const indexPatternId = filters[0].meta.index; + const indexPattern = _.find( + $scope.indexPatterns, + (p: IndexPattern) => p.id === indexPatternId ); - queryFilter.addFilters(restOfFilters); - if (timeRangeFilter) changeTimeFilter(timefilter, timeRangeFilter); + if (indexPattern && indexPattern.timeFieldName) { + const { timeRangeFilter, restOfFilters } = extractTimeFilter( + indexPattern.timeFieldName, + filters + ); + queryFilter.addFilters(restOfFilters); + if (timeRangeFilter) changeTimeFilter(timefilter, timeRangeFilter); + } } $scope.appState.$newFilters = []; From 46833056a1fb9aa45b61e3755398f5c5a9e88a7d Mon Sep 17 00:00:00 2001 From: patrykkopycinski Date: Fri, 18 Oct 2019 14:47:20 +0200 Subject: [PATCH 05/29] [SIEM] Refactor IP details page (#47593) --- .../siem/public/components/link_to/index.ts | 4 +- .../public/components/link_to/link_to.tsx | 32 +- .../components/link_to/redirect_to_hosts.tsx | 15 +- .../link_to/redirect_to_network.tsx | 13 +- .../link_to/redirect_to_overview.tsx | 5 +- .../link_to/redirect_to_timelines.tsx | 7 +- .../siem/public/components/links/index.tsx | 5 +- .../ml_host_conditional_container.tsx | 18 +- .../ml_network_conditional_container.tsx | 9 +- .../navigation/breadcrumbs/index.ts | 2 +- .../navigation/tab_navigation/index.test.tsx | 3 +- .../page/overview/overview_host/index.tsx | 3 +- .../page/overview/overview_network/index.tsx | 3 +- .../components/url_state/helpers.test.ts | 3 +- .../public/components/url_state/helpers.ts | 2 +- .../components/url_state/index.test.tsx | 2 +- .../url_state/index_mocked.test.tsx | 2 +- .../components/url_state/test_dependencies.ts | 3 +- .../public/pages/home/home_navigations.tsx | 17 +- .../plugins/siem/public/pages/home/index.tsx | 17 +- .../plugins/siem/public/pages/home/types.ts | 22 + .../public/pages/hosts/details/nav_tabs.tsx | 3 +- .../plugins/siem/public/pages/hosts/index.tsx | 10 +- .../siem/public/pages/hosts/nav_tabs.tsx | 3 +- .../siem/public/pages/network/index.tsx | 7 +- .../siem/public/pages/network/ip_details.tsx | 468 ------------------ .../__snapshots__/index.test.tsx.snap} | 0 .../index.test.tsx} | 20 +- .../public/pages/network/ip_details/index.tsx | 277 +++++++++++ .../network_top_countries_query_table.tsx | 68 +++ .../network_top_n_flow_query_table.tsx | 68 +++ .../network/ip_details/tls_query_table.tsx | 55 ++ .../public/pages/network/ip_details/types.ts | 73 +++ .../network/ip_details/users_query_table.tsx | 56 +++ .../public/pages/network/ip_details/utils.ts | 35 ++ .../siem/public/pages/network/types.ts | 16 - 36 files changed, 780 insertions(+), 566 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/public/pages/home/types.ts delete mode 100644 x-pack/legacy/plugins/siem/public/pages/network/ip_details.tsx rename x-pack/legacy/plugins/siem/public/pages/network/{__snapshots__/ip_details.test.tsx.snap => ip_details/__snapshots__/index.test.tsx.snap} (100%) rename x-pack/legacy/plugins/siem/public/pages/network/{ip_details.test.tsx => ip_details/index.test.tsx} (89%) create mode 100644 x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/network/ip_details/network_top_countries_query_table.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/network/ip_details/network_top_n_flow_query_table.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/network/ip_details/tls_query_table.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts create mode 100644 x-pack/legacy/plugins/siem/public/pages/network/ip_details/users_query_table.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/network/ip_details/utils.ts diff --git a/x-pack/legacy/plugins/siem/public/components/link_to/index.ts b/x-pack/legacy/plugins/siem/public/components/link_to/index.ts index cbd01b720295f..7eb39de3d96b4 100644 --- a/x-pack/legacy/plugins/siem/public/components/link_to/index.ts +++ b/x-pack/legacy/plugins/siem/public/components/link_to/index.ts @@ -6,6 +6,6 @@ export { LinkToPage } from './link_to'; export { getOverviewUrl, RedirectToOverviewPage } from './redirect_to_overview'; -export { getHostsUrl } from './redirect_to_hosts'; -export { getNetworkUrl, RedirectToNetworkPage } from './redirect_to_network'; +export { getHostsUrl, getHostDetailsUrl } from './redirect_to_hosts'; +export { getNetworkUrl, getIPDetailsUrl, RedirectToNetworkPage } from './redirect_to_network'; export { getTimelinesUrl, RedirectToTimelinesPage } from './redirect_to_timelines'; diff --git a/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx b/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx index 1fdae4ba9b301..0360c1004f151 100644 --- a/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx +++ b/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx @@ -13,33 +13,49 @@ import { RedirectToNetworkPage } from './redirect_to_network'; import { RedirectToOverviewPage } from './redirect_to_overview'; import { RedirectToTimelinesPage } from './redirect_to_timelines'; import { HostsTableType } from '../../store/hosts/model'; +import { SiemPageName } from '../../pages/home/types'; + interface LinkToPageProps { match: RouteMatch<{}>; } export const LinkToPage = pure(({ match }) => ( - - + + - - + + )); diff --git a/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_hosts.tsx b/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_hosts.tsx index ee4ff75595c66..05139320b171d 100644 --- a/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_hosts.tsx +++ b/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_hosts.tsx @@ -9,6 +9,7 @@ import { RouteComponentProps } from 'react-router-dom'; import { RedirectWrapper } from './redirect_wrapper'; import { HostsTableType } from '../../store/hosts/model'; +import { SiemPageName } from '../../pages/home/types'; export type HostComponentProps = RouteComponentProps<{ detailName: string; @@ -24,7 +25,7 @@ export const RedirectToHostsPage = ({ }: HostComponentProps) => { const defaultSelectedTab = HostsTableType.hosts; const selectedTab = tabName ? tabName : defaultSelectedTab; - const to = `/hosts/${selectedTab}${search}`; + const to = `/${SiemPageName.hosts}/${selectedTab}${search}`; return ; }; @@ -37,16 +38,18 @@ export const RedirectToHostDetailsPage = ({ }: HostComponentProps) => { const defaultSelectedTab = HostsTableType.authentications; const selectedTab = tabName ? tabName : defaultSelectedTab; - const to = `/hosts/${detailName}/${selectedTab}${search}`; + const to = `/${SiemPageName.hosts}/${detailName}/${selectedTab}${search}`; return ; }; -export const getHostsUrl = () => '#/link-to/hosts'; +const baseHostsUrl = `#/link-to/${SiemPageName.hosts}`; -export const getTabsOnHostsUrl = (tabName: HostsTableType) => `#/link-to/hosts/${tabName}`; +export const getHostsUrl = () => baseHostsUrl; -export const getHostDetailsUrl = (detailName: string) => `#/link-to/hosts/${detailName}`; +export const getTabsOnHostsUrl = (tabName: HostsTableType) => `${baseHostsUrl}/${tabName}`; + +export const getHostDetailsUrl = (detailName: string) => `${baseHostsUrl}/${detailName}`; export const getTabsOnHostDetailsUrl = (detailName: string, tabName: HostsTableType) => { - return `#/link-to/hosts/${detailName}/${tabName}`; + return `${baseHostsUrl}/${detailName}/${tabName}`; }; diff --git a/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_network.tsx b/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_network.tsx index 50b23486d42a2..4a1fa3b6d3b38 100644 --- a/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_network.tsx +++ b/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_network.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { RedirectWrapper } from './redirect_wrapper'; +import { SiemPageName } from '../../pages/home/types'; export type NetworkComponentProps = RouteComponentProps<{ detailName: string; @@ -20,7 +21,15 @@ export const RedirectToNetworkPage = ({ }, location: { search }, }: NetworkComponentProps) => ( - + ); -export const getNetworkUrl = () => '#/link-to/network'; +const baseNetworkUrl = `#/link-to/${SiemPageName.network}`; +export const getNetworkUrl = () => baseNetworkUrl; +export const getIPDetailsUrl = (detailName: string) => `${baseNetworkUrl}/ip/${detailName}`; diff --git a/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_overview.tsx b/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_overview.tsx index 0dd706aafaddc..c1168a44aa6be 100644 --- a/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_overview.tsx +++ b/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_overview.tsx @@ -7,13 +7,14 @@ import React from 'react'; import { RouteComponentProps } from 'react-router'; import { RedirectWrapper } from './redirect_wrapper'; +import { SiemPageName } from '../../pages/home/types'; export type OverviewComponentProps = RouteComponentProps<{ search: string; }>; export const RedirectToOverviewPage = ({ location: { search } }: OverviewComponentProps) => ( - + ); -export const getOverviewUrl = () => '#/link-to/overview'; +export const getOverviewUrl = () => `#/link-to/${SiemPageName.overview}`; diff --git a/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_timelines.tsx b/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_timelines.tsx index fc44b71570476..153166f00a0c0 100644 --- a/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_timelines.tsx +++ b/x-pack/legacy/plugins/siem/public/components/link_to/redirect_to_timelines.tsx @@ -7,15 +7,14 @@ import React from 'react'; import { RouteComponentProps } from 'react-router'; import { RedirectWrapper } from './redirect_wrapper'; +import { SiemPageName } from '../../pages/home/types'; export type TimelineComponentProps = RouteComponentProps<{ search: string; }>; -export const TIMELINES_PAGE_NAME = 'timelines'; - export const RedirectToTimelinesPage = ({ location: { search } }: TimelineComponentProps) => ( - + ); -export const getTimelinesUrl = () => `#/link-to/${TIMELINES_PAGE_NAME}`; +export const getTimelinesUrl = () => `#/link-to/${SiemPageName.timelines}`; diff --git a/x-pack/legacy/plugins/siem/public/components/links/index.tsx b/x-pack/legacy/plugins/siem/public/components/links/index.tsx index d9e98b4f11662..e260e40c41ac5 100644 --- a/x-pack/legacy/plugins/siem/public/components/links/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/links/index.tsx @@ -9,11 +9,12 @@ import * as React from 'react'; import { pure } from 'recompose'; import { encodeIpv6 } from '../../lib/helpers'; +import { getHostDetailsUrl, getIPDetailsUrl } from '../link_to'; // Internal Links export const HostDetailsLink = pure<{ children?: React.ReactNode; hostName: string }>( ({ children, hostName }) => ( - + {children ? children : hostName} ) @@ -23,7 +24,7 @@ HostDetailsLink.displayName = 'HostDetailsLink'; export const IPDetailsLink = pure<{ children?: React.ReactNode; ip: string }>( ({ children, ip }) => ( - + {children ? children : ip} ) diff --git a/x-pack/legacy/plugins/siem/public/components/ml/conditional_links/ml_host_conditional_container.tsx b/x-pack/legacy/plugins/siem/public/components/ml/conditional_links/ml_host_conditional_container.tsx index 1ff89d7ffe625..8bd97304a7e21 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/conditional_links/ml_host_conditional_container.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml/conditional_links/ml_host_conditional_container.tsx @@ -11,6 +11,8 @@ import { QueryString } from 'ui/utils/query_string'; import { addEntitiesToKql } from './add_entities_to_kql'; import { replaceKQLParts } from './replace_kql_parts'; import { emptyEntity, multipleEntities, getMultipleEntities } from './entity_helpers'; +import { SiemPageName } from '../../../pages/home/types'; +import { HostsTableType } from '../../../store/hosts/model'; interface QueryStringType { '?_g': string; @@ -34,7 +36,7 @@ export const MlHostConditionalContainer = React.memo(({ queryStringDecoded.query = replaceKQLParts(queryStringDecoded.query); } const reEncoded = QueryString.encode(queryStringDecoded); - return ; + return ; }} /> (({ } if (emptyEntity(hostName)) { const reEncoded = QueryString.encode(queryStringDecoded); - return ; + return ( + + ); } else if (multipleEntities(hostName)) { const hosts: string[] = getMultipleEntities(hostName); queryStringDecoded.query = addEntitiesToKql( @@ -62,10 +66,16 @@ export const MlHostConditionalContainer = React.memo(({ queryStringDecoded.query || '' ); const reEncoded = QueryString.encode(queryStringDecoded); - return ; + return ( + + ); } else { const reEncoded = QueryString.encode(queryStringDecoded); - return ; + return ( + + ); } }} /> diff --git a/x-pack/legacy/plugins/siem/public/components/ml/conditional_links/ml_network_conditional_container.tsx b/x-pack/legacy/plugins/siem/public/components/ml/conditional_links/ml_network_conditional_container.tsx index cf9abfe5c46b6..8778818829cf7 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/conditional_links/ml_network_conditional_container.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml/conditional_links/ml_network_conditional_container.tsx @@ -11,6 +11,7 @@ import { QueryString } from 'ui/utils/query_string'; import { addEntitiesToKql } from './add_entities_to_kql'; import { replaceKQLParts } from './replace_kql_parts'; import { emptyEntity, getMultipleEntities, multipleEntities } from './entity_helpers'; +import { SiemPageName } from '../../../pages/home/types'; interface QueryStringType { '?_g': string; @@ -34,7 +35,7 @@ export const MlNetworkConditionalContainer = React.memo; + return ; }} /> ; + return ; } else if (multipleEntities(ip)) { const ips: string[] = getMultipleEntities(ip); queryStringDecoded.query = addEntitiesToKql( @@ -62,10 +63,10 @@ export const MlNetworkConditionalContainer = React.memo; + return ; } else { const reEncoded = QueryString.encode(queryStringDecoded); - return ; + return ; } }} /> diff --git a/x-pack/legacy/plugins/siem/public/components/navigation/breadcrumbs/index.ts b/x-pack/legacy/plugins/siem/public/components/navigation/breadcrumbs/index.ts index be185de965f5e..8d9ebb964ce63 100644 --- a/x-pack/legacy/plugins/siem/public/components/navigation/breadcrumbs/index.ts +++ b/x-pack/legacy/plugins/siem/public/components/navigation/breadcrumbs/index.ts @@ -10,7 +10,7 @@ import { getOr } from 'lodash/fp'; import { APP_NAME } from '../../../../common/constants'; import { getBreadcrumbs as getHostDetailsBreadcrumbs } from '../../../pages/hosts/details/utils'; import { getBreadcrumbs as getIPDetailsBreadcrumbs } from '../../../pages/network/ip_details'; -import { SiemPageName } from '../../../pages/home/home_navigations'; +import { SiemPageName } from '../../../pages/home/types'; import { RouteSpyState } from '../../../utils/route/types'; import { getOverviewUrl } from '../../link_to'; diff --git a/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/index.test.tsx index ac4b78c5b61f5..f58519dc0e4c5 100644 --- a/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/index.test.tsx @@ -9,7 +9,8 @@ import * as React from 'react'; import { TabNavigation } from './'; import { TabNavigationProps } from './types'; -import { navTabs, SiemPageName } from '../../../pages/home/home_navigations'; +import { navTabs } from '../../../pages/home/home_navigations'; +import { SiemPageName } from '../../../pages/home/types'; import { HostsTableType } from '../../../store/hosts/model'; import { navTabsHostDetails } from '../../../pages/hosts/details/nav_tabs'; import { CONSTANTS } from '../../url_state/constants'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx index bb96353c862c8..3d4a2bc31f2fc 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx @@ -17,6 +17,7 @@ import { } from '../../../../containers/overview/overview_host'; import { inputsModel } from '../../../../store/inputs'; import { OverviewHostStats } from '../overview_host_stats'; +import { getHostsUrl } from '../../../link_to'; export interface OwnProps { startDate: number; @@ -55,7 +56,7 @@ export const OverviewHost = pure(({ endDate, startDate, setQu } > - + diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.tsx index c27395d157ebf..c1629a50341db 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.tsx @@ -17,6 +17,7 @@ import { } from '../../../../containers/overview/overview_network'; import { inputsModel } from '../../../../store/inputs'; import { OverviewNetworkStats } from '../overview_network_stats'; +import { getNetworkUrl } from '../../../link_to'; export interface OwnProps { startDate: number; @@ -58,7 +59,7 @@ export const OverviewNetwork = pure(({ endDate, startDate, setQuery }) /> } > - + ; export const navTabs: SiemNavTab = { [SiemPageName.overview]: { diff --git a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx index 94a1fcd203bfc..d3d9a1e7f2c7b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx @@ -29,6 +29,7 @@ import { MlPopover } from '../../components/ml_popover/ml_popover'; import { MlHostConditionalContainer } from '../../components/ml/conditional_links/ml_host_conditional_container'; import { MlNetworkConditionalContainer } from '../../components/ml/conditional_links/ml_network_conditional_container'; import { navTabs } from './home_navigations'; +import { SiemPageName } from './types'; import { UseUrlState } from '../../components/url_state'; import { SpyRoute } from '../../utils/route/spy_routes'; @@ -137,21 +138,27 @@ export const HomePage = pure(() => ( - - } /> + } + /> + ( )} /> ( )} /> - } /> + } + /> ; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/nav_tabs.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/nav_tabs.tsx index 6072b51254fb1..9867e745c3190 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/nav_tabs.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/nav_tabs.tsx @@ -8,9 +8,10 @@ import { omit } from 'lodash/fp'; import * as i18n from './../translations'; import { HostDetailsNavTab } from './types'; import { HostsTableType } from '../../../store/hosts/model'; +import { SiemPageName } from '../../home/types'; const getTabsOnHostDetailsUrl = (hostName: string, tabName: HostsTableType) => - `#/hosts/${hostName}/${tabName}`; + `#/${SiemPageName.hosts}/${hostName}/${tabName}`; export const navTabsHostDetails = ( hostName: string, diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx index e578809131405..6596d4c65c00e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx @@ -18,9 +18,10 @@ import { import { HostsBody } from './hosts_body'; import { HostsTableType } from '../../store/hosts/model'; import { GlobalTime } from '../../containers/global_time'; +import { SiemPageName } from '../home/types'; import { Hosts } from './hosts'; -const hostsPagePath = `/:pageName(hosts)`; +const hostsPagePath = `/:pageName(${SiemPageName.hosts})`; const getHostsTabPath = (pagePath: string) => `${pagePath}/:tabName(` + @@ -236,9 +237,12 @@ export const HostsContainer = React.memo(({ url }) => ( )} /> ( - + )} /> diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/nav_tabs.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/nav_tabs.tsx index 8ba33f796a577..0756efe1f9b6e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/nav_tabs.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/nav_tabs.tsx @@ -8,8 +8,9 @@ import { omit } from 'lodash/fp'; import * as i18n from './translations'; import { HostsTableType } from '../../store/hosts/model'; import { HostsNavTab } from './navigation/types'; +import { SiemPageName } from '../home/types'; -const getTabsOnHostsUrl = (tabName: HostsTableType) => `#/hosts/${tabName}`; +const getTabsOnHostsUrl = (tabName: HostsTableType) => `#/${SiemPageName.hosts}/${tabName}`; export const navTabsHosts = (hasMlUserPermissions: boolean): HostsNavTab => { const hostsNavTabs = { diff --git a/x-pack/legacy/plugins/siem/public/pages/network/index.tsx b/x-pack/legacy/plugins/siem/public/pages/network/index.tsx index 2eedd766cc682..009a89bb3889f 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/index.tsx @@ -13,12 +13,13 @@ import { hasMlUserPermissions } from '../../components/ml/permissions/has_ml_use import { IPDetails } from './ip_details'; import { Network } from './network'; import { GlobalTime } from '../../containers/global_time'; +import { SiemPageName } from '../home/types'; import { getNetworkRoutePath } from './navigation'; import { NetworkRouteType } from './navigation/types'; type Props = Partial> & { url: string }; -const networkPagePath = `/:pageName(network)`; +const networkPagePath = `/:pageName(${SiemPageName.network})`; const ipDetailsPagePath = `${networkPagePath}/ip/:detailName`; export const NetworkContainer = React.memo(() => { @@ -66,9 +67,9 @@ export const NetworkContainer = React.memo(() => { )} /> ( - + )} /> diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details.tsx deleted file mode 100644 index ef3af241a2267..0000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details.tsx +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { EuiHorizontalRule, EuiSpacer, EuiFlexItem } from '@elastic/eui'; -import { getOr } from 'lodash/fp'; -import React, { useEffect } from 'react'; -import { connect } from 'react-redux'; -import { StickyContainer } from 'react-sticky'; -import { Breadcrumb } from 'ui/chrome'; - -import { FiltersGlobal } from '../../components/filters_global'; -import { HeaderPage } from '../../components/header_page'; -import { LastEventTime } from '../../components/last_event_time'; -import { getNetworkUrl } from '../../components/link_to/redirect_to_network'; -import { AnomalyTableProvider } from '../../components/ml/anomaly/anomaly_table_provider'; -import { networkToCriteria } from '../../components/ml/criteria/network_to_criteria'; -import { scoreIntervalToDateTime } from '../../components/ml/score/score_interval_to_datetime'; -import { AnomaliesNetworkTable } from '../../components/ml/tables/anomalies_network_table'; -import { manageQuery } from '../../components/page/manage_query'; -import { FlowTargetSelectConnected } from '../../components/page/network/flow_target_select_connected'; -import { IpOverview } from '../../components/page/network/ip_overview'; -import { NetworkTopNFlowTable } from '../../components/page/network/network_top_n_flow_table'; -import { TlsTable } from '../../components/page/network/tls_table'; -import { UsersTable } from '../../components/page/network/users_table'; -import { SiemSearchBar } from '../../components/search_bar'; -import { IpOverviewQuery } from '../../containers/ip_overview'; -import { NetworkTopNFlowQuery } from '../../containers/network_top_n_flow'; -import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; -import { TlsQuery } from '../../containers/tls'; -import { UsersQuery } from '../../containers/users'; -import { FlowTargetSourceDest, LastEventIndexKey } from '../../graphql/types'; -import { decodeIpv6 } from '../../lib/helpers'; -import { convertToBuildEsQuery } from '../../lib/keury'; -import { ConditionalFlexGroup } from '../../pages/network/navigation/conditional_flex_group'; -import { networkModel, networkSelectors, State, inputsSelectors } from '../../store'; -import { setAbsoluteRangeDatePicker as dispatchAbsoluteRangeDatePicker } from '../../store/inputs/actions'; -import { setIpDetailsTablesActivePageToZero as dispatchIpDetailsTablesActivePageToZero } from '../../store/network/actions'; -import { SpyRoute } from '../../utils/route/spy_routes'; -import { NetworkEmptyPage } from './network_empty_page'; -import { NetworkTopCountriesQuery } from '../../containers/network_top_countries'; -import { NetworkTopCountriesTable } from '../../components/page/network/network_top_countries_table'; -import * as i18n from './translations'; -import { IPDetailsComponentProps } from './types'; - -const TlsTableManage = manageQuery(TlsTable); -const UsersTableManage = manageQuery(UsersTable); -const IpOverviewManage = manageQuery(IpOverview); -const NetworkTopNFlowTableManage = manageQuery(NetworkTopNFlowTable); -const NetworkTopCountriesTableManage = manageQuery(NetworkTopCountriesTable); - -export const IPDetailsComponent = React.memo( - ({ - detailName, - filters, - flowTarget, - from, - isInitializing, - query, - setAbsoluteRangeDatePicker, - setIpDetailsTablesActivePageToZero, - setQuery, - to, - }) => { - useEffect(() => { - setIpDetailsTablesActivePageToZero(null); - }, [detailName]); - return ( - <> - - {({ indicesExist, indexPattern }) => { - const ip = decodeIpv6(detailName); - const filterQuery = convertToBuildEsQuery({ - indexPattern, - queries: [query], - filters, - }); - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - - - } - title={ip} - draggableArguments={{ field: `${flowTarget}.ip`, value: ip }} - > - - - - - {({ id, inspect, ipOverviewData, loading, refetch }) => ( - - {({ isLoadingAnomaliesData, anomaliesData }) => ( - { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }} - /> - )} - - )} - - - - - - - - {({ - id, - inspect, - isInspected, - loading, - loadPage, - networkTopNFlow, - pageInfo, - refetch, - totalCount, - }) => ( - - )} - - - - - - {({ - id, - inspect, - isInspected, - loading, - loadPage, - networkTopNFlow, - pageInfo, - refetch, - totalCount, - }) => ( - - )} - - - - - - - - - - {({ - id, - inspect, - isInspected, - loading, - loadPage, - networkTopCountries, - pageInfo, - refetch, - totalCount, - }) => ( - - )} - - - - - - {({ - id, - inspect, - isInspected, - loading, - loadPage, - networkTopCountries, - pageInfo, - refetch, - totalCount, - }) => ( - - )} - - - - - - - - {({ - id, - inspect, - isInspected, - users, - totalCount, - pageInfo, - loading, - loadPage, - refetch, - }) => ( - - )} - - - - - - {({ - id, - inspect, - isInspected, - tls, - totalCount, - pageInfo, - loading, - loadPage, - refetch, - }) => ( - - )} - - - - - { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }} - /> - - ) : ( - <> - - - - - ); - }} - - - - ); - } -); - -IPDetailsComponent.displayName = 'IPDetailsComponent'; - -const makeMapStateToProps = () => { - const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); - const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); - const getIpDetailsFlowTargetSelector = networkSelectors.ipDetailsFlowTargetSelector(); - return (state: State) => ({ - query: getGlobalQuerySelector(state), - filters: getGlobalFiltersQuerySelector(state), - flowTarget: getIpDetailsFlowTargetSelector(state), - }); -}; - -export const IPDetails = connect( - makeMapStateToProps, - { - setAbsoluteRangeDatePicker: dispatchAbsoluteRangeDatePicker, - setIpDetailsTablesActivePageToZero: dispatchIpDetailsTablesActivePageToZero, - } -)(IPDetailsComponent); - -export const getBreadcrumbs = (ip: string | undefined, search: string[]): Breadcrumb[] => { - const breadcrumbs = [ - { - text: i18n.PAGE_TITLE, - href: `${getNetworkUrl()}${search && search[0] ? search[0] : ''}`, - }, - ]; - if (ip) { - return [ - ...breadcrumbs, - { - text: decodeIpv6(ip), - href: '', - }, - ]; - } else { - return breadcrumbs; - } -}; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/__snapshots__/ip_details.test.tsx.snap b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/__snapshots__/index.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/siem/public/pages/network/__snapshots__/ip_details.test.tsx.snap rename to x-pack/legacy/plugins/siem/public/pages/network/ip_details/__snapshots__/index.test.tsx.snap diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details.test.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx similarity index 89% rename from x-pack/legacy/plugins/siem/public/pages/network/ip_details.test.tsx rename to x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx index e903a0b4b2761..a438fcbaa5c46 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx @@ -13,18 +13,18 @@ import { MockedProvider } from 'react-apollo/test-utils'; import { ActionCreator } from 'typescript-fsa'; import { npSetup } from 'ui/new_platform'; -import '../../mock/match_media'; +import '../../../mock/match_media'; -import { mocksSource } from '../../containers/source/mock'; -import { FlowTarget } from '../../graphql/types'; -import { apolloClientObservable, mockGlobalState, TestProviders } from '../../mock'; -import { MockNpSetUp, mockUiSettings } from '../../mock/ui_settings'; -import { createStore, State } from '../../store'; -import { InputsModelId } from '../../store/inputs/constants'; +import { mocksSource } from '../../../containers/source/mock'; +import { FlowTarget } from '../../../graphql/types'; +import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../mock'; +import { MockNpSetUp, mockUiSettings } from '../../../mock/ui_settings'; +import { createStore, State } from '../../../store'; +import { InputsModelId } from '../../../store/inputs/constants'; -import { IPDetailsComponent, IPDetails } from './ip_details'; +import { IPDetailsComponent, IPDetails } from './index'; -jest.mock('../../lib/settings/use_kibana_ui_setting'); +jest.mock('../../../lib/settings/use_kibana_ui_setting'); type Action = 'PUSH' | 'POP' | 'REPLACE'; const pop: Action = 'POP'; @@ -37,7 +37,7 @@ mockNpSetup.core.uiSettings = mockUiSettings; // Test will fail because we will to need to mock some core services to make the test work // For now let's forget about SiemSearchBar -jest.mock('../../components/search_bar', () => ({ +jest.mock('../../../components/search_bar', () => ({ SiemSearchBar: () => null, })); diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx new file mode 100644 index 0000000000000..9e7ef2975e2b5 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx @@ -0,0 +1,277 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiHorizontalRule, EuiSpacer, EuiFlexItem } from '@elastic/eui'; +import React, { useCallback, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { StickyContainer } from 'react-sticky'; + +import { FiltersGlobal } from '../../../components/filters_global'; +import { HeaderPage } from '../../../components/header_page'; +import { LastEventTime } from '../../../components/last_event_time'; +import { AnomalyTableProvider } from '../../../components/ml/anomaly/anomaly_table_provider'; +import { networkToCriteria } from '../../../components/ml/criteria/network_to_criteria'; +import { scoreIntervalToDateTime } from '../../../components/ml/score/score_interval_to_datetime'; +import { AnomaliesNetworkTable } from '../../../components/ml/tables/anomalies_network_table'; +import { manageQuery } from '../../../components/page/manage_query'; +import { FlowTargetSelectConnected } from '../../../components/page/network/flow_target_select_connected'; +import { IpOverview } from '../../../components/page/network/ip_overview'; +import { SiemSearchBar } from '../../../components/search_bar'; +import { IpOverviewQuery } from '../../../containers/ip_overview'; +import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../../containers/source'; +import { FlowTargetSourceDest, LastEventIndexKey } from '../../../graphql/types'; +import { decodeIpv6 } from '../../../lib/helpers'; +import { convertToBuildEsQuery } from '../../../lib/keury'; +import { ConditionalFlexGroup } from '../../../pages/network/navigation/conditional_flex_group'; +import { networkModel, networkSelectors, State, inputsSelectors } from '../../../store'; +import { setAbsoluteRangeDatePicker as dispatchAbsoluteRangeDatePicker } from '../../../store/inputs/actions'; +import { setIpDetailsTablesActivePageToZero as dispatchIpDetailsTablesActivePageToZero } from '../../../store/network/actions'; +import { SpyRoute } from '../../../utils/route/spy_routes'; +import { NetworkEmptyPage } from '../network_empty_page'; + +import { IPDetailsComponentProps } from './types'; +export { getBreadcrumbs } from './utils'; +import { TlsQueryTable } from './tls_query_table'; +import { UsersQueryTable } from './users_query_table'; +import { NetworkTopNFlowQueryTable } from './network_top_n_flow_query_table'; +import { NetworkTopCountriesQueryTable } from './network_top_countries_query_table'; + +const IpOverviewManage = manageQuery(IpOverview); + +export const IPDetailsComponent = React.memo( + ({ + detailName, + filters, + flowTarget, + from, + isInitializing, + query, + setAbsoluteRangeDatePicker, + setIpDetailsTablesActivePageToZero, + setQuery, + to, + }) => { + const narrowDateRange = useCallback( + (score, interval) => { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }, + [scoreIntervalToDateTime, setAbsoluteRangeDatePicker] + ); + + useEffect(() => { + setIpDetailsTablesActivePageToZero(null); + }, [detailName]); + + return ( + <> + + {({ indicesExist, indexPattern }) => { + const ip = decodeIpv6(detailName); + const filterQuery = convertToBuildEsQuery({ + indexPattern, + queries: [query], + filters, + }); + return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( + + + + + + } + title={ip} + draggableArguments={{ field: `${flowTarget}.ip`, value: ip }} + > + + + + + {({ id, inspect, ipOverviewData, loading, refetch }) => ( + + {({ isLoadingAnomaliesData, anomaliesData }) => ( + { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }} + /> + )} + + )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) : ( + <> + + + + + ); + }} + + + + ); + } +); + +IPDetailsComponent.displayName = 'IPDetailsComponent'; + +const makeMapStateToProps = () => { + const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); + const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); + const getIpDetailsFlowTargetSelector = networkSelectors.ipDetailsFlowTargetSelector(); + return (state: State) => ({ + query: getGlobalQuerySelector(state), + filters: getGlobalFiltersQuerySelector(state), + flowTarget: getIpDetailsFlowTargetSelector(state), + }); +}; + +export const IPDetails = connect( + makeMapStateToProps, + { + setAbsoluteRangeDatePicker: dispatchAbsoluteRangeDatePicker, + setIpDetailsTablesActivePageToZero: dispatchIpDetailsTablesActivePageToZero, + } +)(IPDetailsComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/network_top_countries_query_table.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/network_top_countries_query_table.tsx new file mode 100644 index 0000000000000..8f3505009b9a5 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/network_top_countries_query_table.tsx @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { getOr } from 'lodash/fp'; +import { manageQuery } from '../../../components/page/manage_query'; +import { NetworkWithIndexComponentsQueryTableProps } from './types'; +import { NetworkTopCountriesQuery } from '../../../containers/network_top_countries'; +import { NetworkTopCountriesTable } from '../../../components/page/network/network_top_countries_table'; + +const NetworkTopCountriesTableManage = manageQuery(NetworkTopCountriesTable); + +export const NetworkTopCountriesQueryTable = ({ + endDate, + filterQuery, + flowTarget, + ip, + setQuery, + skip, + startDate, + type, + indexPattern, +}: NetworkWithIndexComponentsQueryTableProps) => ( + + {({ + id, + inspect, + isInspected, + loading, + loadPage, + networkTopCountries, + pageInfo, + refetch, + totalCount, + }) => ( + + )} + +); + +NetworkTopCountriesQueryTable.displayName = 'NetworkTopCountriesQueryTable'; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/network_top_n_flow_query_table.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/network_top_n_flow_query_table.tsx new file mode 100644 index 0000000000000..47d68471fb69b --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/network_top_n_flow_query_table.tsx @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getOr } from 'lodash/fp'; +import React from 'react'; +import { manageQuery } from '../../../components/page/manage_query'; +import { NetworkTopNFlowTable } from '../../../components/page/network/network_top_n_flow_table'; +import { NetworkTopNFlowQuery } from '../../../containers/network_top_n_flow'; +import { NetworkWithIndexComponentsQueryTableProps } from './types'; + +const NetworkTopNFlowTableManage = manageQuery(NetworkTopNFlowTable); + +export const NetworkTopNFlowQueryTable = ({ + endDate, + filterQuery, + flowTarget, + ip, + setQuery, + skip, + startDate, + type, + indexPattern, +}: NetworkWithIndexComponentsQueryTableProps) => ( + + {({ + id, + inspect, + isInspected, + loading, + loadPage, + networkTopNFlow, + pageInfo, + refetch, + totalCount, + }) => ( + + )} + +); + +NetworkTopNFlowQueryTable.displayName = 'NetworkTopNFlowQueryTable'; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/tls_query_table.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/tls_query_table.tsx new file mode 100644 index 0000000000000..ad3ffb8cb0a57 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/tls_query_table.tsx @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getOr } from 'lodash/fp'; +import React from 'react'; +import { manageQuery } from '../../../components/page/manage_query'; +import { TlsTable } from '../../../components/page/network/tls_table'; +import { TlsQuery } from '../../../containers/tls'; +import { TlsQueryTableComponentProps } from './types'; + +const TlsTableManage = manageQuery(TlsTable); + +export const TlsQueryTable = ({ + endDate, + filterQuery, + flowTarget, + ip, + setQuery, + skip, + startDate, + type, +}: TlsQueryTableComponentProps) => ( + + {({ id, inspect, isInspected, tls, totalCount, pageInfo, loading, loadPage, refetch }) => ( + + )} + +); + +TlsQueryTable.displayName = 'TlsQueryTable'; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts new file mode 100644 index 0000000000000..008409197f77d --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Filter } from '@kbn/es-query'; +import { StaticIndexPattern } from 'ui/index_patterns'; +import { ActionCreator } from 'typescript-fsa'; +import { Query } from 'src/plugins/data/common'; + +import { NetworkType } from '../../../store/network/model'; +import { ESTermQuery } from '../../../../common/typed_json'; +import { InspectQuery, Refetch } from '../../../store/inputs/model'; +import { FlowTarget, FlowTargetSourceDest } from '../../../graphql/types'; +import { InputsModelId } from '../../../store/inputs/constants'; +import { GlobalTimeArgs } from '../../../containers/global_time'; + +export const type = NetworkType.details; + +type SetAbsoluteRangeDatePicker = ActionCreator<{ + id: InputsModelId; + from: number; + to: number; +}>; + +interface IPDetailsComponentReduxProps { + filters: Filter[]; + flowTarget: FlowTarget; + query: Query; +} + +interface IPDetailsComponentDispatchProps { + setAbsoluteRangeDatePicker: SetAbsoluteRangeDatePicker; + setIpDetailsTablesActivePageToZero: ActionCreator; +} + +export type IPDetailsComponentProps = IPDetailsComponentReduxProps & + IPDetailsComponentDispatchProps & + GlobalTimeArgs & { detailName: string }; + +interface OwnProps { + type: NetworkType; + startDate: number; + endDate: number; + filterQuery: string | ESTermQuery; + ip: string; + skip: boolean; + setQuery: ({ + id, + inspect, + loading, + refetch, + }: { + id: string; + inspect: InspectQuery | null; + loading: boolean; + refetch: Refetch; + }) => void; +} + +export type NetworkComponentsQueryProps = OwnProps & { + flowTarget: FlowTarget; +}; + +export type TlsQueryTableComponentProps = OwnProps & { + flowTarget: FlowTargetSourceDest; +}; + +export type NetworkWithIndexComponentsQueryTableProps = OwnProps & { + flowTarget: FlowTargetSourceDest; + indexPattern: StaticIndexPattern; +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/users_query_table.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/users_query_table.tsx new file mode 100644 index 0000000000000..d2f6102e86595 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/users_query_table.tsx @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { getOr } from 'lodash/fp'; +import { manageQuery } from '../../../components/page/manage_query'; +import { UsersQuery } from '../../../containers/users'; +import { NetworkComponentsQueryProps } from './types'; +import { UsersTable } from '../../../components/page/network/users_table'; + +const UsersTableManage = manageQuery(UsersTable); + +export const UsersQueryTable = ({ + endDate, + filterQuery, + flowTarget, + ip, + setQuery, + skip, + startDate, + type, +}: NetworkComponentsQueryProps) => ( + + {({ id, inspect, isInspected, users, totalCount, pageInfo, loading, loadPage, refetch }) => ( + + )} + +); + +UsersQueryTable.displayName = 'UsersQueryTable'; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/utils.ts b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/utils.ts new file mode 100644 index 0000000000000..222bf108b4fad --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/utils.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Breadcrumb } from 'ui/chrome'; + +import { decodeIpv6 } from '../../../lib/helpers'; +import { getNetworkUrl } from '../../../components/link_to/redirect_to_network'; +import { networkModel } from '../../../store/network'; +import * as i18n from '../translations'; + +export const type = networkModel.NetworkType.details; + +export const getBreadcrumbs = (ip: string | undefined, search: string[]): Breadcrumb[] => { + const breadcrumbs = [ + { + text: i18n.PAGE_TITLE, + href: `${getNetworkUrl()}${search && search[0] ? search[0] : ''}`, + }, + ]; + + if (ip) { + return [ + ...breadcrumbs, + { + text: decodeIpv6(ip), + href: '', + }, + ]; + } else { + return breadcrumbs; + } +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/types.ts b/x-pack/legacy/plugins/siem/public/pages/network/types.ts index be58572cb6621..46c868729b832 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/network/types.ts @@ -9,7 +9,6 @@ import { RouteComponentProps } from 'react-router-dom'; import { ActionCreator } from 'typescript-fsa'; import { Query } from 'src/plugins/data/common'; -import { FlowTarget } from '../../graphql/types'; import { GlobalTimeArgs } from '../../containers/global_time'; import { InputsModelId } from '../../store/inputs/constants'; @@ -32,18 +31,3 @@ export type NetworkComponentProps = NetworkComponentReduxProps & hasMlUserPermissions: boolean; capabilitiesFetched: boolean; }; - -interface IPDetailsComponentReduxProps { - filters: Filter[]; - flowTarget: FlowTarget; - query: Query; -} - -interface IPDetailsComponentDispatchProps { - setAbsoluteRangeDatePicker: SetAbsoluteRangeDatePicker; - setIpDetailsTablesActivePageToZero: ActionCreator; -} - -export type IPDetailsComponentProps = IPDetailsComponentReduxProps & - IPDetailsComponentDispatchProps & - GlobalTimeArgs & { detailName: string }; From a46e788354a0a244ee4aa9ffb5774e8500d32893 Mon Sep 17 00:00:00 2001 From: Corey Robertson Date: Fri, 18 Oct 2019 09:03:36 -0400 Subject: [PATCH 06/29] Re-enable embeddables in canvas (#48563) --- .../canvas_plugin_src/functions/common/index.ts | 14 ++++++-------- .../functions/common/saved_map.ts | 1 - .../functions/common/saved_search.ts | 1 - .../functions/common/saved_visualization.ts | 1 - .../plugins/canvas/i18n/functions/function_help.ts | 4 ---- .../components/workpad_header/workpad_header.tsx | 4 +--- 6 files changed, 7 insertions(+), 18 deletions(-) diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/index.ts index 894df9dc1c6b9..097aef69d4b4c 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/index.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/index.ts @@ -47,10 +47,9 @@ import { rounddate } from './rounddate'; import { rowCount } from './rowCount'; import { repeatImage } from './repeatImage'; import { revealImage } from './revealImage'; -// TODO: elastic/kibana#44822 Disabling pending filters work -// import { savedMap } from './saved_map'; -// import { savedSearch } from './saved_search'; -// import { savedVisualization } from './saved_visualization'; +import { savedMap } from './saved_map'; +import { savedSearch } from './saved_search'; +import { savedVisualization } from './saved_visualization'; import { seriesStyle } from './seriesStyle'; import { shape } from './shape'; import { sort } from './sort'; @@ -107,10 +106,9 @@ export const functions = [ revealImage, rounddate, rowCount, - // TODO: elastic/kibana#44822 Disabling pending filters work - // savedMap, - // savedSearch, - // savedVisualization, + savedMap, + savedSearch, + savedVisualization, seriesStyle, shape, sort, diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts index 7541924008845..958d9c6a3a6f0 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts @@ -35,7 +35,6 @@ interface SavedMapInput extends EmbeddableInput { type Return = EmbeddableExpression; export function savedMap(): ExpressionFunction<'savedMap', Filter | null, Arguments, Return> { - // @ts-ignore elastic/kibana#44822 Disabling pending filters work const { help, args: argHelp } = getFunctionHelp().savedMap; return { name: 'savedMap', diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_search.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_search.ts index 3159daee75bc6..4c8170bcb08bd 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_search.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_search.ts @@ -23,7 +23,6 @@ interface Arguments { type Return = EmbeddableExpression & { id: SearchInput['id'] }>; export function savedSearch(): ExpressionFunction<'savedSearch', Filter | null, Arguments, Return> { - // @ts-ignore elastic/kibana#44822 Disabling pending filters work const { help, args: argHelp } = getFunctionHelp().savedSearch; return { name: 'savedSearch', diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts index cd01acd4387be..6b7d06454f44c 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts @@ -26,7 +26,6 @@ export function savedVisualization(): ExpressionFunction< Arguments, Return > { - // @ts-ignore elastic/kibana#44822 Disabling pending filters work const { help, args: argHelp } = getFunctionHelp().savedVisualization; return { name: 'savedVisualization', diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/function_help.ts b/x-pack/legacy/plugins/canvas/i18n/functions/function_help.ts index de0d62b3d4453..495415851e118 100644 --- a/x-pack/legacy/plugins/canvas/i18n/functions/function_help.ts +++ b/x-pack/legacy/plugins/canvas/i18n/functions/function_help.ts @@ -213,12 +213,8 @@ export const getFunctionHelp = (): FunctionHelpDict => ({ revealImage, rounddate, rowCount, - // TODO: elastic/kibana#44822 Disabling pending filters work - // @ts-ignore savedMap, - // @ts-ignore savedSearch, - // @ts-ignore savedVisualization, seriesStyle, shape, diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_header.tsx b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_header.tsx index b05e1f5b757c2..31ad0593f58bb 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_header.tsx +++ b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_header.tsx @@ -13,6 +13,7 @@ import { EuiFlexGroup, EuiButtonIcon, EuiButton, + EuiButtonEmpty, EuiOverlayMask, EuiModal, EuiModalFooter, @@ -193,14 +194,11 @@ export class WorkpadHeader extends React.PureComponent { - {/* - TODO: elastic/kibana#44822 Disabling pending filters work {strings.getEmbedObjectButtonLabel()} - */} Date: Fri, 18 Oct 2019 16:26:26 +0300 Subject: [PATCH 07/29] [Vis: Default editor] EUIficate Vega options tab (#47473) * EUIficate Vega options tab * Update list of dependencies * Fix comments * Adjust styles --- .../vis_type_vega/public/_vega_editor.scss | 33 +---- .../vis_type_vega/public/components/index.ts | 20 +++ .../public/components/vega_actions_menu.tsx | 85 ++++++++++++ .../public/components/vega_help_menu.tsx | 91 +++++++++++++ .../public/components/vega_vis_editor.tsx | 101 ++++++++++++++ .../public/help_menus/vega_action_menu.js | 114 ---------------- .../public/help_menus/vega_help_menu.js | 126 ------------------ .../public/shim/legacy_dependencies_plugin.ts | 5 +- .../public/shim/vega_legacy_module.ts | 49 ------- .../public/vega_editor_controller.js | 86 ------------ .../public/vega_editor_template.html | 30 ----- .../vis_type_vega/public/vega_type.ts | 4 +- .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - 14 files changed, 307 insertions(+), 443 deletions(-) create mode 100644 src/legacy/core_plugins/vis_type_vega/public/components/index.ts create mode 100644 src/legacy/core_plugins/vis_type_vega/public/components/vega_actions_menu.tsx create mode 100644 src/legacy/core_plugins/vis_type_vega/public/components/vega_help_menu.tsx create mode 100644 src/legacy/core_plugins/vis_type_vega/public/components/vega_vis_editor.tsx delete mode 100644 src/legacy/core_plugins/vis_type_vega/public/help_menus/vega_action_menu.js delete mode 100644 src/legacy/core_plugins/vis_type_vega/public/help_menus/vega_help_menu.js delete mode 100644 src/legacy/core_plugins/vis_type_vega/public/shim/vega_legacy_module.ts delete mode 100644 src/legacy/core_plugins/vis_type_vega/public/vega_editor_controller.js delete mode 100644 src/legacy/core_plugins/vis_type_vega/public/vega_editor_template.html diff --git a/src/legacy/core_plugins/vis_type_vega/public/_vega_editor.scss b/src/legacy/core_plugins/vis_type_vega/public/_vega_editor.scss index 94ba9a9c6bc43..f4276541d5d9e 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/_vega_editor.scss +++ b/src/legacy/core_plugins/vis_type_vega/public/_vega_editor.scss @@ -1,41 +1,22 @@ .visEditor--vega { .visEditorSidebar__config { padding: 0; - // Makes sure the vega options dropdown menu is visible - overflow: inherit; + position: relative; } - // The following is necessary for the Vega editor to expand to full height of the editor panel - .visEditorSidebar__config, .visEditorSidebar__options { - @include flex-parent(1, 1, auto); - - > * { - @include flex-parent(1, 1, auto); - } - } - - @include euiBreakpoint('xs', 's', 'm') { - .visEditor__collapsibleSidebar { - flex-grow: 1; - } + @include euiScrollBar; + flex-shrink: 1; + overflow-y: auto; } } - .vgaEditor { - @include flex-parent(1, 1, auto); - position: relative; - @include euiBreakpoint('xs', 's', 'm') { - min-height: $euiSize * 15; + @include euiScrollBar; + max-height: $euiSize * 15; + overflow-y: auto; } - - position: relative; -} - -.vgaEditor__aceEditor { - flex: 1 1 auto; } .vgaEditor__aceEditorActions { diff --git a/src/legacy/core_plugins/vis_type_vega/public/components/index.ts b/src/legacy/core_plugins/vis_type_vega/public/components/index.ts new file mode 100644 index 0000000000000..90f067c778fd2 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vega/public/components/index.ts @@ -0,0 +1,20 @@ +/* + * 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 { VegaVisEditor } from './vega_vis_editor'; diff --git a/src/legacy/core_plugins/vis_type_vega/public/components/vega_actions_menu.tsx b/src/legacy/core_plugins/vis_type_vega/public/components/vega_actions_menu.tsx new file mode 100644 index 0000000000000..71a88b47a8be3 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vega/public/components/vega_actions_menu.tsx @@ -0,0 +1,85 @@ +/* + * 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 React, { useState, useCallback } from 'react'; +import { EuiButtonIcon, EuiContextMenuPanel, EuiContextMenuItem, EuiPopover } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; + +interface VegaActionsMenuProps { + formatHJson(): void; + formatJson(): void; +} + +function VegaActionsMenu({ formatHJson, formatJson }: VegaActionsMenuProps) { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const onButtonClick = useCallback(() => setIsPopoverOpen(isOpen => !isOpen), []); + const onHJsonCLick = useCallback(() => { + formatHJson(); + setIsPopoverOpen(false); + }, [isPopoverOpen, formatHJson]); + + const onJsonCLick = useCallback(() => { + formatJson(); + setIsPopoverOpen(false); + }, [isPopoverOpen, formatJson]); + + const closePopover = useCallback(() => setIsPopoverOpen(false), []); + + const button = ( + + ); + + const items = [ + + + , + + + , + ]; + + return ( + + + + ); +} + +export { VegaActionsMenu }; diff --git a/src/legacy/core_plugins/vis_type_vega/public/components/vega_help_menu.tsx b/src/legacy/core_plugins/vis_type_vega/public/components/vega_help_menu.tsx new file mode 100644 index 0000000000000..e4443c0058e9b --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vega/public/components/vega_help_menu.tsx @@ -0,0 +1,91 @@ +/* + * 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 React, { useCallback, useState } from 'react'; +import { EuiButtonIcon, EuiContextMenuPanel, EuiContextMenuItem, EuiPopover } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; + +function VegaHelpMenu() { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const onButtonClick = useCallback(() => setIsPopoverOpen(!isPopoverOpen), [isPopoverOpen]); + + const closePopover = useCallback(() => setIsPopoverOpen(false), []); + + const button = ( + + ); + + const items = [ + + + , + + + , + + + , + ]; + + return ( + + + + ); +} + +export { VegaHelpMenu }; diff --git a/src/legacy/core_plugins/vis_type_vega/public/components/vega_vis_editor.tsx b/src/legacy/core_plugins/vis_type_vega/public/components/vega_vis_editor.tsx new file mode 100644 index 0000000000000..6d14acf6ec7aa --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vega/public/components/vega_vis_editor.tsx @@ -0,0 +1,101 @@ +/* + * 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 React, { useCallback } from 'react'; +import { EuiCodeEditor } from '@elastic/eui'; +import compactStringify from 'json-stringify-pretty-compact'; +// @ts-ignore +import hjson from 'hjson'; +import { i18n } from '@kbn/i18n'; + +import { toastNotifications } from 'ui/notify'; +import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisParams } from '../vega_fn'; +import { VegaHelpMenu } from './vega_help_menu'; +import { VegaActionsMenu } from './vega_actions_menu'; + +const aceOptions = { + maxLines: Infinity, + highlightActiveLine: false, + showPrintMargin: false, + tabSize: 2, + useSoftTabs: true, + wrap: true, +}; + +const hjsonStringifyOptions = { + bracesSameLine: true, + keepWsc: true, +}; + +function format(value: string, stringify: typeof compactStringify, options?: any) { + try { + const spec = hjson.parse(value, { legacyRoot: false, keepWsc: true }); + return stringify(spec, options); + } catch (err) { + // This is a common case - user tries to format an invalid HJSON text + toastNotifications.addError(err, { + title: i18n.translate('visTypeVega.editor.formatError', { + defaultMessage: 'Error formatting spec', + }), + }); + + return value; + } +} + +function VegaVisEditor({ stateParams, setValue }: VisOptionsProps) { + const onChange = useCallback( + (value: string) => { + setValue('spec', value); + }, + [setValue] + ); + + const formatJson = useCallback( + () => setValue('spec', format(stateParams.spec, compactStringify)), + [setValue, stateParams.spec] + ); + + const formatHJson = useCallback( + () => setValue('spec', format(stateParams.spec, hjson.stringify, hjsonStringifyOptions)), + [setValue, stateParams.spec] + ); + + return ( +
+ +
+ + +
+
+ ); +} + +export { VegaVisEditor }; diff --git a/src/legacy/core_plugins/vis_type_vega/public/help_menus/vega_action_menu.js b/src/legacy/core_plugins/vis_type_vega/public/help_menus/vega_action_menu.js deleted file mode 100644 index 6f136e3679f30..0000000000000 --- a/src/legacy/core_plugins/vis_type_vega/public/help_menus/vega_action_menu.js +++ /dev/null @@ -1,114 +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 PropTypes from 'prop-types'; - -import React, { - Component, -} from 'react'; - -import { - EuiButtonIcon, - EuiContextMenuPanel, - EuiContextMenuItem, - EuiPopover, -} from '@elastic/eui'; - -import { FormattedMessage } from '@kbn/i18n/react'; - -export class VegaActionsMenu extends Component { - constructor(props) { - super(props); - - this.state = { - isPopoverOpen: false, - }; - } - - onButtonClick = () => { - this.setState(prevState => ({ - isPopoverOpen: !prevState.isPopoverOpen, - })); - }; - - closePopover = () => { - this.setState({ - isPopoverOpen: false, - }); - }; - - render() { - const button = ( - - } - /> - ); - - const items = [ - ( - { this.closePopover(); this.props.formatHJson(event); }} - > - - - ), ( - { this.closePopover(); this.props.formatJson(event); }} - > - - - ) - ]; - - return ( - - - - ); - } -} - -VegaActionsMenu.propTypes = { - formatHJson: PropTypes.func.isRequired, - formatJson: PropTypes.func.isRequired, -}; diff --git a/src/legacy/core_plugins/vis_type_vega/public/help_menus/vega_help_menu.js b/src/legacy/core_plugins/vis_type_vega/public/help_menus/vega_help_menu.js deleted file mode 100644 index fe0819a729490..0000000000000 --- a/src/legacy/core_plugins/vis_type_vega/public/help_menus/vega_help_menu.js +++ /dev/null @@ -1,126 +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 React, { - Component, -} from 'react'; - -import { - EuiButtonIcon, - EuiContextMenuPanel, - EuiContextMenuItem, - EuiPopover, -} from '@elastic/eui'; - -import { FormattedMessage } from '@kbn/i18n/react'; - -export class VegaHelpMenu extends Component { - constructor(props) { - super(props); - - this.state = { - isPopoverOpen: false, - }; - } - - onButtonClick = () => { - this.setState(prevState => ({ - isPopoverOpen: !prevState.isPopoverOpen, - })); - }; - - closePopover = () => { - this.setState({ - isPopoverOpen: false, - }); - }; - - render() { - const button = ( - - } - /> - ); - - const items = [ - ( - { this.closePopover(); }} - > - - - ), ( - { this.closePopover(); }} - > - - - ), ( - { this.closePopover(); }} - > - - - ) - ]; - - return ( - - - - ); - } -} diff --git a/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts index 2c4c2d2491fc4..af4425e3d5548 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts @@ -18,9 +18,9 @@ */ import chrome from 'ui/chrome'; +import 'ui/vis/map/service_settings'; import 'ui/es'; // required for $injector.get('es') below import { CoreStart, Plugin } from 'kibana/public'; -import { initVegaLegacyModule } from './vega_legacy_module'; /** @internal */ export interface LegacyDependenciesPluginSetup { @@ -31,9 +31,6 @@ export interface LegacyDependenciesPluginSetup { export class LegacyDependenciesPlugin implements Plugin, void> { public async setup() { - // Init kibana/vega AngularJS module. - initVegaLegacyModule(); - const $injector = await chrome.dangerouslyGetActiveInjector(); return { diff --git a/src/legacy/core_plugins/vis_type_vega/public/shim/vega_legacy_module.ts b/src/legacy/core_plugins/vis_type_vega/public/shim/vega_legacy_module.ts deleted file mode 100644 index 4dc6f03821649..0000000000000 --- a/src/legacy/core_plugins/vis_type_vega/public/shim/vega_legacy_module.ts +++ /dev/null @@ -1,49 +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 'ngreact'; -import 'brace/mode/hjson'; -import 'brace/ext/searchbox'; -import 'ui/accessibility/kbn_ui_ace_keyboard_mode'; -import 'ui/vis/map/service_settings'; - -import { once } from 'lodash'; -// @ts-ignore -import { uiModules } from 'ui/modules'; -import { wrapInI18nContext } from 'ui/i18n'; - -// @ts-ignore -import { VegaEditorController } from '../vega_editor_controller'; -// @ts-ignore -import { VegaHelpMenu } from '../help_menus/vega_help_menu'; -// @ts-ignore -import { VegaActionsMenu } from '../help_menus/vega_action_menu'; - -/** @internal */ -export const initVegaLegacyModule = once((): void => { - uiModules - .get('kibana/vega', ['react']) - .controller('VegaEditorController', VegaEditorController) - .directive('vegaActionsMenu', (reactDirective: any) => - reactDirective(wrapInI18nContext(VegaActionsMenu)) - ) - .directive('vegaHelpMenu', (reactDirective: any) => - reactDirective(wrapInI18nContext(VegaHelpMenu)) - ); -}); diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_editor_controller.js b/src/legacy/core_plugins/vis_type_vega/public/vega_editor_controller.js deleted file mode 100644 index f91beff59a34f..0000000000000 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_editor_controller.js +++ /dev/null @@ -1,86 +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 compactStringify from 'json-stringify-pretty-compact'; -import hjson from 'hjson'; -import { toastNotifications } from 'ui/notify'; -import { i18n } from '@kbn/i18n'; - -export class VegaEditorController { - constructor($scope) { - this.$scope = $scope; - $scope.aceLoaded = (editor) => { - editor.$blockScrolling = Infinity; - - const session = editor.getSession(); - session.setTabSize(2); - session.setUseSoftTabs(true); - - this.aceEditor = editor; - }; - - $scope.formatJson = (event) => { - this._format(event, compactStringify, { - maxLength: this._getCodeWidth(), - }); - }; - - $scope.formatHJson = (event) => { - this._format(event, hjson.stringify, { - condense: this._getCodeWidth(), - bracesSameLine: true, - keepWsc: true, - }); - }; - } - - _getCodeWidth() { - return this.aceEditor.getSession().getWrapLimit(); - } - - _format(event, stringify, opts) { - event.preventDefault(); - - let newSpec; - try { - const spec = hjson.parse(this.aceEditor.getSession().doc.getValue(), { legacyRoot: false, keepWsc: true }); - newSpec = stringify(spec, opts); - } catch (err) { - // This is a common case - user tries to format an invalid HJSON text - toastNotifications.addError(err, { - title: i18n.translate('visTypeVega.editor.formatError', { - defaultMessage: 'Error formatting spec', - }), - }); - return; - } - - // ui-ace only accepts changes from the editor when they - // happen outside of a digest cycle - // Per @spalger, we used $$postDigest() instead of setTimeout(() => {}, 0) - // because it better described the intention. - this.$scope.$$postDigest(() => { - // set the new value to the session doc so that it - // is treated as an edit by ace: ace adds it to the - // undo stack and emits it as a change like all - // other edits - this.aceEditor.getSession().doc.setValue(newSpec); - }); - } -} diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_editor_template.html b/src/legacy/core_plugins/vis_type_vega/public/vega_editor_template.html deleted file mode 100644 index 4d5d6189f3302..0000000000000 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_editor_template.html +++ /dev/null @@ -1,30 +0,0 @@ -
-
- -
- - - -
- -
diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_type.ts b/src/legacy/core_plugins/vis_type_vega/public/vega_type.ts index 6ffcd8867ffea..0d5290ddbefc7 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_type.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/vega_type.ts @@ -24,9 +24,9 @@ import { DefaultEditorSize } from 'ui/vis/editor_size'; // @ts-ignore import { defaultFeedbackMessage } from 'ui/vis/default_feedback_message'; -import vegaEditorTemplate from './vega_editor_template.html'; import { visFactory } from '../../visualizations/public'; import { VegaVisualizationDependencies } from './plugin'; +import { VegaVisEditor } from './components'; import { createVegaRequestHandler } from './vega_request_handler'; // @ts-ignore @@ -48,7 +48,7 @@ export const createVegaTypeDefinition = (dependencies: VegaVisualizationDependen icon: 'visVega', visConfig: { defaults: { spec: defaultSpec } }, editorConfig: { - optionsTemplate: vegaEditorTemplate, + optionsTemplate: VegaVisEditor, enableAutoApply: true, defaultSize: DefaultEditorSize.MEDIUM, }, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 351ebc3cb0e5f..34092fe93b047 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -3157,11 +3157,8 @@ "visTypeVega.editor.formatError": "仕様のフォーマット中にエラーが発生", "visTypeVega.editor.reformatAsHJSONButtonLabel": "HJSON に変換", "visTypeVega.editor.reformatAsJSONButtonLabel": "JSON に変換しコメントを削除", - "visTypeVega.editor.vegaDocumentationLinkText": "Vega ドキュメント", "visTypeVega.editor.vegaEditorOptionsButtonAriaLabel": "Vega エディターオプション", "visTypeVega.editor.vegaHelpButtonAriaLabel": "Vega ヘルプ", - "visTypeVega.editor.vegaHelpLinkText": "Kibana Vega ヘルプ", - "visTypeVega.editor.vegaLiteDocumentationLinkText": "Vega-Lite ドキュメンテーション", "visTypeVega.emsFileParser.emsFileNameDoesNotExistErrorMessage": "{emsfile} {emsfileName} が存在しません", "visTypeVega.emsFileParser.missingNameOfFileErrorMessage": "{dataUrlParamValue} の {dataUrlParam} には {nameParam} パラメーター (ファイル名) が必要です", "visTypeVega.esQueryParser.autointervalValueTypeErrorMessage": "{autointerval} は文字 {trueValue} または数字である必要があります", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 7251a8931b78c..79ffd81b1b533 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3158,11 +3158,8 @@ "visTypeVega.editor.formatError": "格式化规范时出错", "visTypeVega.editor.reformatAsHJSONButtonLabel": "重新格式化为 HJSON", "visTypeVega.editor.reformatAsJSONButtonLabel": "重新格式化为 JSON,删除注释", - "visTypeVega.editor.vegaDocumentationLinkText": "Vega 文档", "visTypeVega.editor.vegaEditorOptionsButtonAriaLabel": "Vega 编辑器选项", "visTypeVega.editor.vegaHelpButtonAriaLabel": "Vega 帮助", - "visTypeVega.editor.vegaHelpLinkText": "Kibana Vega 帮助", - "visTypeVega.editor.vegaLiteDocumentationLinkText": "Vega-Lite 文档", "visTypeVega.emsFileParser.emsFileNameDoesNotExistErrorMessage": "{emsfile} {emsfileName} 不存在", "visTypeVega.emsFileParser.missingNameOfFileErrorMessage": "具有 {dataUrlParamValue} 的 {dataUrlParam} 需要 {nameParam} 参数(文件名)", "visTypeVega.esQueryParser.autointervalValueTypeErrorMessage": "{autointerval} 必须为 {trueValue} 或数字", From 6e89f8ab7d132239b3ce7200c15954c243627895 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 18 Oct 2019 14:36:01 +0100 Subject: [PATCH 08/29] [ML] Disable exclude frequent if no by or over has been selected (#48625) * [ML] Disable exclude frequent if no by or over has been selected * fixing typo in comment --- .../advanced_detector_modal.tsx | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx index 9b56c9d2cc858..2b2a7ce54c37d 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx @@ -87,6 +87,7 @@ export const AdvancedDetectorModal: FC = ({ ); const [descriptionOption, setDescriptionOption] = useState(detector.description || ''); const [fieldsEnabled, setFieldsEnabled] = useState(true); + const [excludeFrequentEnabled, setExcludeFrequentEnabled] = useState(true); const [fieldOptionEnabled, setFieldOptionEnabled] = useState(true); const { descriptionPlaceholder, setDescriptionPlaceholder } = useDetectorPlaceholder(detector); @@ -117,6 +118,9 @@ export const AdvancedDetectorModal: FC = ({ useEffect(() => { const agg = getAgg(aggOption.label); let field = getField(fieldOption.label); + const byField = getField(byFieldOption.label); + const overField = getField(overFieldOption.label); + const partitionField = getField(partitionFieldOption.label); if (agg !== null) { setFieldsEnabled(true); @@ -126,6 +130,8 @@ export const AdvancedDetectorModal: FC = ({ field = eventRateField; } else { setFieldOptionEnabled(true); + // only enable exclude frequent if there is a by or over selected + setExcludeFrequentEnabled(byField !== null || overField !== null); } } else { setFieldsEnabled(false); @@ -134,9 +140,9 @@ export const AdvancedDetectorModal: FC = ({ const dtr: RichDetector = { agg, field, - byField: getField(byFieldOption.label), - overField: getField(overFieldOption.label), - partitionField: getField(partitionFieldOption.label), + byField, + overField, + partitionField, excludeFrequent: excludeFrequentOption.label !== '' ? excludeFrequentOption.label : null, description: descriptionOption !== '' ? descriptionOption : null, }; @@ -157,9 +163,20 @@ export const AdvancedDetectorModal: FC = ({ setFieldsEnabled(aggOption.label !== ''); if (agg !== null) { setFieldOptionEnabled(isFieldlessAgg(agg) === false); + + const byField = getField(byFieldOption.label); + const overField = getField(overFieldOption.label); + setExcludeFrequentEnabled(byField !== null || overField !== null); } }, []); + useEffect(() => { + // wipe the exclude frequent choice if the select has been disabled + if (excludeFrequentEnabled === false) { + setExcludeFrequentOption(emptyOption); + } + }, [excludeFrequentEnabled]); + function onCreateClick() { detectorChangeHandler(detector, payload.index); } @@ -245,7 +262,7 @@ export const AdvancedDetectorModal: FC = ({ selectedOptions={[excludeFrequentOption]} onChange={onOptionChange(setExcludeFrequentOption)} isClearable={true} - isDisabled={fieldsEnabled === false} + isDisabled={fieldsEnabled === false || excludeFrequentEnabled === false} />
From f13949acd8286ee20027fb56cc0f76c8d09b646c Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 18 Oct 2019 14:37:08 +0100 Subject: [PATCH 09/29] [ML] Adding time range to wizard summary step (#48620) --- .../advanced_detector_modal.tsx | 1 + .../advanced_detector_modal/descriptions.tsx | 3 +- .../components/job_details/job_details.tsx | 30 +++++++++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx index 2b2a7ce54c37d..97fb8c1d41fc5 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx @@ -273,6 +273,7 @@ export const AdvancedDetectorModal: FC = ({ setDescriptionOption(e.target.value)} diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/descriptions.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/descriptions.tsx index 6bef006b83ef7..e7a306decfbef 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/descriptions.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/descriptions.tsx @@ -168,6 +168,7 @@ export const DescriptionDescription: FC = memo(({ children }) => { ); return ( {title}} description={ @@ -177,7 +178,7 @@ export const DescriptionDescription: FC = memo(({ children }) => { /> } > - + <>{children} diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/job_details.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/job_details.tsx index 885ba92e5e0de..dc0311e552bda 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/job_details.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/summary_step/components/job_details/job_details.tsx @@ -6,6 +6,7 @@ import React, { FC, useContext } from 'react'; import { i18n } from '@kbn/i18n'; +import moment from 'moment'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlexGroup, EuiFlexItem, EuiDescriptionList } from '@elastic/eui'; import { JobCreatorContext } from '../../../job_creator_context'; @@ -16,11 +17,16 @@ import { } from '../../../../../common/job_creator'; import { newJobDefaults } from '../../../../../utils/new_job_defaults'; import { ListItems, falseLabel, trueLabel, defaultLabel, Italic } from '../common'; +import { useKibanaContext } from '../../../../../../../contexts/kibana'; export const JobDetails: FC = () => { const { jobCreator } = useContext(JobCreatorContext); + const kibanaContext = useKibanaContext(); + const dateFormat: string = kibanaContext.kibanaConfig.get('dateFormat'); const { anomaly_detectors: anomalyDetectors } = newJobDefaults(); + const isAdvanced = isAdvancedJobCreator(jobCreator); + const modelMemoryLimitDefault = anomalyDetectors.model_memory_limit || ''; const modelMemoryLimit = jobCreator.modelMemoryLimit !== null ? ( @@ -117,7 +123,7 @@ export const JobDetails: FC = () => { }); } - if (isAdvancedJobCreator(jobCreator) && jobCreator.categorizationFieldName !== null) { + if (isAdvanced && jobCreator.categorizationFieldName !== null) { detectorDetails.push({ title: i18n.translate( 'xpack.ml.newJob.wizard.summaryStep.jobDetails.categorizationField.title', @@ -129,7 +135,7 @@ export const JobDetails: FC = () => { }); } - if (isAdvancedJobCreator(jobCreator) && jobCreator.summaryCountFieldName !== null) { + if (isAdvanced && jobCreator.summaryCountFieldName !== null) { detectorDetails.push({ title: i18n.translate( 'xpack.ml.newJob.wizard.summaryStep.jobDetails.summaryCountField.title', @@ -185,6 +191,21 @@ export const JobDetails: FC = () => { }, ]; + const timeRangeDetails: ListItems[] = [ + { + title: i18n.translate('xpack.ml.newJob.wizard.summaryStep.timeRange.start.title', { + defaultMessage: 'Start', + }), + description: moment(jobCreator.start).format(dateFormat), + }, + { + title: i18n.translate('xpack.ml.newJob.wizard.summaryStep.timeRange.end.title', { + defaultMessage: 'End', + }), + description: moment(jobCreator.end).format(dateFormat), + }, + ]; + return ( @@ -196,6 +217,11 @@ export const JobDetails: FC = () => { + {isAdvanced === false && ( + + + + )} ); }; From 894fff0f8e480a8d7f3b7aeb27e5724fd872d59d Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Fri, 18 Oct 2019 19:11:10 +0530 Subject: [PATCH 10/29] main and nav landmark a11y fixes (#48381) * main and nav landmark a11y fixes * deduping i18n keys * renaming appNav aria-label prop --- src/core/public/chrome/ui/header/header.tsx | 22 +++++++++++++++---- .../dev_tools/partials/dev_tools_app.html | 10 ++++----- .../public/chrome/directives/kbn_chrome.html | 4 ++-- .../management/components/sidebar_nav.tsx | 4 ++++ .../apm/public/new-platform/plugin.tsx | 2 +- .../public/components/admin_page/admin.tsx | 4 ++-- .../components/navigation/app_navigation.tsx | 7 +++--- .../framework/kibana_framework_adapter.ts | 4 ++-- .../public/pages/infrastructure/index.tsx | 6 ++++- .../plugins/infra/public/pages/logs/index.tsx | 9 ++++---- .../plugins/siem/public/pages/home/index.tsx | 7 +++++- .../plugins/uptime/public/uptime_app.tsx | 4 ++-- 12 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index f24b0ed1681aa..4e73f49527856 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -406,12 +406,26 @@ class HeaderUI extends Component { data-test-subj="navDrawer" isLocked={isLocked} onIsLockedUpdate={onIsLockedUpdate} + aria-label={i18n.translate('core.ui.primaryNav.screenReaderLabel', { + defaultMessage: 'Primary', + })} > - + + ); diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/partials/dev_tools_app.html b/src/legacy/core_plugins/kibana/public/dev_tools/partials/dev_tools_app.html index e9424534cd9d2..6c076092c76d5 100644 --- a/src/legacy/core_plugins/kibana/public/dev_tools/partials/dev_tools_app.html +++ b/src/legacy/core_plugins/kibana/public/dev_tools/partials/dev_tools_app.html @@ -1,9 +1,9 @@ -
- +
+ -
-
+
+ diff --git a/src/legacy/ui/public/chrome/directives/kbn_chrome.html b/src/legacy/ui/public/chrome/directives/kbn_chrome.html index ced89287d310f..541082e68de58 100644 --- a/src/legacy/ui/public/chrome/directives/kbn_chrome.html +++ b/src/legacy/ui/public/chrome/directives/kbn_chrome.html @@ -1,9 +1,9 @@
-
+ >
diff --git a/src/legacy/ui/public/management/components/sidebar_nav.tsx b/src/legacy/ui/public/management/components/sidebar_nav.tsx index ef232c7ef7eda..f0ac787e0ef44 100644 --- a/src/legacy/ui/public/management/components/sidebar_nav.tsx +++ b/src/legacy/ui/public/management/components/sidebar_nav.tsx @@ -19,6 +19,7 @@ import { EuiIcon, EuiSideNav, IconType } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; import React from 'react'; import { IndexedArray } from 'ui/indexed_array'; @@ -73,6 +74,9 @@ export class SidebarNav extends React.Component { public render() { return ( -
+
{
- + ); } } diff --git a/x-pack/legacy/plugins/infra/public/components/navigation/app_navigation.tsx b/x-pack/legacy/plugins/infra/public/components/navigation/app_navigation.tsx index b1eef34001750..fe3c930f9e08e 100644 --- a/x-pack/legacy/plugins/infra/public/components/navigation/app_navigation.tsx +++ b/x-pack/legacy/plugins/infra/public/components/navigation/app_navigation.tsx @@ -9,11 +9,12 @@ import React from 'react'; import euiStyled from '../../../../../common/eui_styled_components'; interface AppNavigationProps { + 'aria-label': string; children: React.ReactNode; } -export const AppNavigation = ({ children }: AppNavigationProps) => ( -