From d27fc476dd53afdf5ad9393e903c4d25de40b257 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 14 Feb 2020 08:36:50 -0700 Subject: [PATCH 01/32] [Maps] refactor Join component to remove componentDidUpdate (#57518) * [Maps] refactor Join component to remove componentDidUpdate * [Maps] refactor LayerPanel to remove getDerivedStateFromProps * consolidate async layer state loading into LayerPanel component * fix jest snapshot Co-authored-by: Elastic Machine --- .../__snapshots__/view.test.js.snap | 5 +- .../connected_components/layer_panel/index.js | 4 +- .../layer_panel/join_editor/resources/join.js | 71 +++---------------- .../layer_panel/join_editor/view.js | 4 +- .../connected_components/layer_panel/view.js | 66 +++++++++-------- .../maps/public/layers/vector_layer.js | 6 +- 6 files changed, 56 insertions(+), 100 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap index 101716d297b81..7997cde97d89c 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap @@ -101,7 +101,10 @@ exports[`LayerPanel is rendered 1`] = ` mockSourceSettings - + { - return _.get(props, 'join.right.indexPatternId'); -}; - export class Join extends Component { state = { - leftFields: null, - leftSourceName: '', rightFields: undefined, indexPattern: undefined, loadError: undefined, - prevIndexPatternId: getIndexPatternId(this.props), }; componentDidMount() { this._isMounted = true; - this._loadLeftFields(); - this._loadLeftSourceName(); + this._loadRightFields(_.get(this.props.join, 'right.indexPatternId')); } componentWillUnmount() { this._isMounted = false; } - componentDidUpdate() { - if (!this.state.rightFields && getIndexPatternId(this.props) && !this.state.loadError) { - this._loadRightFields(getIndexPatternId(this.props)); - } - } - - static getDerivedStateFromProps(nextProps, prevState) { - const nextIndexPatternId = getIndexPatternId(nextProps); - if (nextIndexPatternId !== prevState.prevIndexPatternId) { - return { - rightFields: undefined, - loadError: undefined, - prevIndexPatternId: nextIndexPatternId, - }; - } - - return null; - } - async _loadRightFields(indexPatternId) { if (!indexPatternId) { return; @@ -79,11 +52,6 @@ export class Join extends Component { return; } - if (indexPatternId !== this.state.prevIndexPatternId) { - // ignore out of order responses - return; - } - if (!this._isMounted) { return; } @@ -94,34 +62,6 @@ export class Join extends Component { }); } - async _loadLeftSourceName() { - const leftSourceName = await this.props.layer.getSourceName(); - if (!this._isMounted) { - return; - } - this.setState({ leftSourceName }); - } - - async _loadLeftFields() { - let leftFields; - try { - const leftFieldsInstances = await this.props.layer.getLeftJoinFields(); - const leftFieldPromises = leftFieldsInstances.map(async field => { - return { - name: field.getName(), - label: await field.getLabel(), - }; - }); - leftFields = await Promise.all(leftFieldPromises); - } catch (error) { - leftFields = []; - } - if (!this._isMounted) { - return; - } - this.setState({ leftFields }); - } - _onLeftFieldChange = leftField => { this.props.onChange({ leftField: leftField, @@ -130,6 +70,11 @@ export class Join extends Component { }; _onRightSourceChange = ({ indexPatternId, indexPatternTitle }) => { + this.setState({ + rightFields: undefined, + loadError: undefined, + }); + this._loadRightFields(indexPatternId); this.props.onChange({ leftField: this.props.join.leftField, right: { @@ -181,8 +126,8 @@ export class Join extends Component { }; render() { - const { join, onRemove } = this.props; - const { leftSourceName, leftFields, rightFields, indexPattern } = this.state; + const { join, onRemove, leftFields, leftSourceName } = this.props; + const { rightFields, indexPattern } = this.state; const right = _.get(join, 'right', {}); const rightSourceName = right.indexPatternTitle ? right.indexPatternTitle diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/view.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/view.js index 9f3461e45dfd4..92e32885d43a8 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/view.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/view.js @@ -20,7 +20,7 @@ import { Join } from './resources/join'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -export function JoinEditor({ joins, layer, onChange }) { +export function JoinEditor({ joins, layer, onChange, leftJoinFields, layerDisplayName }) { const renderJoins = () => { return joins.map((joinDescriptor, index) => { const handleOnChange = updatedDescriptor => { @@ -39,6 +39,8 @@ export function JoinEditor({ joins, layer, onChange }) { layer={layer} onChange={handleOnChange} onRemove={handleOnRemove} + leftFields={leftJoinFields} + leftSourceName={layerDisplayName} /> ); diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js index 50c0949cf91ae..755d4bb6b323a 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js @@ -37,30 +37,17 @@ const localStorage = new Storage(window.localStorage); import { npStart } from 'ui/new_platform'; export class LayerPanel extends React.Component { - static getDerivedStateFromProps(nextProps, prevState) { - const nextId = nextProps.selectedLayer ? nextProps.selectedLayer.getId() : null; - if (nextId !== prevState.prevId) { - return { - displayName: '', - immutableSourceProps: [], - hasLoadedSourcePropsForLayer: false, - prevId: nextId, - }; - } - return null; - } - - state = {}; + state = { + displayName: '', + immutableSourceProps: [], + leftJoinFields: null, + }; componentDidMount() { this._isMounted = true; this.loadDisplayName(); this.loadImmutableSourceProperties(); - } - - componentDidUpdate() { - this.loadDisplayName(); - this.loadImmutableSourceProperties(); + this.loadLeftJoinFields(); } componentWillUnmount() { @@ -73,27 +60,45 @@ export class LayerPanel extends React.Component { } const displayName = await this.props.selectedLayer.getDisplayName(); - if (!this._isMounted || displayName === this.state.displayName) { - return; + if (this._isMounted) { + this.setState({ displayName }); } - - this.setState({ displayName }); }; loadImmutableSourceProperties = async () => { - if (this.state.hasLoadedSourcePropsForLayer || !this.props.selectedLayer) { + if (!this.props.selectedLayer) { return; } const immutableSourceProps = await this.props.selectedLayer.getImmutableSourceProperties(); if (this._isMounted) { - this.setState({ - immutableSourceProps, - hasLoadedSourcePropsForLayer: true, - }); + this.setState({ immutableSourceProps }); } }; + async loadLeftJoinFields() { + if (!this.props.selectedLayer || !this.props.selectedLayer.isJoinable()) { + return; + } + + let leftJoinFields; + try { + const leftFieldsInstances = await this.props.selectedLayer.getLeftJoinFields(); + const leftFieldPromises = leftFieldsInstances.map(async field => { + return { + name: field.getName(), + label: await field.getLabel(), + }; + }); + leftJoinFields = await Promise.all(leftFieldPromises); + } catch (error) { + leftJoinFields = []; + } + if (this._isMounted) { + this.setState({ leftJoinFields }); + } + } + _onSourceChange = ({ propName, value }) => { this.props.updateSourceProp(this.props.selectedLayer.getId(), propName, value); }; @@ -121,7 +126,10 @@ export class LayerPanel extends React.Component { return ( - + diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index 31c3831fb612a..1698d52ea4406 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -187,10 +187,6 @@ export class VectorLayer extends AbstractLayer { return await this._source.getLeftJoinFields(); } - async getSourceName() { - return this._source.getDisplayName(); - } - _getJoinFields() { const joinFields = []; this.getValidJoins().forEach(join => { @@ -272,7 +268,7 @@ export class VectorLayer extends AbstractLayer { try { startLoading(sourceDataId, requestToken, searchFilters); - const leftSourceName = await this.getSourceName(); + const leftSourceName = await this._source.getDisplayName(); const { propertiesMap } = await joinSource.getPropertiesMap( searchFilters, leftSourceName, From 52b4fe74049655fd1d58b6d108708c549b6f63be Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 14 Feb 2020 15:54:49 +0000 Subject: [PATCH 02/32] [ML] Categorization wizard functional tests (#57600) * [ML] Categorization wizard functional tests * changes based on review * some idiot left his own name in the code --- .../detector_cards.tsx | 2 + .../examples_valid_callout.tsx | 6 +- .../categorization_view/field_examples.tsx | 8 +- .../anomaly_detection/categorization_job.ts | 395 ++++++++++++++++++ .../anomaly_detection/index.ts | 1 + .../services/machine_learning/index.ts | 1 + .../machine_learning/job_type_selection.ts | 9 + .../job_wizard_categorization.ts | 63 +++ .../machine_learning/job_wizard_common.ts | 10 + x-pack/test/functional/services/ml.ts | 3 + 10 files changed, 496 insertions(+), 2 deletions(-) create mode 100644 x-pack/test/functional/apps/machine_learning/anomaly_detection/categorization_job.ts create mode 100644 x-pack/test/functional/services/machine_learning/job_wizard_categorization.ts diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_detector/detector_cards.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_detector/detector_cards.tsx index 68d5fc24a96e3..991e1d5c49b7a 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_detector/detector_cards.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_detector/detector_cards.tsx @@ -17,6 +17,7 @@ interface CardProps { export const CountCard: FC = ({ onClick, isSelected }) => ( = ({ onClick, isSelected }) => ( export const RareCard: FC = ({ onClick, isSelected }) => ( = ({ } return ( - + {validationChecks.map((v, i) => (
{v.message}
))} diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/field_examples.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/field_examples.tsx index 51cea179a6c0d..d3f1f0e58698b 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/field_examples.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/field_examples.tsx @@ -57,7 +57,13 @@ export const FieldExamples: FC = ({ fieldExamples }) => { txt.push(buffer); return { example: txt }; }); - return ; + return ( + + ); }; const Token: FC = ({ children }) => ( diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/categorization_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/categorization_job.ts new file mode 100644 index 0000000000000..6ea9e694d2955 --- /dev/null +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/categorization_job.ts @@ -0,0 +1,395 @@ +/* + * 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 expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../legacy/plugins/ml/common/constants/new_job'; + +// eslint-disable-next-line import/no-default-export +export default function({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + const jobId = `categorization_${Date.now()}`; + const jobIdClone = `${jobId}_clone`; + const jobDescription = + 'Create categorization job based on the categorization_functional_test dataset with a count rare'; + const jobGroups = ['automated', 'categorization']; + const jobGroupsClone = [...jobGroups, 'clone']; + const detectorTypeIdentifier = 'Rare'; + const categorizationFieldIdentifier = 'field1'; + const categorizationExampleCount = 5; + const bucketSpan = '15m'; + const memoryLimit = '15mb'; + + function getExpectedRow(expectedJobId: string, expectedJobGroups: string[]) { + return { + id: expectedJobId, + description: jobDescription, + jobGroups: [...new Set(expectedJobGroups)].sort(), + recordCount: '1,501', + memoryStatus: 'ok', + jobState: 'closed', + datafeedState: 'stopped', + latestTimestamp: '2019-11-21 06:01:13', + }; + } + + function getExpectedCounts(expectedJobId: string) { + return { + job_id: expectedJobId, + processed_record_count: '1,501', + processed_field_count: '1,501', + input_bytes: '335.4 KB', + input_field_count: '1,501', + invalid_date_count: '0', + missing_field_count: '0', + out_of_order_timestamp_count: '0', + empty_bucket_count: '21,428', + sparse_bucket_count: '0', + bucket_count: '22,059', + earliest_record_timestamp: '2019-04-05 11:25:35', + latest_record_timestamp: '2019-11-21 06:01:13', + input_record_count: '1,501', + latest_bucket_timestamp: '2019-11-21 06:00:00', + latest_empty_bucket_timestamp: '2019-11-21 05:45:00', + }; + } + + function getExpectedModelSizeStats(expectedJobId: string) { + return { + job_id: expectedJobId, + result_type: 'model_size_stats', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '15.0 MB', + total_by_field_count: '30', + total_over_field_count: '0', + total_partition_field_count: '2', + bucket_allocation_failures_count: '0', + memory_status: 'ok', + timestamp: '2019-11-21 05:45:00', + }; + } + + describe('categorization', function() { + this.tags(['smoke', 'mlqa']); + before(async () => { + await esArchiver.load('ml/categorization'); + await ml.api.createCalendar('wizard-test-calendar'); + }); + + after(async () => { + await esArchiver.unload('ml/categorization'); + await ml.api.cleanMlIndices(); + }); + + it('job creation loads the job management page', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + }); + + it('job creation loads the new job source selection page', async () => { + await ml.jobManagement.navigateToNewJobSourceSelection(); + }); + + it('job creation loads the job type selection page', async () => { + await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob( + 'categorization_functional_test' + ); + }); + + it('job creation loads the categorization job wizard page', async () => { + await ml.jobTypeSelection.selectCategorizationJob(); + }); + + it('job creation displays the time range step', async () => { + await ml.jobWizardCommon.assertTimeRangeSectionExists(); + }); + + it('job creation sets the timerange', async () => { + await ml.jobWizardCommon.clickUseFullDataButton( + 'Apr 5, 2019 @ 11:25:35.770', + 'Nov 21, 2019 @ 06:01:13.914' + ); + }); + + it('job creation displays the event rate chart', async () => { + await ml.jobWizardCommon.assertEventRateChartExists(); + await ml.jobWizardCommon.assertEventRateChartHasData(); + }); + + it('job creation displays the pick fields step', async () => { + await ml.jobWizardCommon.advanceToPickFieldsSection(); + }); + + it(`job creation selects ${detectorTypeIdentifier} detector type`, async () => { + await ml.jobWizardCategorization.assertCategorizationDetectorTypeSelectionExists(); + await ml.jobWizardCategorization.selectCategorizationDetectorType(detectorTypeIdentifier); + }); + + it(`job creation selects the categorization field`, async () => { + await ml.jobWizardCategorization.assertCategorizationFieldInputExists(); + await ml.jobWizardCategorization.selectCategorizationField(categorizationFieldIdentifier); + await ml.jobWizardCategorization.assertCategorizationExamplesCallout( + CATEGORY_EXAMPLES_VALIDATION_STATUS.VALID + ); + await ml.jobWizardCategorization.assertCategorizationExamplesTable( + categorizationExampleCount + ); + }); + + it('job creation inputs the bucket span', async () => { + await ml.jobWizardCommon.assertBucketSpanInputExists(); + await ml.jobWizardCommon.setBucketSpan(bucketSpan); + }); + + it('job creation displays the job details step', async () => { + await ml.jobWizardCommon.advanceToJobDetailsSection(); + }); + + it('job creation inputs the job id', async () => { + await ml.jobWizardCommon.assertJobIdInputExists(); + await ml.jobWizardCommon.setJobId(jobId); + }); + + it('job creation inputs the job description', async () => { + await ml.jobWizardCommon.assertJobDescriptionInputExists(); + await ml.jobWizardCommon.setJobDescription(jobDescription); + }); + + it('job creation inputs job groups', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + for (const jobGroup of jobGroups) { + await ml.jobWizardCommon.addJobGroup(jobGroup); + } + await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); + }); + + it('job creation opens the additional settings section', async () => { + await ml.jobWizardCommon.ensureAdditionalSettingsSectionOpen(); + }); + + it('job creation adds a new custom url', async () => { + await ml.jobWizardCommon.addCustomUrl({ label: 'check-kibana-dashboard' }); + }); + + it('job creation assigns calendars', async () => { + await ml.jobWizardCommon.addCalendar('wizard-test-calendar'); + }); + + it('job creation opens the advanced section', async () => { + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + }); + + it('job creation displays the model plot switch', async () => { + await ml.jobWizardCommon.assertModelPlotSwitchExists(); + await ml.jobWizardCommon.assertModelPlotSwitchEnabled(false); + await ml.jobWizardCommon.assertModelPlotSwitchCheckedState(false); + }); + + it('job creation enables the dedicated index switch', async () => { + await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); + await ml.jobWizardCommon.activateDedicatedIndexSwitch(); + }); + + it('job creation inputs the model memory limit', async () => { + await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); + await ml.jobWizardCommon.setModelMemoryLimit(memoryLimit); + }); + + it('job creation displays the validation step', async () => { + await ml.jobWizardCommon.advanceToValidationSection(); + }); + + it('job creation displays the summary step', async () => { + await ml.jobWizardCommon.advanceToSummarySection(); + }); + + it('job creation creates the job and finishes processing', async () => { + await ml.jobWizardCommon.assertCreateJobButtonExists(); + await ml.jobWizardCommon.createJobAndWaitForCompletion(); + }); + + it('job creation displays the created job in the job list', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.jobTable.waitForJobsToLoad(); + await ml.jobTable.filterWithSearchString(jobId); + const rows = await ml.jobTable.parseJobTable(); + expect(rows.filter(row => row.id === jobId)).to.have.length(1); + }); + + it('job creation displays details for the created job in the job list', async () => { + await ml.jobTable.assertJobRowFields(jobId, getExpectedRow(jobId, jobGroups)); + + await ml.jobTable.assertJobRowDetailsCounts( + jobId, + getExpectedCounts(jobId), + getExpectedModelSizeStats(jobId) + ); + }); + + it('job creation has detector results', async () => { + await ml.api.assertDetectorResultsExist(jobId, 0); + }); + + it('job cloning clicks the clone action and loads the single metric wizard', async () => { + await ml.jobTable.clickCloneJobAction(jobId); + await ml.jobTypeSelection.assertCategorizationJobWizardOpen(); + }); + + it('job cloning displays the time range step', async () => { + await ml.jobWizardCommon.assertTimeRangeSectionExists(); + }); + + it('job cloning sets the timerange', async () => { + await ml.jobWizardCommon.clickUseFullDataButton( + 'Apr 5, 2019 @ 11:25:35.770', + 'Nov 21, 2019 @ 06:01:13.914' + ); + }); + + it('job cloning displays the event rate chart', async () => { + await ml.jobWizardCommon.assertEventRateChartExists(); + await ml.jobWizardCommon.assertEventRateChartHasData(); + }); + + it('job cloning displays the pick fields step', async () => { + await ml.jobWizardCommon.advanceToPickFieldsSection(); + }); + + it('job cloning pre-fills field and aggregation', async () => { + await ml.jobWizardCategorization.assertCategorizationDetectorTypeSelectionExists(); + }); + + it('job cloning pre-fills the bucket span', async () => { + await ml.jobWizardCommon.assertBucketSpanInputExists(); + await ml.jobWizardCommon.assertBucketSpanValue(bucketSpan); + }); + + it('job cloning displays the job details step', async () => { + await ml.jobWizardCommon.advanceToJobDetailsSection(); + }); + + it('job cloning does not pre-fill the job id', async () => { + await ml.jobWizardCommon.assertJobIdInputExists(); + await ml.jobWizardCommon.assertJobIdValue(''); + }); + + it('job cloning inputs the clone job id', async () => { + await ml.jobWizardCommon.setJobId(jobIdClone); + }); + + it('job cloning pre-fills the job description', async () => { + await ml.jobWizardCommon.assertJobDescriptionInputExists(); + await ml.jobWizardCommon.assertJobDescriptionValue(jobDescription); + }); + + it('job cloning pre-fills job groups', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); + }); + + it('job cloning inputs the clone job group', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + await ml.jobWizardCommon.addJobGroup('clone'); + await ml.jobWizardCommon.assertJobGroupSelection(jobGroupsClone); + }); + + it('job cloning opens the additional settings section', async () => { + await ml.jobWizardCommon.ensureAdditionalSettingsSectionOpen(); + }); + + it('job cloning persists custom urls', async () => { + await ml.customUrls.assertCustomUrlItem(0, 'check-kibana-dashboard'); + }); + + it('job cloning persists assigned calendars', async () => { + await ml.jobWizardCommon.assertCalendarsSelection(['wizard-test-calendar']); + }); + + it('job cloning opens the advanced section', async () => { + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + }); + + it('job cloning pre-fills the model plot switch', async () => { + await ml.jobWizardCommon.assertModelPlotSwitchExists(); + await ml.jobWizardCommon.assertModelPlotSwitchEnabled(false); + await ml.jobWizardCommon.assertModelPlotSwitchCheckedState(false); + }); + + it('job cloning pre-fills the dedicated index switch', async () => { + await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); + await ml.jobWizardCommon.assertDedicatedIndexSwitchCheckedState(true); + }); + + it('job cloning pre-fills the model memory limit', async () => { + await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); + await ml.jobWizardCommon.assertModelMemoryLimitValue(memoryLimit); + }); + + it('job cloning displays the validation step', async () => { + await ml.jobWizardCommon.advanceToValidationSection(); + }); + + it('job cloning displays the summary step', async () => { + await ml.jobWizardCommon.advanceToSummarySection(); + }); + + it('job cloning creates the job and finishes processing', async () => { + await ml.jobWizardCommon.assertCreateJobButtonExists(); + await ml.jobWizardCommon.createJobAndWaitForCompletion(); + }); + + it('job cloning displays the created job in the job list', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.jobTable.waitForJobsToLoad(); + await ml.jobTable.filterWithSearchString(jobIdClone); + const rows = await ml.jobTable.parseJobTable(); + expect(rows.filter(row => row.id === jobIdClone)).to.have.length(1); + }); + + it('job cloning displays details for the created job in the job list', async () => { + await ml.jobTable.assertJobRowFields(jobIdClone, getExpectedRow(jobIdClone, jobGroupsClone)); + + await ml.jobTable.assertJobRowDetailsCounts( + jobIdClone, + getExpectedCounts(jobIdClone), + getExpectedModelSizeStats(jobIdClone) + ); + }); + + it('job cloning has detector results', async () => { + await ml.api.assertDetectorResultsExist(jobId, 0); + }); + + it('job deletion has results for the job before deletion', async () => { + await ml.api.assertJobResultsExist(jobIdClone); + }); + + it('job deletion triggers the delete action', async () => { + await ml.jobTable.clickDeleteJobAction(jobIdClone); + }); + + it('job deletion confirms the delete modal', async () => { + await ml.jobTable.confirmDeleteJobModal(); + }); + + it('job deletion does not display the deleted job in the job list any more', async () => { + await ml.jobTable.waitForJobsToLoad(); + await ml.jobTable.filterWithSearchString(jobIdClone); + const rows = await ml.jobTable.parseJobTable(); + expect(rows.filter(row => row.id === jobIdClone)).to.have.length(0); + }); + + it('job deletion does not have results for the deleted job any more', async () => { + await ml.api.assertNoJobResultsExist(jobIdClone); + }); + }); +} diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/index.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/index.ts index a52e3d3aca2c0..28e8b221cff4e 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/index.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/index.ts @@ -16,5 +16,6 @@ export default function({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./advanced_job')); loadTestFile(require.resolve('./single_metric_viewer')); loadTestFile(require.resolve('./anomaly_explorer')); + loadTestFile(require.resolve('./categorization_job')); }); } diff --git a/x-pack/test/functional/services/machine_learning/index.ts b/x-pack/test/functional/services/machine_learning/index.ts index b01f127519670..4cecd27631e18 100644 --- a/x-pack/test/functional/services/machine_learning/index.ts +++ b/x-pack/test/functional/services/machine_learning/index.ts @@ -21,6 +21,7 @@ export { MachineLearningJobTableProvider } from './job_table'; export { MachineLearningJobTypeSelectionProvider } from './job_type_selection'; export { MachineLearningJobWizardAdvancedProvider } from './job_wizard_advanced'; export { MachineLearningJobWizardCommonProvider } from './job_wizard_common'; +export { MachineLearningJobWizardCategorizationProvider } from './job_wizard_categorization'; export { MachineLearningJobWizardMultiMetricProvider } from './job_wizard_multi_metric'; export { MachineLearningJobWizardPopulationProvider } from './job_wizard_population'; export { MachineLearningNavigationProvider } from './navigation'; diff --git a/x-pack/test/functional/services/machine_learning/job_type_selection.ts b/x-pack/test/functional/services/machine_learning/job_type_selection.ts index 6686b5b28f200..be66c53326a23 100644 --- a/x-pack/test/functional/services/machine_learning/job_type_selection.ts +++ b/x-pack/test/functional/services/machine_learning/job_type_selection.ts @@ -45,5 +45,14 @@ export function MachineLearningJobTypeSelectionProvider({ getService }: FtrProvi async assertAdvancedJobWizardOpen() { await testSubjects.existOrFail('mlPageJobWizard advanced'); }, + + async selectCategorizationJob() { + await testSubjects.clickWhenNotDisabled('mlJobTypeLinkCategorizationJob'); + await this.assertCategorizationJobWizardOpen(); + }, + + async assertCategorizationJobWizardOpen() { + await testSubjects.existOrFail('mlPageJobWizard categorization'); + }, }; } diff --git a/x-pack/test/functional/services/machine_learning/job_wizard_categorization.ts b/x-pack/test/functional/services/machine_learning/job_wizard_categorization.ts new file mode 100644 index 0000000000000..cb590c7022965 --- /dev/null +++ b/x-pack/test/functional/services/machine_learning/job_wizard_categorization.ts @@ -0,0 +1,63 @@ +/* + * 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 expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../ftr_provider_context'; +import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../legacy/plugins/ml/common/constants/new_job'; + +export function MachineLearningJobWizardCategorizationProvider({ getService }: FtrProviderContext) { + const comboBox = getService('comboBox'); + const testSubjects = getService('testSubjects'); + + return { + async assertCategorizationDetectorTypeSelectionExists() { + await testSubjects.existOrFail('~mlJobWizardCategorizationDetectorCountCard'); + await testSubjects.existOrFail('~mlJobWizardCategorizationDetectorRareCard'); + }, + + async selectCategorizationDetectorType(identifier: string) { + const id = `~mlJobWizardCategorizationDetector${identifier}Card`; + await testSubjects.existOrFail(id); + await testSubjects.clickWhenNotDisabled(id); + await testSubjects.existOrFail(`mlJobWizardCategorizationDetector${identifier}Card selected`); + }, + + async assertCategorizationFieldInputExists() { + await testSubjects.existOrFail('mlCategorizationFieldNameSelect > comboBoxInput'); + }, + + async selectCategorizationField(identifier: string) { + await comboBox.set('mlCategorizationFieldNameSelect > comboBoxInput', identifier); + + await this.assertCategorizationFieldSelection([identifier]); + }, + + async assertCategorizationFieldSelection(expectedIdentifier: string[]) { + const comboBoxSelectedOptions = await comboBox.getComboBoxSelectedOptions( + 'mlCategorizationFieldNameSelect > comboBoxInput' + ); + expect(comboBoxSelectedOptions).to.eql( + expectedIdentifier, + `Expected categorization field selection to be '${expectedIdentifier}' (got ${comboBoxSelectedOptions}')` + ); + }, + + async assertCategorizationExamplesCallout(status: CATEGORY_EXAMPLES_VALIDATION_STATUS) { + await testSubjects.existOrFail(`mlJobWizardCategorizationExamplesCallout ${status}`); + }, + + async assertCategorizationExamplesTable(exampleCount: number) { + const table = await testSubjects.find('mlJobWizardCategorizationExamplesTable'); + const body = await table.findAllByTagName('tbody'); + expect(body.length).to.eql(1, `Expected categorization field examples table to have a body`); + const rows = await body[0].findAllByTagName('tr'); + expect(rows.length).to.eql( + exampleCount, + `Expected categorization field examples table to have '${exampleCount}' rows (got ${rows.length}')` + ); + }, + }; +} diff --git a/x-pack/test/functional/services/machine_learning/job_wizard_common.ts b/x-pack/test/functional/services/machine_learning/job_wizard_common.ts index c2f408276d9e4..38e6694669c1a 100644 --- a/x-pack/test/functional/services/machine_learning/job_wizard_common.ts +++ b/x-pack/test/functional/services/machine_learning/job_wizard_common.ts @@ -224,6 +224,16 @@ export function MachineLearningJobWizardCommonProvider( expect(actualCheckedState).to.eql(expectedValue); }, + async assertModelPlotSwitchEnabled(expectedValue: boolean) { + const isEnabled = await testSubjects.isEnabled('mlJobWizardSwitchModelPlot'); + expect(isEnabled).to.eql( + expectedValue, + `Expected model plot switch to be '${expectedValue ? 'enabled' : 'disabled'}' (got ${ + isEnabled ? 'enabled' : 'disabled' + }')` + ); + }, + async assertDedicatedIndexSwitchExists( sectionOptions: SectionOptions = { withAdvancedSection: true } ) { diff --git a/x-pack/test/functional/services/ml.ts b/x-pack/test/functional/services/ml.ts index 5957a8a2eeb0a..18574c62b84d9 100644 --- a/x-pack/test/functional/services/ml.ts +++ b/x-pack/test/functional/services/ml.ts @@ -23,6 +23,7 @@ import { MachineLearningJobTableProvider, MachineLearningJobTypeSelectionProvider, MachineLearningJobWizardAdvancedProvider, + MachineLearningJobWizardCategorizationProvider, MachineLearningJobWizardCommonProvider, MachineLearningJobWizardMultiMetricProvider, MachineLearningJobWizardPopulationProvider, @@ -49,6 +50,7 @@ export function MachineLearningProvider(context: FtrProviderContext) { const jobTable = MachineLearningJobTableProvider(context); const jobTypeSelection = MachineLearningJobTypeSelectionProvider(context); const jobWizardAdvanced = MachineLearningJobWizardAdvancedProvider(context, common); + const jobWizardCategorization = MachineLearningJobWizardCategorizationProvider(context); const jobWizardCommon = MachineLearningJobWizardCommonProvider(context, common, customUrls); const jobWizardMultiMetric = MachineLearningJobWizardMultiMetricProvider(context); const jobWizardPopulation = MachineLearningJobWizardPopulationProvider(context); @@ -73,6 +75,7 @@ export function MachineLearningProvider(context: FtrProviderContext) { jobTable, jobTypeSelection, jobWizardAdvanced, + jobWizardCategorization, jobWizardCommon, jobWizardMultiMetric, jobWizardPopulation, From 98564f857d58828ba6de0c3fab80b5cef31cfe1d Mon Sep 17 00:00:00 2001 From: Corey Robertson Date: Fri, 14 Feb 2020 10:57:06 -0500 Subject: [PATCH 03/32] Update Canvas usage of Storage from kibana-utils (#55595) Co-authored-by: Elastic Machine --- x-pack/legacy/plugins/canvas/public/legacy.ts | 2 -- .../canvas/public/lib/__tests__/clipboard.js | 16 --------- .../plugins/canvas/public/lib/clipboard.js | 17 --------- .../canvas/public/lib/clipboard.test.ts | 36 +++++++++++++++++++ .../plugins/canvas/public/lib/clipboard.ts | 25 +++++++++++++ .../plugins/canvas/public/lib/get_window.ts | 6 ++-- .../legacy/plugins/canvas/public/plugin.tsx | 3 -- 7 files changed, 65 insertions(+), 40 deletions(-) delete mode 100644 x-pack/legacy/plugins/canvas/public/lib/__tests__/clipboard.js delete mode 100644 x-pack/legacy/plugins/canvas/public/lib/clipboard.js create mode 100644 x-pack/legacy/plugins/canvas/public/lib/clipboard.test.ts create mode 100644 x-pack/legacy/plugins/canvas/public/lib/clipboard.ts diff --git a/x-pack/legacy/plugins/canvas/public/legacy.ts b/x-pack/legacy/plugins/canvas/public/legacy.ts index ea873e6f2296d..0d2e77637f19d 100644 --- a/x-pack/legacy/plugins/canvas/public/legacy.ts +++ b/x-pack/legacy/plugins/canvas/public/legacy.ts @@ -10,7 +10,6 @@ import { CanvasStartDeps } from './plugin'; // eslint-disable-line import/order // @ts-ignore Untyped Kibana Lib import chrome, { loadingCount } from 'ui/chrome'; // eslint-disable-line import/order import { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; // eslint-disable-line import/order -import { Storage } from '../../../../../src/plugins/kibana_utils/public'; // eslint-disable-line import/order // @ts-ignore Untyped Kibana Lib import { formatMsg } from '../../../../../src/plugins/kibana_legacy/public'; // eslint-disable-line import/order @@ -31,7 +30,6 @@ const shimStartPlugins: CanvasStartDeps = { absoluteToParsedUrl, // ToDo: Copy directly into canvas formatMsg, - storage: Storage, // ToDo: Won't be a part of New Platform. Will need to handle internally trackSubUrlForApp: chrome.trackSubUrlForApp, }, diff --git a/x-pack/legacy/plugins/canvas/public/lib/__tests__/clipboard.js b/x-pack/legacy/plugins/canvas/public/lib/__tests__/clipboard.js deleted file mode 100644 index c616a76d0dcc3..0000000000000 --- a/x-pack/legacy/plugins/canvas/public/lib/__tests__/clipboard.js +++ /dev/null @@ -1,16 +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 expect from '@kbn/expect'; -import { setClipboardData, getClipboardData } from '../clipboard'; -import { elements } from '../../../__tests__/fixtures/workpads'; - -describe('clipboard', () => { - it('stores and retrieves clipboard data', () => { - setClipboardData(elements); - expect(getClipboardData()).to.eql(JSON.stringify(elements)); - }); -}); diff --git a/x-pack/legacy/plugins/canvas/public/lib/clipboard.js b/x-pack/legacy/plugins/canvas/public/lib/clipboard.js deleted file mode 100644 index 1fd14f086c949..0000000000000 --- a/x-pack/legacy/plugins/canvas/public/lib/clipboard.js +++ /dev/null @@ -1,17 +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 { LOCALSTORAGE_CLIPBOARD } from '../../common/lib/constants'; -import { getWindow } from './get_window'; - -let storage = null; - -export const initClipboard = function(Storage) { - storage = new Storage(getWindow().localStorage); -}; - -export const setClipboardData = data => storage.set(LOCALSTORAGE_CLIPBOARD, JSON.stringify(data)); -export const getClipboardData = () => storage.get(LOCALSTORAGE_CLIPBOARD); diff --git a/x-pack/legacy/plugins/canvas/public/lib/clipboard.test.ts b/x-pack/legacy/plugins/canvas/public/lib/clipboard.test.ts new file mode 100644 index 0000000000000..54c3000dae36c --- /dev/null +++ b/x-pack/legacy/plugins/canvas/public/lib/clipboard.test.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ +jest.mock('../../../../../../src/plugins/kibana_utils/public'); + +import { Storage } from '../../../../../../src/plugins/kibana_utils/public'; +import { setClipboardData, getClipboardData } from './clipboard'; +import { LOCALSTORAGE_CLIPBOARD } from '../../common/lib/constants'; +import { elements } from '../../__tests__/fixtures/workpads'; + +const set = jest.fn(); +const get = jest.fn(); + +describe('clipboard', () => { + beforeAll(() => { + // @ts-ignore + Storage.mockImplementation(() => ({ + set, + get, + })); + }); + + test('stores data to local storage', () => { + setClipboardData(elements); + + expect(set).toBeCalledWith(LOCALSTORAGE_CLIPBOARD, JSON.stringify(elements)); + }); + + test('gets data from local storage', () => { + getClipboardData(); + + expect(get).toBeCalledWith(LOCALSTORAGE_CLIPBOARD); + }); +}); diff --git a/x-pack/legacy/plugins/canvas/public/lib/clipboard.ts b/x-pack/legacy/plugins/canvas/public/lib/clipboard.ts new file mode 100644 index 0000000000000..50c5cdd0042fd --- /dev/null +++ b/x-pack/legacy/plugins/canvas/public/lib/clipboard.ts @@ -0,0 +1,25 @@ +/* + * 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 { Storage } from '../../../../../../src/plugins/kibana_utils/public'; +import { LOCALSTORAGE_CLIPBOARD } from '../../common/lib/constants'; +import { getWindow } from './get_window'; + +let storage: Storage; + +const getStorage = (): Storage => { + if (!storage) { + storage = new Storage(getWindow().localStorage); + } + + return storage; +}; + +export const setClipboardData = (data: any) => { + getStorage().set(LOCALSTORAGE_CLIPBOARD, JSON.stringify(data)); +}; + +export const getClipboardData = () => getStorage().get(LOCALSTORAGE_CLIPBOARD); diff --git a/x-pack/legacy/plugins/canvas/public/lib/get_window.ts b/x-pack/legacy/plugins/canvas/public/lib/get_window.ts index 1ee7e68be8485..42c632f4a514f 100644 --- a/x-pack/legacy/plugins/canvas/public/lib/get_window.ts +++ b/x-pack/legacy/plugins/canvas/public/lib/get_window.ts @@ -5,8 +5,10 @@ */ // return window if it exists, otherwise just return an object literal -const windowObj = { location: null }; +const windowObj = { location: null, localStorage: {} as Window['localStorage'] }; -export const getWindow = (): Window | { location: Location | null } => { +export const getWindow = (): + | Window + | { location: Location | null; localStorage: Window['localStorage'] } => { return typeof window === 'undefined' ? windowObj : window; }; diff --git a/x-pack/legacy/plugins/canvas/public/plugin.tsx b/x-pack/legacy/plugins/canvas/public/plugin.tsx index 44731628cf653..a5fbbccb4299f 100644 --- a/x-pack/legacy/plugins/canvas/public/plugin.tsx +++ b/x-pack/legacy/plugins/canvas/public/plugin.tsx @@ -8,7 +8,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Chrome } from 'ui/chrome'; import { i18n } from '@kbn/i18n'; -import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { CoreSetup, CoreStart, Plugin } from '../../../../../src/core/public'; import { HomePublicPluginSetup } from '../../../../../src/plugins/home/public'; // @ts-ignore: Untyped Local @@ -43,7 +42,6 @@ export interface CanvasStartDeps { __LEGACY: { absoluteToParsedUrl: (url: string, basePath: string) => any; formatMsg: any; - storage: typeof Storage; trackSubUrlForApp: Chrome['trackSubUrlForApp']; }; } @@ -92,7 +90,6 @@ export class CanvasPlugin loadExpressionTypes(); loadTransitions(); - initClipboard(plugins.__LEGACY.storage); initLoadingIndicator(core.http.addLoadingCountSource); core.chrome.setBadge( From 356e3a47768701740ae99863f8e0089258874a20 Mon Sep 17 00:00:00 2001 From: gchaps <33642766+gchaps@users.noreply.github.com> Date: Fri, 14 Feb 2020 08:24:27 -0800 Subject: [PATCH 04/32] [DOCS] Adds Save to Advanced Settings doc (#57696) * [DOCS] Adds Save to Advanced Settings doc * [DOCS] Incorporates review comments --- docs/management/advanced-options.asciidoc | 29 ++++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 9caa3900fccfd..ec626677d0902 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -8,6 +8,7 @@ for displayed decimal values. . Go to *Management > {kib} > Advanced Settings*. . Scroll or search for the setting you want to modify. . Enter a new value for the setting. +. Click *Save changes*. [float] @@ -34,7 +35,7 @@ removes it from {kib} permanently. [float] [[kibana-general-settings]] -=== General settings +==== General [horizontal] `csv:quoteValues`:: Set this property to `true` to quote exported values. @@ -109,7 +110,7 @@ cluster alert notifications from Monitoring. [float] [[kibana-accessibility-settings]] -=== Accessibility settings +==== Accessibility [horizontal] `accessibility:disableAnimations`:: Turns off all unnecessary animations in the @@ -117,14 +118,14 @@ cluster alert notifications from Monitoring. [float] [[kibana-dashboard-settings]] -=== Dashboard settings +==== Dashboard [horizontal] `xpackDashboardMode:roles`:: The roles that belong to <>. [float] [[kibana-discover-settings]] -=== Discover settings +==== Discover [horizontal] `context:defaultSize`:: The number of surrounding entries to display in the context view. The default value is 5. @@ -150,7 +151,7 @@ working on big documents. [float] [[kibana-notification-settings]] -=== Notifications settings +==== Notifications [horizontal] `notifications:banner`:: A custom banner intended for temporary notices to all users. @@ -169,7 +170,7 @@ displays. The default value is 10000. Set this field to `Infinity` to disable wa [float] [[kibana-reporting-settings]] -=== Reporting settings +==== Reporting [horizontal] `xpackReporting:customPdfLogo`:: A custom image to use in the footer of the PDF. @@ -177,7 +178,7 @@ displays. The default value is 10000. Set this field to `Infinity` to disable wa [float] [[kibana-rollups-settings]] -=== Rollup settings +==== Rollup [horizontal] `rollups:enableIndexPatterns`:: Enables the creation of index patterns that @@ -187,7 +188,7 @@ Refresh the page to apply the changes. [float] [[kibana-search-settings]] -=== Search settings +==== Search [horizontal] `courier:batchSearches`:: **Deprecated in 7.6. Starting in 8.0, this setting will be optimized internally.** @@ -215,21 +216,21 @@ might increase the search time. This setting is off by default. Users must opt-i [float] [[kibana-siem-settings]] -=== SIEM settings +==== SIEM [horizontal] `siem:defaultAnomalyScore`:: The threshold above which Machine Learning job anomalies are displayed in the SIEM app. `siem:defaultIndex`:: A comma-delimited list of Elasticsearch indices from which the SIEM app collects events. -`siem:enableNewsFeed`:: Enables the security news feed on the SIEM *Overview* +`siem:enableNewsFeed`:: Enables the security news feed on the SIEM *Overview* page. -`siem:newsFeedUrl`:: The URL from which the security news feed content is +`siem:newsFeedUrl`:: The URL from which the security news feed content is retrieved. `siem:refreshIntervalDefaults`:: The default refresh interval for the SIEM time filter, in milliseconds. `siem:timeDefaults`:: The default period of time in the SIEM time filter. [float] [[kibana-timelion-settings]] -=== Timelion settings +==== Timelion [horizontal] `timelion:default_columns`:: The default number of columns to use on a Timelion sheet. @@ -252,7 +253,7 @@ this is the number of buckets to try to represent. [float] [[kibana-visualization-settings]] -=== Visualization settings +==== Visualization [horizontal] `visualization:colorMapping`:: Maps values to specified colors in visualizations. @@ -273,7 +274,7 @@ If disabled, only visualizations that are considered production-ready are availa [float] [[kibana-telemetry-settings]] -=== Usage data settings +==== Usage data Helps improve the Elastic Stack by providing usage statistics for basic features. This data will not be shared outside of Elastic. From 0abfd3c72fb627232f56b959895e1b51fa8e70fd Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Fri, 14 Feb 2020 13:06:31 -0600 Subject: [PATCH 05/32] Upgrade EUI to v19.0.0 (#57284) * eui to v19.0.0 * typescript updates; idAria removal * src snapshot updates * mock euicode and euicodeblock for jest * x-pack snapshot updates * mock euicode for jest * more euicode snapshots * mock euicode in storyshots * types/enzyme yarn.lock * sidenav type update --- package.json | 2 +- packages/kbn-ui-shared-deps/package.json | 2 +- .../__snapshots__/no_results.test.js.snap | 64 +- .../np_ready/angular/directives/histogram.tsx | 2 +- .../angular/directives/no_results.test.js | 25 + src/legacy/server/sass/build.test.js | 69 +- .../field/__snapshots__/field.test.tsx.snap | 180 ---- .../management_app/components/field/field.tsx | 2 - .../static/forms/components/field.tsx | 1 - .../static/forms/components/form_row.tsx | 16 +- .../public/components/share_context_menu.tsx | 3 +- src/plugins/share/public/types.ts | 8 +- .../plugins/kbn_tp_run_pipeline/package.json | 2 +- .../kbn_tp_custom_visualizations/package.json | 2 +- .../kbn_tp_embeddable_explorer/package.json | 2 +- .../kbn_tp_sample_panel_action/package.json | 2 +- typings/@elastic/eui/index.d.ts | 2 - .../__test__/__snapshots__/List.test.tsx.snap | 6 - .../canvas/.storybook/storyshots.test.js | 13 + .../keyboard_shortcuts_doc.stories.storyshot | 792 ++++-------------- .../dense_vector_type.tsx | 1 - .../scaled_float_type.tsx | 1 - .../token_count_type.tsx | 1 - .../template_form/steps/step_logistics.tsx | 20 +- .../analysis_setup_indices_form.tsx | 9 +- .../analysis_setup_timerange_form.tsx | 17 +- .../fields_configuration_panel.tsx | 10 - .../indices_configuration_panel.tsx | 4 - .../name_configuration_panel.tsx | 2 - x-pack/legacy/plugins/infra/types/eui.d.ts | 17 - .../dimension_panel/dimension_panel.test.tsx | 29 +- .../common/model_memory_limit/description.tsx | 8 +- .../components/frequency/description.tsx | 8 +- .../components/query_delay/description.tsx | 8 +- .../components/scroll_size/description.tsx | 8 +- .../components/time_field/description.tsx | 3 +- .../components/calendars/description.tsx | 3 +- .../components/custom_urls/description.tsx | 3 +- .../dedicated_index/description.tsx | 3 +- .../components/model_plot/description.tsx | 3 +- .../components/groups/description.tsx | 8 +- .../job_description/description.tsx | 3 +- .../components/job_id/description.tsx | 9 +- .../advanced_detector_modal/descriptions.tsx | 21 +- .../components/bucket_span/description.tsx | 8 +- .../categorization_field/description.tsx | 3 +- .../components/influencers/description.tsx | 3 +- .../components/sparse_data/description.tsx | 3 +- .../components/split_field/description.tsx | 6 +- .../summary_count_field/description.tsx | 3 +- .../components/job_settings_form.tsx | 7 +- .../collection_enabled.test.js.snap | 26 +- .../collection_interval.test.js.snap | 52 +- .../__snapshots__/exporters.test.js.snap | 64 +- .../exporters/__tests__/exporters.test.js | 13 + .../__snapshots__/plugin_enabled.test.js.snap | 24 +- .../__tests__/plugin_enabled.test.js | 13 + .../__snapshots__/reason_found.test.js.snap | 104 +-- .../reasons/__tests__/reason_found.test.js | 13 + .../remote_cluster_form.test.js.snap | 75 +- .../report_listing.test.tsx.snap | 6 - .../note_card_body.test.tsx.snap | 63 +- .../__snapshots__/index.test.tsx.snap | 63 +- .../policy_form/steps/step_logistics.tsx | 8 - .../policy_form/steps/step_retention.tsx | 5 - .../policy_form/steps/step_settings.tsx | 20 +- .../components/repository_form/step_one.tsx | 5 +- .../type_settings/azure_settings.tsx | 18 - .../type_settings/fs_settings.tsx | 12 - .../type_settings/gcs_settings.tsx | 16 - .../type_settings/hdfs_settings.tsx | 22 +- .../type_settings/readonly_settings.tsx | 4 +- .../type_settings/s3_settings.tsx | 24 - .../steps/step_logistics.tsx | 23 +- .../steps/step_settings.tsx | 15 +- .../__snapshots__/monitor_list.test.tsx.snap | 3 - x-pack/package.json | 2 +- .../elasticsearch_privileges.test.tsx.snap | 6 - .../simple_privilege_section.test.tsx.snap | 3 - .../json_watch_edit_simulate.tsx | 4 - x-pack/typings/@elastic/eui/index.d.ts | 1 - yarn.lock | 18 +- 82 files changed, 616 insertions(+), 1536 deletions(-) diff --git a/package.json b/package.json index 26e1112ead697..3156e87e763b2 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "@elastic/charts": "^17.0.2", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "7.6.0", - "@elastic/eui": "18.3.0", + "@elastic/eui": "19.0.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.3.5", diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 0b1a31619fdf9..4b4db9d7f37f3 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -11,7 +11,7 @@ "devDependencies": { "@elastic/charts": "^17.0.2", "abort-controller": "^3.0.0", - "@elastic/eui": "18.3.0", + "@elastic/eui": "19.0.0", "@kbn/dev-utils": "1.0.0", "@kbn/i18n": "1.0.0", "@yarnpkg/lockfile": "^1.1.0", diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/__snapshots__/no_results.test.js.snap b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/__snapshots__/no_results.test.js.snap index 98cb3ccf6dd91..4126bd9d27ffd 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/__snapshots__/no_results.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/__snapshots__/no_results.test.js.snap @@ -77,12 +77,8 @@ Array [
- - + + 200 @@ -101,12 +97,8 @@ Array [
- - + + status:200 @@ -125,12 +117,8 @@ Array [
- - + + status:[400 TO 499] @@ -149,12 +137,8 @@ Array [
- - + + status:[400 TO 499] AND extension:PHP @@ -173,12 +157,8 @@ Array [
- - + + status:[400 TO 499] AND (extension:php OR extension:html) @@ -291,15 +271,9 @@ Array [
-
-
-              
+          
+
+              
                 {"reason":"Awful error"}
               
             
@@ -320,15 +294,9 @@ Array [
-
-
-              
+          
+
+              
                 {"reason":"Bad error"}
               
             
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/histogram.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/histogram.tsx index 77bbab97d95c7..8db3c77ba0f47 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/histogram.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/histogram.tsx @@ -41,7 +41,7 @@ import { } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; -import { EuiChartThemeType } from '@elastic/eui/src/themes/charts/themes'; +import { EuiChartThemeType } from '@elastic/eui/dist/eui_charts_theme'; import { Subscription } from 'rxjs'; import { getServices, timezoneProvider } from '../../../kibana_services'; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/no_results.test.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/no_results.test.js index 7de792c612993..98a4a926a282e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/no_results.test.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/no_results.test.js @@ -36,6 +36,31 @@ jest.mock('../../../kibana_services', () => { }; }); +// Mocking to prevent errors with React portal. +// Temporary until https://github.com/elastic/kibana/pull/55877 provides other alternatives. +jest.mock('@elastic/eui/lib/components/code/code_block', () => { + const React = require.requireActual('react'); + return { + EuiCodeBlock: ({ children }) => ( +
+
+          {children}
+        
+
+ ), + }; +}); +jest.mock('@elastic/eui/lib/components/code/code', () => { + const React = require.requireActual('react'); + return { + EuiCode: ({ children }) => ( + + {children} + + ), + }; +}); + beforeEach(() => { jest.clearAllMocks(); }); diff --git a/src/legacy/server/sass/build.test.js b/src/legacy/server/sass/build.test.js index 7092f6ad12921..46a898c30f84e 100644 --- a/src/legacy/server/sass/build.test.js +++ b/src/legacy/server/sass/build.test.js @@ -47,28 +47,7 @@ it('builds light themed SASS', async () => { expect(readFileSync(targetPath, 'utf8').replace(/(\/\*# sourceMappingURL=).*( \*\/)/, '$1...$2')) .toMatchInlineSnapshot(` - "/* 1 */ - /* 1 */ - /** - * 1. Extend beta badges to at least 40% of the container's width - * 2. Fix for IE to ensure badges are visible outside of a
+ } + > + xpack.monitoring.collection.enabled + - xpack.monitoring.collection.enabled - + /> @@ -214,15 +221,22 @@ exports[`ExplainCollectionEnabled should explain about xpack.monitoring.collecti paddingSize="l" transparentBackground={false} > + + -1 +
+ } + > + -1 + - -1 - + /> diff --git a/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap b/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap index ac3dce3bfaef6..3cf35609acd07 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap +++ b/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap @@ -366,15 +366,22 @@ exports[`ExplainCollectionInterval collection interval setting updates should sh paddingSize="l" transparentBackground={false} > + + xpack.monitoring.collection.interval +
+ } + > + xpack.monitoring.collection.interval + - xpack.monitoring.collection.interval - + /> @@ -387,15 +394,22 @@ exports[`ExplainCollectionInterval collection interval setting updates should sh paddingSize="l" transparentBackground={false} > + + -1 +
+ } + > + -1 + - -1 - + /> @@ -682,15 +696,22 @@ exports[`ExplainCollectionInterval should explain about xpack.monitoring.collect paddingSize="l" transparentBackground={false} > + + xpack.monitoring.collection.interval +
+ } + > + xpack.monitoring.collection.interval + - xpack.monitoring.collection.interval - + /> @@ -703,15 +724,22 @@ exports[`ExplainCollectionInterval should explain about xpack.monitoring.collect paddingSize="l" transparentBackground={false} > + + -1 +
+ } + > + -1 + - -1 - + /> diff --git a/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/exporters/__tests__/__snapshots__/exporters.test.js.snap b/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/exporters/__tests__/__snapshots__/exporters.test.js.snap index 89cd3e5852f82..fb06ff2d866bb 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/exporters/__tests__/__snapshots__/exporters.test.js.snap +++ b/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/exporters/__tests__/__snapshots__/exporters.test.js.snap @@ -26,32 +26,20 @@ Array [ >

We checked the - - + + esProd001 settings for - - + + xpack.monitoring.exporters , and found the reason: - - + + myMonitoringClusterExporter1 @@ -59,32 +47,20 @@ Array [

Using monitoring exporters to ship the monitoring data to a remote monitoring cluster is highly recommended as it keeps the integrity of the monitoring data safe no matter what the state of the production cluster. However, as this instance of Kibana could not find any monitoring data, there seems to be a problem with the - - + + xpack.monitoring.exporters configuration, or the - - + + xpack.monitoring.elasticsearch settings in - - + + kibana.yml @@ -92,22 +68,14 @@ Array [

Check that the intended exporters are enabled for sending statistics to the monitoring cluster, and that the monitoring cluster host matches the - - + + xpack.monitoring.elasticsearch setting in - - + + kibana.yml diff --git a/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/exporters/__tests__/exporters.test.js b/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/exporters/__tests__/exporters.test.js index bdeb469daee46..c9147037f0022 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/exporters/__tests__/exporters.test.js +++ b/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/exporters/__tests__/exporters.test.js @@ -8,6 +8,19 @@ import React from 'react'; import { renderWithIntl } from '../../../../../../../../../test_utils/enzyme_helpers'; import { ExplainExporters, ExplainExportersCloud } from '../exporters'; +// Mocking to prevent errors with React portal. +// Temporary until https://github.com/elastic/kibana/pull/55877 provides other alternatives. +jest.mock('@elastic/eui/lib/components/code/code', () => { + const React = require.requireActual('react'); + return { + EuiCode: ({ children }) => ( + + {children} + + ), + }; +}); + describe('ExplainExporters', () => { test('should explain about xpack.monitoring.exporters setting', () => { const reason = { diff --git a/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/plugin_enabled/__tests__/__snapshots__/plugin_enabled.test.js.snap b/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/plugin_enabled/__tests__/__snapshots__/plugin_enabled.test.js.snap index 8871d8caadd1c..63053c3f7c0cd 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/plugin_enabled/__tests__/__snapshots__/plugin_enabled.test.js.snap +++ b/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/plugin_enabled/__tests__/__snapshots__/plugin_enabled.test.js.snap @@ -26,32 +26,20 @@ Array [ >

We checked the cluster settings and found that - - + + xpack.monitoring.enabled is set to - - + + false set, which disables monitoring. Removing the - - + + xpack.monitoring.enabled: false diff --git a/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/plugin_enabled/__tests__/plugin_enabled.test.js b/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/plugin_enabled/__tests__/plugin_enabled.test.js index b962d136ba642..56536a8e4270b 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/plugin_enabled/__tests__/plugin_enabled.test.js +++ b/x-pack/legacy/plugins/monitoring/public/components/no_data/explanations/plugin_enabled/__tests__/plugin_enabled.test.js @@ -8,6 +8,19 @@ import React from 'react'; import { renderWithIntl } from '../../../../../../../../../test_utils/enzyme_helpers'; import { ExplainPluginEnabled } from '../plugin_enabled'; +// Mocking to prevent errors with React portal. +// Temporary until https://github.com/elastic/kibana/pull/55877 provides other alternatives. +jest.mock('@elastic/eui/lib/components/code/code', () => { + const React = require.requireActual('react'); + return { + EuiCode: ({ children }) => ( + + {children} + + ), + }; +}); + describe('ExplainPluginEnabled', () => { test('should explain about xpack.monitoring.enabled setting', () => { const reason = { diff --git a/x-pack/legacy/plugins/monitoring/public/components/no_data/reasons/__tests__/__snapshots__/reason_found.test.js.snap b/x-pack/legacy/plugins/monitoring/public/components/no_data/reasons/__tests__/__snapshots__/reason_found.test.js.snap index fadf7c5757bf8..898be82b139d1 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/no_data/reasons/__tests__/__snapshots__/reason_found.test.js.snap +++ b/x-pack/legacy/plugins/monitoring/public/components/no_data/reasons/__tests__/__snapshots__/reason_found.test.js.snap @@ -26,22 +26,14 @@ Array [ >

We checked the cluster settings and found that - - + + xpack.monitoring.collection.interval is set to - - + + -1 @@ -109,32 +101,20 @@ Array [ >

We checked the - - + + node001foo settings for - - + + xpack.monitoring.exporters , and found the reason: - - + + myMonitoringClusterExporter1 @@ -142,32 +122,20 @@ Array [

Using monitoring exporters to ship the monitoring data to a remote monitoring cluster is highly recommended as it keeps the integrity of the monitoring data safe no matter what the state of the production cluster. However, as this instance of Kibana could not find any monitoring data, there seems to be a problem with the - - + + xpack.monitoring.exporters configuration, or the - - + + xpack.monitoring.elasticsearch settings in - - + + kibana.yml @@ -175,22 +143,14 @@ Array [

Check that the intended exporters are enabled for sending statistics to the monitoring cluster, and that the monitoring cluster host matches the - - + + xpack.monitoring.elasticsearch setting in - - + + kibana.yml @@ -277,32 +237,20 @@ Array [ >

We checked the node001foo settings and found that - - + + xpack.monitoring.enabled is set to - - + + false set, which disables monitoring. Removing the - - + + xpack.monitoring.enabled: false diff --git a/x-pack/legacy/plugins/monitoring/public/components/no_data/reasons/__tests__/reason_found.test.js b/x-pack/legacy/plugins/monitoring/public/components/no_data/reasons/__tests__/reason_found.test.js index a51817db324b7..e9b2ff11538ab 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/no_data/reasons/__tests__/reason_found.test.js +++ b/x-pack/legacy/plugins/monitoring/public/components/no_data/reasons/__tests__/reason_found.test.js @@ -8,6 +8,19 @@ import React from 'react'; import { renderWithIntl } from '../../../../../../../../test_utils/enzyme_helpers'; import { ReasonFound } from '../'; +// Mocking to prevent errors with React portal. +// Temporary until https://github.com/elastic/kibana/pull/55877 provides other alternatives. +jest.mock('@elastic/eui/lib/components/code/code', () => { + const React = require.requireActual('react'); + return { + EuiCode: ({ children }) => ( + + {children} + + ), + }; +}); + const enabler = {}; describe('ReasonFound', () => { diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap b/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap index 65fc455417fe3..45751997eb0d5 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap +++ b/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap @@ -5,27 +5,28 @@ Array [

-
+
-

- Name -

+ + +
-
-
+
+
-

- Seed nodes for cluster discovery -

+ + +
-
-
+
+
-

- Make remote cluster optional -

+ + +
-
+
,
= ({ defaultMessage="A unique identifier for this policy." /> } - idAria="nameDescription" fullWidth > = ({ defaultMessage="Name" /> } - describedByIds={['nameDescription']} isInvalid={touched.name && Boolean(errors.name)} error={errors.name} fullWidth @@ -158,7 +156,6 @@ export const PolicyStepLogistics: React.FunctionComponent = ({ defaultMessage="The repository where you want to store the snapshots." /> } - idAria="policyRepositoryDescription" fullWidth > = ({ defaultMessage="Repository" /> } - describedByIds={['policyRepositoryDescription']} isInvalid={touched.repository && Boolean(errors.repository)} error={errors.repository} fullWidth @@ -307,7 +303,6 @@ export const PolicyStepLogistics: React.FunctionComponent = ({ defaultMessage="The name for the snapshots. A unique identifier is automatically added to each name." /> } - idAria="policySnapshotNameDescription" fullWidth > = ({ defaultMessage="Snapshot name" /> } - describedByIds={['policySnapshotNameDescription']} isInvalid={touched.snapshotName && Boolean(errors.snapshotName)} error={errors.snapshotName} helpText={ @@ -389,7 +383,6 @@ export const PolicyStepLogistics: React.FunctionComponent = ({ defaultMessage="The frequency at which to take the snapshots." /> } - idAria="policyScheduleDescription" fullWidth > {isAdvancedCronVisible ? ( @@ -401,7 +394,6 @@ export const PolicyStepLogistics: React.FunctionComponent = ({ defaultMessage="Schedule" /> } - describedByIds={['policyScheduleDescription']} isInvalid={touched.schedule && Boolean(errors.schedule)} error={errors.schedule} helpText={ diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_retention.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_retention.tsx index df7e2c8807d9f..ec01885e76ff1 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_retention.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_retention.tsx @@ -73,7 +73,6 @@ export const PolicyStepRetention: React.FunctionComponent = ({ defaultMessage="The time to wait before deleting snapshots." /> } - idAria="expirationDescription" fullWidth > = ({ defaultMessage="Delete after" /> } - describedByIds={['expirationDescription']} isInvalid={touched.expireAfterValue && Boolean(errors.expireAfterValue)} error={errors.expireAfterValue} fullWidth @@ -140,7 +138,6 @@ export const PolicyStepRetention: React.FunctionComponent = ({ defaultMessage="The minimum and maximum number of snapshots to store in your cluster." /> } - idAria="countDescription" fullWidth > @@ -152,7 +149,6 @@ export const PolicyStepRetention: React.FunctionComponent = ({ defaultMessage="Mininum count" /> } - describedByIds={['countDescription']} isInvalid={touched.minCount && Boolean(errors.minCount)} error={errors.minCount} fullWidth @@ -180,7 +176,6 @@ export const PolicyStepRetention: React.FunctionComponent = ({ defaultMessage="Maximum count" /> } - describedByIds={['countDescription']} isInvalid={touched.maxCount && Boolean(errors.maxCount)} error={errors.maxCount} fullWidth diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_settings.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_settings.tsx index 0e3b6e030d1c6..552dbff8e7441 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_settings.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_settings.tsx @@ -126,10 +126,9 @@ export const PolicyStepSettings: React.FunctionComponent = ({ defaultMessage="Indices to back up." /> } - idAria="indicesDescription" fullWidth > - + {isManagedPolicy ? ( = ({ defaultMessage="Ignores indices that are unavailable when taking the snapshot. Otherwise, the entire snapshot will fail." /> } - idAria="policyIgnoreUnavailableDescription" fullWidth > - + = ({ defaultMessage="Allows snapshots of indices with primary shards that are unavailable. Otherwise, the entire snapshot will fail." /> } - idAria="policyPartialDescription" fullWidth > - + = ({ defaultMessage="Stores the global state of the cluster as part of the snapshot." /> } - idAria="policyIncludeGlobalStateDescription" fullWidth > - + = ({ defaultMessage="A unique name for the repository." /> } - idAria="repositoryNameDescription" fullWidth > = ({ defaultMessage="Name" /> } - describedByIds={['repositoryNameDescription']} isInvalid={Boolean(hasValidationErrors && validation.errors.name)} error={validation.errors.name} fullWidth @@ -303,10 +301,9 @@ export const RepositoryFormStepOne: React.FunctionComponent = ({ /> } - idAria="sourceOnlyDescription" fullWidth > - + = ({ defaultMessage="The name of the Azure client." /> } - idAria="azureRepositoryClientDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['azureRepositoryClientDescription']} isInvalid={Boolean(hasErrors && settingErrors.client)} error={settingErrors.client} > @@ -123,7 +121,6 @@ export const AzureSettings: React.FunctionComponent = ({ defaultMessage="The name of the Azure container to use for snapshots." /> } - idAria="azureRepositoryContainerDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['azureRepositoryContainerDescription']} isInvalid={Boolean(hasErrors && settingErrors.container)} error={settingErrors.container} > @@ -169,7 +165,6 @@ export const AzureSettings: React.FunctionComponent = ({ defaultMessage="The container path to the repository data." /> } - idAria="azureRepositoryBasePathDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['azureRepositoryBasePathDescription']} isInvalid={Boolean(hasErrors && settingErrors.basePath)} error={settingErrors.basePath} > @@ -215,13 +209,11 @@ export const AzureSettings: React.FunctionComponent = ({ defaultMessage="Compresses the index mapping and setting files for snapshots. Data files are not compressed." /> } - idAria="azureRepositoryCompressDescription" fullWidth > @@ -261,7 +253,6 @@ export const AzureSettings: React.FunctionComponent = ({ defaultMessage="Breaks files into smaller units when taking snapshots." /> } - idAria="azureRepositoryChunkSizeDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['azureRepositoryChunkSizeDescription']} isInvalid={Boolean(hasErrors && settingErrors.chunkSize)} error={settingErrors.chunkSize} helpText={textService.getSizeNotationHelpText()} @@ -308,7 +298,6 @@ export const AzureSettings: React.FunctionComponent = ({ defaultMessage="The rate for creating snapshots for each node." /> } - idAria="azureRepositoryMaxSnapshotBytesDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['azureRepositoryMaxSnapshotBytesDescription']} isInvalid={Boolean(hasErrors && settingErrors.maxSnapshotBytesPerSec)} error={settingErrors.maxSnapshotBytesPerSec} helpText={textService.getSizeNotationHelpText()} @@ -355,7 +343,6 @@ export const AzureSettings: React.FunctionComponent = ({ defaultMessage="The snapshot restore rate for each node." /> } - idAria="azureRepositoryMaxRestoreBytesDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['azureRepositoryMaxRestoreBytesDescription']} isInvalid={Boolean(hasErrors && settingErrors.maxRestoreBytesPerSec)} error={settingErrors.maxRestoreBytesPerSec} helpText={textService.getSizeNotationHelpText()} @@ -402,7 +388,6 @@ export const AzureSettings: React.FunctionComponent = ({ defaultMessage="The primary or secondary location. If secondary, read-only is true." /> } - idAria="azureRepositoryLocationModeDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['azureRepositoryLocationModeDescription']} isInvalid={Boolean(hasErrors && settingErrors.locationMode)} error={settingErrors.locationMode} > @@ -450,13 +434,11 @@ export const AzureSettings: React.FunctionComponent = ({ defaultMessage="Only one cluster should have write access to this repository. All other clusters should be read-only." /> } - idAria="azureRepositoryReadonlyDescription" fullWidth > diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/fs_settings.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/fs_settings.tsx index 2e2238ac93e3c..711db1ee300cb 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/fs_settings.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/fs_settings.tsx @@ -73,7 +73,6 @@ export const FSSettings: React.FunctionComponent = ({ /> } - idAria="fsRepositoryLocationDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['fsRepositoryLocationDescription']} isInvalid={Boolean(hasErrors && settingErrors.location)} error={settingErrors.location} > @@ -119,13 +117,11 @@ export const FSSettings: React.FunctionComponent = ({ defaultMessage="Compresses the index mapping and setting files for snapshots. Data files are not compressed." /> } - idAria="fsRepositoryCompressDescription" fullWidth > @@ -165,7 +161,6 @@ export const FSSettings: React.FunctionComponent = ({ defaultMessage="Breaks files into smaller units when taking snapshots." /> } - idAria="fsRepositoryChunkSizeDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['fsRepositoryChunkSizeDescription']} isInvalid={Boolean(hasErrors && settingErrors.chunkSize)} error={settingErrors.chunkSize} helpText={textService.getSizeNotationHelpText()} @@ -212,7 +206,6 @@ export const FSSettings: React.FunctionComponent = ({ defaultMessage="The rate for creating snapshots for each node." /> } - idAria="fsRepositoryMaxSnapshotBytesDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['fsRepositoryMaxSnapshotBytesDescription']} isInvalid={Boolean(hasErrors && settingErrors.maxSnapshotBytesPerSec)} error={settingErrors.maxSnapshotBytesPerSec} helpText={textService.getSizeNotationHelpText()} @@ -259,7 +251,6 @@ export const FSSettings: React.FunctionComponent = ({ defaultMessage="The snapshot restore rate for each node." /> } - idAria="fsRepositoryMaxRestoreBytesDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['fsRepositoryMaxRestoreBytesDescription']} isInvalid={Boolean(hasErrors && settingErrors.maxRestoreBytesPerSec)} error={settingErrors.maxRestoreBytesPerSec} helpText={textService.getSizeNotationHelpText()} @@ -306,13 +296,11 @@ export const FSSettings: React.FunctionComponent = ({ defaultMessage="Only one cluster should have write access to this repository. All other clusters should be read-only." /> } - idAria="fsRepositoryReadonlyDescription" fullWidth > diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/gcs_settings.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/gcs_settings.tsx index d15e0043b8c81..5a34d3aac6f6b 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/gcs_settings.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/gcs_settings.tsx @@ -64,7 +64,6 @@ export const GCSSettings: React.FunctionComponent = ({ defaultMessage="The name of the Google Cloud Storage client." /> } - idAria="gcsRepositoryClientDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['gcsRepositoryClientDescription']} isInvalid={Boolean(hasErrors && settingErrors.client)} error={settingErrors.client} > @@ -110,7 +108,6 @@ export const GCSSettings: React.FunctionComponent = ({ defaultMessage="The name of the Google Cloud Storage bucket to use for snapshots." /> } - idAria="gcsRepositoryBucketDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['gcsRepositoryBucketDescription']} isInvalid={Boolean(hasErrors && settingErrors.bucket)} error={settingErrors.bucket} > @@ -156,7 +152,6 @@ export const GCSSettings: React.FunctionComponent = ({ defaultMessage="The bucket path to the repository data." /> } - idAria="gcsRepositoryBasePathDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['gcsRepositoryBasePathDescription']} isInvalid={Boolean(hasErrors && settingErrors.basePath)} error={settingErrors.basePath} > @@ -202,13 +196,11 @@ export const GCSSettings: React.FunctionComponent = ({ defaultMessage="Compresses the index mapping and setting files for snapshots. Data files are not compressed." /> } - idAria="gcsRepositoryCompressDescription" fullWidth > @@ -248,7 +240,6 @@ export const GCSSettings: React.FunctionComponent = ({ defaultMessage="Breaks files into smaller units when taking snapshots." /> } - idAria="gcsRepositoryChunkSizeDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['gcsRepositoryChunkSizeDescription']} isInvalid={Boolean(hasErrors && settingErrors.chunkSize)} error={settingErrors.chunkSize} helpText={textService.getSizeNotationHelpText()} @@ -295,7 +285,6 @@ export const GCSSettings: React.FunctionComponent = ({ defaultMessage="The rate for creating snapshots for each node." /> } - idAria="gcsRepositoryMaxSnapshotBytesDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['gcsRepositoryMaxSnapshotBytesDescription']} isInvalid={Boolean(hasErrors && settingErrors.maxSnapshotBytesPerSec)} error={settingErrors.maxSnapshotBytesPerSec} helpText={textService.getSizeNotationHelpText()} @@ -342,7 +330,6 @@ export const GCSSettings: React.FunctionComponent = ({ defaultMessage="The snapshot restore rate for each node." /> } - idAria="gcsRepositoryMaxRestoreBytesDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['gcsRepositoryMaxRestoreBytesDescription']} isInvalid={Boolean(hasErrors && settingErrors.maxRestoreBytesPerSec)} error={settingErrors.maxRestoreBytesPerSec} helpText={textService.getSizeNotationHelpText()} @@ -389,13 +375,11 @@ export const GCSSettings: React.FunctionComponent = ({ defaultMessage="Only one cluster should have write access to this repository. All other clusters should be read-only." /> } - idAria="gcsRepositoryReadonlyDescription" fullWidth > diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/hdfs_settings.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/hdfs_settings.tsx index ae42b810bf059..4ef662d645bea 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/hdfs_settings.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/hdfs_settings.tsx @@ -79,7 +79,6 @@ export const HDFSSettings: React.FunctionComponent = ({ defaultMessage="The URI address for HDFS." /> } - idAria="hdfsRepositoryUriDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['hdfsRepositoryUriDescription']} isInvalid={Boolean(hasErrors && settingErrors.uri)} error={settingErrors.uri} > @@ -108,7 +106,7 @@ export const HDFSSettings: React.FunctionComponent = ({ uri: e.target.value ? `hdfs://${e.target.value}` : '', }); }} - aria-describedby="hdfsRepositoryUriDescription hdfsRepositoryUriProtocolDescription" + aria-describedby="hdfsRepositoryUriProtocolDescription" data-test-subj="uriInput" /> @@ -132,7 +130,6 @@ export const HDFSSettings: React.FunctionComponent = ({ defaultMessage="The file path where data is stored." /> } - idAria="hdfsRepositoryPathDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['hdfsRepositoryPathDescription']} isInvalid={Boolean(hasErrors && settingErrors.path)} error={settingErrors.path} > @@ -178,13 +174,11 @@ export const HDFSSettings: React.FunctionComponent = ({ defaultMessage="Loads the default Hadoop configuration." /> } - idAria="hdfsRepositoryLoadDefaultsDescription" fullWidth > @@ -224,13 +218,11 @@ export const HDFSSettings: React.FunctionComponent = ({ defaultMessage="Compresses the index mapping and setting files for snapshots. Data files are not compressed." /> } - idAria="hdfsRepositoryCompressDescription" fullWidth > @@ -270,7 +262,6 @@ export const HDFSSettings: React.FunctionComponent = ({ defaultMessage="Breaks files into smaller units when taking snapshots." /> } - idAria="hdfsRepositoryChunkSizeDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['hdfsRepositoryChunkSizeDescription']} isInvalid={Boolean(hasErrors && settingErrors.chunkSize)} error={settingErrors.chunkSize} helpText={textService.getSizeNotationHelpText()} @@ -317,7 +307,6 @@ export const HDFSSettings: React.FunctionComponent = ({ defaultMessage="The Kerberos principal to use when connecting to a secured HDFS cluster." /> } - idAria="hdfsRepositorySecurityPrincipalDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['hdfsRepositorySecurityPrincipalDescription']} isInvalid={Boolean(hasErrors && settingErrors.securityPrincipal)} error={settingErrors.securityPrincipal} > @@ -365,7 +353,6 @@ export const HDFSSettings: React.FunctionComponent = ({ /> } - idAria="hdfsRepositoryConfigurationDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['hdfsRepositoryConfigurationDescription']} isInvalid={isConfInvalid} error={ = ({ defaultMessage="The rate for creating snapshots for each node." /> } - idAria="hdfsRepositoryMaxSnapshotBytesDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['hdfsRepositoryMaxSnapshotBytesDescription']} isInvalid={Boolean(hasErrors && settingErrors.maxSnapshotBytesPerSec)} error={settingErrors.maxSnapshotBytesPerSec} helpText={textService.getSizeNotationHelpText()} @@ -510,7 +494,6 @@ export const HDFSSettings: React.FunctionComponent = ({ defaultMessage="The snapshot restore rate for each node." /> } - idAria="hdfsRepositoryMaxRestoreBytesDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['hdfsRepositoryMaxRestoreBytesDescription']} isInvalid={Boolean(hasErrors && settingErrors.maxRestoreBytesPerSec)} error={settingErrors.maxRestoreBytesPerSec} helpText={textService.getSizeNotationHelpText()} @@ -557,13 +539,11 @@ export const HDFSSettings: React.FunctionComponent = ({ defaultMessage="Only one cluster should have write access to this repository. All other clusters should be read-only." /> } - idAria="hdfsRepositoryReadonlyDescription" fullWidth > diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/readonly_settings.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/readonly_settings.tsx index 5241a55455395..a0cc076465990 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/readonly_settings.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/readonly_settings.tsx @@ -116,7 +116,6 @@ export const ReadonlySettings: React.FunctionComponent = ({ /> } - idAria="readonlyRepositoryUrlDescription" fullWidth >
@@ -130,7 +129,6 @@ export const ReadonlySettings: React.FunctionComponent = ({ /> } fullWidth - describedByIds={['readonlyRepositoryUrlDescription']} > = ({ /> } fullWidth - describedByIds={['readonlyRepositoryUrlDescription readonlyRepositoryUrlHelp']} + describedByIds={['readonlyRepositoryUrlHelp']} isInvalid={Boolean(hasErrors && settingErrors.url)} error={settingErrors.url} > diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/s3_settings.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/s3_settings.tsx index a897368ae7ca3..1a9902b42a931 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/s3_settings.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/type_settings/s3_settings.tsx @@ -93,7 +93,6 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="The name of the AWS S3 client." /> } - idAria="s3RepositoryClientDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['s3RepositoryClientDescription']} isInvalid={Boolean(hasErrors && settingErrors.client)} error={settingErrors.client} > @@ -139,7 +137,6 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="The name of the AWS S3 bucket to use for snapshots." /> } - idAria="s3RepositoryBucketDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['s3RepositoryBucketDescription']} isInvalid={Boolean(hasErrors && settingErrors.bucket)} error={settingErrors.bucket} > @@ -185,7 +181,6 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="The bucket path to the repository data." /> } - idAria="s3RepositoryBasePathDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['s3RepositoryBasePathDescription']} isInvalid={Boolean(hasErrors && settingErrors.basePath)} error={settingErrors.basePath} > @@ -231,13 +225,11 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="Compresses the index mapping and setting files for snapshots. Data files are not compressed." /> } - idAria="s3RepositoryCompressDescription" fullWidth > @@ -277,7 +269,6 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="Breaks files into smaller units when taking snapshots." /> } - idAria="s3RepositoryChunkSizeDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['s3RepositoryChunkSizeDescription']} isInvalid={Boolean(hasErrors && settingErrors.chunkSize)} error={settingErrors.chunkSize} helpText={textService.getSizeNotationHelpText()} @@ -324,13 +314,11 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="Encrypts files on the server using AES256 algorithm." /> } - idAria="s3RepositoryServerSideEncryptionDescription" fullWidth > @@ -371,7 +359,6 @@ export const S3Settings: React.FunctionComponent = ({ to split the chunk into several parts and upload each in its own request." /> } - idAria="s3RepositoryBufferSizeDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['s3RepositoryBufferSizeDescription']} isInvalid={Boolean(hasErrors && settingErrors.bufferSize)} error={settingErrors.bufferSize} helpText={textService.getSizeNotationHelpText()} @@ -418,7 +404,6 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="The canned ACL to add to new S3 buckets and objects." /> } - idAria="s3RepositoryCannedAclDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['s3RepositoryCannedAclDescription']} isInvalid={Boolean(hasErrors && settingErrors.cannedAcl)} error={settingErrors.cannedAcl} > @@ -465,7 +449,6 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="The storage class for new objects in the S3 repository." /> } - idAria="s3RepositoryStorageClassDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['s3RepositoryStorageClassDescription']} isInvalid={Boolean(hasErrors && settingErrors.storageClass)} error={settingErrors.storageClass} > @@ -512,7 +494,6 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="The rate for creating snapshots for each node." /> } - idAria="s3RepositoryMaxSnapshotBytesDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['s3RepositoryMaxSnapshotBytesDescription']} isInvalid={Boolean(hasErrors && settingErrors.maxSnapshotBytesPerSec)} error={settingErrors.maxSnapshotBytesPerSec} helpText={textService.getSizeNotationHelpText()} @@ -559,7 +539,6 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="The snapshot restore rate for each node." /> } - idAria="s3RepositoryMaxRestoreBytesDescription" fullWidth > = ({ /> } fullWidth - describedByIds={['s3RepositoryMaxRestoreBytesDescription']} isInvalid={Boolean(hasErrors && settingErrors.maxRestoreBytesPerSec)} error={settingErrors.maxRestoreBytesPerSec} helpText={textService.getSizeNotationHelpText()} @@ -606,13 +584,11 @@ export const S3Settings: React.FunctionComponent = ({ defaultMessage="Only one cluster should have write access to this repository. All other clusters should be read-only." /> } - idAria="s3RepositoryReadonlyDescription" fullWidth > diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_logistics.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_logistics.tsx index f5a3180adbd6e..bd8a0650c087f 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_logistics.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_logistics.tsx @@ -141,14 +141,9 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = if they are closed and have the same number of shards as the snapshot index." /> } - idAria="stepLogisticsIndicesDescription" fullWidth > - + = defaultMessage="Renames indices on restore." /> } - idAria="stepLogisticsRenameIndicesDescription" fullWidth > - + = defaultMessage="Allows restore of indices that don’t have snapshots of all shards." /> } - idAria="stepLogisticsPartialDescription" fullWidth > - + = templates with the same name. Also restores persistent settings." /> } - idAria="stepLogisticsIncludeGlobalStateDescription" fullWidth > = ( }} /> } - idAria="stepSettingsIndexSettingsDescription" fullWidth > - + = ( /> } fullWidth - describedByIds={['stepSettingsIndexSettingsDescription']} isInvalid={Boolean(errors.indexSettings)} error={errors.indexSettings} helpText={ @@ -235,14 +229,9 @@ export const RestoreSnapshotStepSettings: React.FunctionComponent = ( }} /> } - idAria="stepSettingsIgnoreIndexSettingsDescription" fullWidth > - + diff --git a/x-pack/package.json b/x-pack/package.json index 43df763c22bdc..e3bc8aa36373d 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -176,7 +176,7 @@ "@elastic/apm-rum-react": "^0.3.2", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "7.6.0", - "@elastic/eui": "18.3.0", + "@elastic/eui": "19.0.0", "@elastic/filesaver": "1.1.2", "@elastic/maki": "6.1.0", "@elastic/node-crypto": "^1.0.0", diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap index 323629de7578d..2a00c7ca5c347 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap @@ -26,8 +26,6 @@ exports[`it renders without crashing 1`] = `

} - fullWidth={false} - gutterSize="l" title={

} - titleSize="xs" >

} - fullWidth={false} - gutterSize="l" title={

} - titleSize="xs" > renders without crashing 1`] = ` />

} - fullWidth={false} - gutterSize="l" title={

renders without crashing 1`] = ` />

} - titleSize="xs" > {i18n.translate( @@ -323,7 +322,6 @@ export const JsonWatchEditSimulate = ({ } > {i18n.translate( @@ -361,7 +358,6 @@ export const JsonWatchEditSimulate = ({ > ; export const EuiCodeEditor: React.FC; export const Query: any; } diff --git a/yarn.lock b/yarn.lock index 0a55e3d7c7850..cac39dfd4c352 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1955,15 +1955,17 @@ tabbable "^1.1.0" uuid "^3.1.0" -"@elastic/eui@18.3.0": - version "18.3.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-18.3.0.tgz#e21c6246624f694e2ae1c7c1f1a11b612faf260a" - integrity sha512-Rkj1rTtDa6iZMUF7pxYRojku1sLXzTU0FK1D9i0XE3H//exy3VyTV6qUlbdkiKXjO7emrgQqfzKDeXT+ZYztgg== +"@elastic/eui@19.0.0": + version "19.0.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-19.0.0.tgz#cf7d644945c95997d442585cf614e853f173746e" + integrity sha512-8/USz56MYhu6bV4oecJct7tsdi0ktErOIFLobNmQIKdxDOni/KpttX6IHqxM7OuIWi1AEMXoIozw68+oyL/uKQ== dependencies: "@types/chroma-js" "^1.4.3" + "@types/enzyme" "^3.1.13" "@types/lodash" "^4.14.116" "@types/numeral" "^0.0.25" "@types/react-beautiful-dnd" "^10.1.0" + "@types/react-virtualized" "^9.18.7" chroma-js "^2.0.4" classnames "^2.2.5" highlight.js "^9.12.0" @@ -4384,10 +4386,10 @@ resolved "https://registry.yarnpkg.com/@types/elasticsearch/-/elasticsearch-5.0.33.tgz#b0fd37dc674f498223b6d68c313bdfd71f4d812b" integrity sha512-n/g9pqJEpE4fyUE8VvHNGtl7E2Wv8TCroNwfgAeJKRV4ghDENahtrAo1KMsFNIejBD2gDAlEUa4CM4oEEd8p9Q== -"@types/enzyme@^3.9.0": - version "3.9.3" - resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.9.3.tgz#d1029c0edd353d7b00f3924803eb88216460beed" - integrity sha512-jDKoZiiMA3lGO3skSO7dfqEHNvmiTLLV+PHD9EBQVlJANJvpY6qq1zzjRI24ZOtG7F+CS7BVWDXKewRmN8PjHQ== +"@types/enzyme@^3.1.13", "@types/enzyme@^3.9.0": + version "3.10.5" + resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.5.tgz#fe7eeba3550369eed20e7fb565bfb74eec44f1f0" + integrity sha512-R+phe509UuUYy9Tk0YlSbipRpfVtIzb/9BHn5pTEtjJTF5LXvUjrIQcZvNyANNEyFrd2YGs196PniNT1fgvOQA== dependencies: "@types/cheerio" "*" "@types/react" "*" From 6bd09d616ffb93124d9fd36db77da11c883eb9e1 Mon Sep 17 00:00:00 2001 From: Josh Dover Date: Fri, 14 Feb 2020 12:06:59 -0700 Subject: [PATCH 06/32] Fix maybe behavior with object type (#55932) --- .../src/types/duration_type.test.ts | 6 +-- .../src/types/maybe_type.test.ts | 38 +++++++++++++++++++ .../kbn-config-schema/src/types/maybe_type.ts | 2 +- .../src/types/object_type.test.ts | 22 ++++++++++- .../src/types/object_type.ts | 6 +-- .../event_log/server/event_logger.test.ts | 2 - x-pack/plugins/security/server/config.ts | 2 +- 7 files changed, 67 insertions(+), 11 deletions(-) diff --git a/packages/kbn-config-schema/src/types/duration_type.test.ts b/packages/kbn-config-schema/src/types/duration_type.test.ts index 09e92ce727f2a..57e917dc99b2b 100644 --- a/packages/kbn-config-schema/src/types/duration_type.test.ts +++ b/packages/kbn-config-schema/src/types/duration_type.test.ts @@ -101,7 +101,7 @@ describe('#defaultValue', () => { source: duration({ defaultValue: 600 }), target: duration({ defaultValue: siblingRef('source') }), fromContext: duration({ defaultValue: contextRef('val') }), - }).validate(undefined, { val: momentDuration(700, 'ms') }) + }).validate({}, { val: momentDuration(700, 'ms') }) ).toMatchInlineSnapshot(` Object { "fromContext": "PT0.7S", @@ -115,7 +115,7 @@ Object { source: duration({ defaultValue: '1h' }), target: duration({ defaultValue: siblingRef('source') }), fromContext: duration({ defaultValue: contextRef('val') }), - }).validate(undefined, { val: momentDuration(2, 'hour') }) + }).validate({}, { val: momentDuration(2, 'hour') }) ).toMatchInlineSnapshot(` Object { "fromContext": "PT2H", @@ -129,7 +129,7 @@ Object { source: duration({ defaultValue: momentDuration(1, 'hour') }), target: duration({ defaultValue: siblingRef('source') }), fromContext: duration({ defaultValue: contextRef('val') }), - }).validate(undefined, { val: momentDuration(2, 'hour') }) + }).validate({}, { val: momentDuration(2, 'hour') }) ).toMatchInlineSnapshot(` Object { "fromContext": "PT2H", diff --git a/packages/kbn-config-schema/src/types/maybe_type.test.ts b/packages/kbn-config-schema/src/types/maybe_type.test.ts index ecc1d218e186d..c35fa18593520 100644 --- a/packages/kbn-config-schema/src/types/maybe_type.test.ts +++ b/packages/kbn-config-schema/src/types/maybe_type.test.ts @@ -60,3 +60,41 @@ test('includes namespace in failure', () => { const type = schema.maybe(schema.string()); expect(() => type.validate(null, {}, 'foo-namespace')).toThrowErrorMatchingSnapshot(); }); + +describe('maybe + object', () => { + test('returns undefined if undefined object', () => { + const type = schema.maybe(schema.object({})); + expect(type.validate(undefined)).toEqual(undefined); + }); + + test('returns undefined if undefined object with no defaults', () => { + const type = schema.maybe( + schema.object({ + type: schema.string(), + id: schema.string(), + }) + ); + + expect(type.validate(undefined)).toEqual(undefined); + }); + + test('returns empty object if maybe keys', () => { + const type = schema.object({ + name: schema.maybe(schema.string()), + }); + expect(type.validate({})).toEqual({}); + }); + + test('returns empty object if maybe nested object', () => { + const type = schema.object({ + name: schema.maybe( + schema.object({ + type: schema.string(), + id: schema.string(), + }) + ), + }); + + expect(type.validate({})).toEqual({}); + }); +}); diff --git a/packages/kbn-config-schema/src/types/maybe_type.ts b/packages/kbn-config-schema/src/types/maybe_type.ts index 06a9369110203..415f6315c5723 100644 --- a/packages/kbn-config-schema/src/types/maybe_type.ts +++ b/packages/kbn-config-schema/src/types/maybe_type.ts @@ -25,7 +25,7 @@ export class MaybeType extends Type { type .getSchema() .optional() - .default() + .default(() => undefined, 'undefined') ); } } diff --git a/packages/kbn-config-schema/src/types/object_type.test.ts b/packages/kbn-config-schema/src/types/object_type.test.ts index 5786984cf7ebd..64739d7a4c4da 100644 --- a/packages/kbn-config-schema/src/types/object_type.test.ts +++ b/packages/kbn-config-schema/src/types/object_type.test.ts @@ -30,6 +30,11 @@ test('returns value by default', () => { expect(type.validate(value)).toEqual({ name: 'test' }); }); +test('returns empty object if undefined', () => { + const type = schema.object({}); + expect(type.validate(undefined)).toEqual({}); +}); + test('properly parse the value if input is a string', () => { const type = schema.object({ name: schema.string(), @@ -112,14 +117,26 @@ test('undefined object within object', () => { }), }); + expect(type.validate(undefined)).toEqual({ + foo: { + bar: 'hello world', + }, + }); + expect(type.validate({})).toEqual({ foo: { bar: 'hello world', }, }); + + expect(type.validate({ foo: {} })).toEqual({ + foo: { + bar: 'hello world', + }, + }); }); -test('object within object with required', () => { +test('object within object with key without defaultValue', () => { const type = schema.object({ foo: schema.object({ bar: schema.string(), @@ -127,6 +144,9 @@ test('object within object with required', () => { }); const value = { foo: {} }; + expect(() => type.validate(undefined)).toThrowErrorMatchingInlineSnapshot( + `"[foo.bar]: expected value of type [string] but got [undefined]"` + ); expect(() => type.validate(value)).toThrowErrorMatchingInlineSnapshot( `"[foo.bar]: expected value of type [string] but got [undefined]"` ); diff --git a/packages/kbn-config-schema/src/types/object_type.ts b/packages/kbn-config-schema/src/types/object_type.ts index d2e6c708c263c..4f3d68a6bac97 100644 --- a/packages/kbn-config-schema/src/types/object_type.ts +++ b/packages/kbn-config-schema/src/types/object_type.ts @@ -33,23 +33,23 @@ export type ObjectResultType

= Readonly<{ [K in keyof P]: TypeO export type ObjectTypeOptions

= TypeOptions< { [K in keyof P]: TypeOf } > & { + /** Should uknown keys not be defined in the schema be allowed. Defaults to `false` */ allowUnknowns?: boolean; }; export class ObjectType

extends Type> { private props: Record; - constructor(props: P, options: ObjectTypeOptions

= {}) { + constructor(props: P, { allowUnknowns = false, ...typeOptions }: ObjectTypeOptions

= {}) { const schemaKeys = {} as Record; for (const [key, value] of Object.entries(props)) { schemaKeys[key] = value.getSchema(); } - const { allowUnknowns, ...typeOptions } = options; const schema = internals .object() .keys(schemaKeys) - .optional() .default() + .optional() .unknown(Boolean(allowUnknowns)); super(schema, typeOptions); diff --git a/x-pack/plugins/event_log/server/event_logger.test.ts b/x-pack/plugins/event_log/server/event_logger.test.ts index c2de8d4dfd12b..97e52ad04dd08 100644 --- a/x-pack/plugins/event_log/server/event_logger.test.ts +++ b/x-pack/plugins/event_log/server/event_logger.test.ts @@ -57,8 +57,6 @@ describe('EventLogger', () => { kibana: { server_uuid: '424-24-2424', }, - error: {}, - user: {}, }); const $timeStamp = event!['@timestamp']!; diff --git a/x-pack/plugins/security/server/config.ts b/x-pack/plugins/security/server/config.ts index 4f1c25702ae97..db8c48f314d7c 100644 --- a/x-pack/plugins/security/server/config.ts +++ b/x-pack/plugins/security/server/config.ts @@ -41,7 +41,7 @@ export const ConfigSchema = schema.object( secureCookies: schema.boolean({ defaultValue: false }), authc: schema.object({ providers: schema.arrayOf(schema.string(), { defaultValue: ['basic'], minSize: 1 }), - oidc: providerOptionsSchema('oidc', schema.maybe(schema.object({ realm: schema.string() }))), + oidc: providerOptionsSchema('oidc', schema.object({ realm: schema.string() })), saml: providerOptionsSchema( 'saml', schema.object({ From 73cb0aa840622aa6e48afc03f5bf0fede6f54786 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Fri, 14 Feb 2020 19:08:02 +0000 Subject: [PATCH 07/32] [ML] New Platform server shim: update filters routes to use new platform router (#57597) * [ML] Update filters routes to use new platform router * [ML] Edits to filters route following review * [ML] Edits following review and fix job service api docs Co-authored-by: Elastic Machine --- .../{detector_rule.js => detector_rule.ts} | 38 +-- .../plugins/ml/common/types/detector_rules.ts | 26 ++ .../{filter_manager.js => filter_manager.ts} | 115 ++++++--- .../plugins/ml/server/models/filter/index.ts | 7 + .../ml/server/new_platform/filters_schema.ts | 19 ++ .../plugins/ml/server/new_platform/plugin.ts | 1 - .../plugins/ml/server/routes/apidoc.json | 11 +- .../plugins/ml/server/routes/filters.js | 126 ---------- .../plugins/ml/server/routes/filters.ts | 227 ++++++++++++++++++ .../plugins/ml/server/routes/job_service.ts | 40 +-- 10 files changed, 410 insertions(+), 200 deletions(-) rename x-pack/legacy/plugins/ml/common/constants/{detector_rule.js => detector_rule.ts} (53%) create mode 100644 x-pack/legacy/plugins/ml/common/types/detector_rules.ts rename x-pack/legacy/plugins/ml/server/models/filter/{filter_manager.js => filter_manager.ts} (57%) create mode 100644 x-pack/legacy/plugins/ml/server/models/filter/index.ts create mode 100644 x-pack/legacy/plugins/ml/server/new_platform/filters_schema.ts delete mode 100644 x-pack/legacy/plugins/ml/server/routes/filters.js create mode 100644 x-pack/legacy/plugins/ml/server/routes/filters.ts diff --git a/x-pack/legacy/plugins/ml/common/constants/detector_rule.js b/x-pack/legacy/plugins/ml/common/constants/detector_rule.ts similarity index 53% rename from x-pack/legacy/plugins/ml/common/constants/detector_rule.js rename to x-pack/legacy/plugins/ml/common/constants/detector_rule.ts index f07b82f4d2d3e..81120d01318ab 100644 --- a/x-pack/legacy/plugins/ml/common/constants/detector_rule.js +++ b/x-pack/legacy/plugins/ml/common/constants/detector_rule.ts @@ -8,28 +8,28 @@ * Contains values for ML job detector rules. */ -export const ACTION = { - SKIP_MODEL_UPDATE: 'skip_model_update', - SKIP_RESULT: 'skip_result', -}; +export enum ACTION { + SKIP_MODEL_UPDATE = 'skip_model_update', + SKIP_RESULT = 'skip_result', +} -export const FILTER_TYPE = { - EXCLUDE: 'exclude', - INCLUDE: 'include', -}; +export enum FILTER_TYPE { + EXCLUDE = 'exclude', + INCLUDE = 'include', +} -export const APPLIES_TO = { - ACTUAL: 'actual', - DIFF_FROM_TYPICAL: 'diff_from_typical', - TYPICAL: 'typical', -}; +export enum APPLIES_TO { + ACTUAL = 'actual', + DIFF_FROM_TYPICAL = 'diff_from_typical', + TYPICAL = 'typical', +} -export const OPERATOR = { - LESS_THAN: 'lt', - LESS_THAN_OR_EQUAL: 'lte', - GREATER_THAN: 'gt', - GREATER_THAN_OR_EQUAL: 'gte', -}; +export enum OPERATOR { + LESS_THAN = 'lt', + LESS_THAN_OR_EQUAL = 'lte', + GREATER_THAN = 'gt', + GREATER_THAN_OR_EQUAL = 'gte', +} // List of detector functions which don't support rules with numeric conditions. export const CONDITIONS_NOT_SUPPORTED_FUNCTIONS = ['freq_rare', 'lat_long', 'metric', 'rare']; diff --git a/x-pack/legacy/plugins/ml/common/types/detector_rules.ts b/x-pack/legacy/plugins/ml/common/types/detector_rules.ts new file mode 100644 index 0000000000000..c94e5d1327363 --- /dev/null +++ b/x-pack/legacy/plugins/ml/common/types/detector_rules.ts @@ -0,0 +1,26 @@ +/* + * 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 { ACTION, FILTER_TYPE, APPLIES_TO, OPERATOR } from '../constants/detector_rule'; + +export interface DetectorRuleScope { + [id: string]: { + filter_id: string; + filter_type: FILTER_TYPE; + }; +} + +export interface DetectorRuleCondition { + applies_to: APPLIES_TO; + operator: OPERATOR; + value: number; +} + +export interface DetectorRule { + actions: ACTION[]; + scope?: DetectorRuleScope; + conditions?: DetectorRuleCondition[]; +} diff --git a/x-pack/legacy/plugins/ml/server/models/filter/filter_manager.js b/x-pack/legacy/plugins/ml/server/models/filter/filter_manager.ts similarity index 57% rename from x-pack/legacy/plugins/ml/server/models/filter/filter_manager.js rename to x-pack/legacy/plugins/ml/server/models/filter/filter_manager.ts index d644494c20606..f40663a5eb6b2 100644 --- a/x-pack/legacy/plugins/ml/server/models/filter/filter_manager.js +++ b/x-pack/legacy/plugins/ml/server/models/filter/filter_manager.ts @@ -5,22 +5,75 @@ */ import Boom from 'boom'; +import { IScopedClusterClient } from 'src/core/server'; + +import { DetectorRule, DetectorRuleScope } from '../../../common/types/detector_rules'; + +export interface Filter { + filter_id: string; + description?: string; + items: string[]; +} + +export interface FormFilter { + filterId: string; + description?: string; + addItems?: string[]; + removeItems?: string[]; +} + +export interface FilterRequest { + filter_id: string; + description?: string; + add_items?: string[]; + remove_items?: string[]; +} + +interface FilterUsage { + jobs: string[]; + detectors: string[]; +} + +interface FilterStats { + filter_id: string; + description?: string; + item_count: number; + used_by: FilterUsage; +} + +interface FiltersInUse { + [id: string]: FilterUsage; +} + +interface PartialDetector { + detector_description: string; + custom_rules: DetectorRule[]; +} + +interface PartialJob { + job_id: string; + analysis_config: { + detectors: PartialDetector[]; + }; +} export class FilterManager { - constructor(callWithRequest) { - this.callWithRequest = callWithRequest; + private _client: IScopedClusterClient['callAsCurrentUser']; + + constructor(client: IScopedClusterClient['callAsCurrentUser']) { + this._client = client; } - async getFilter(filterId) { + async getFilter(filterId: string) { try { const [JOBS, FILTERS] = [0, 1]; const results = await Promise.all([ - this.callWithRequest('ml.jobs'), - this.callWithRequest('ml.filters', { filterId }), + this._client('ml.jobs'), + this._client('ml.filters', { filterId }), ]); if (results[FILTERS] && results[FILTERS].filters.length) { - let filtersInUse = {}; + let filtersInUse: FiltersInUse = {}; if (results[JOBS] && results[JOBS].jobs) { filtersInUse = this.buildFiltersInUse(results[JOBS].jobs); } @@ -38,7 +91,7 @@ export class FilterManager { async getAllFilters() { try { - const filtersResp = await this.callWithRequest('ml.filters'); + const filtersResp = await this._client('ml.filters'); return filtersResp.filters; } catch (error) { throw Boom.badRequest(error); @@ -48,13 +101,10 @@ export class FilterManager { async getAllFilterStats() { try { const [JOBS, FILTERS] = [0, 1]; - const results = await Promise.all([ - this.callWithRequest('ml.jobs'), - this.callWithRequest('ml.filters'), - ]); + const results = await Promise.all([this._client('ml.jobs'), this._client('ml.filters')]); // Build a map of filter_ids against jobs and detectors using that filter. - let filtersInUse = {}; + let filtersInUse: FiltersInUse = {}; if (results[JOBS] && results[JOBS].jobs) { filtersInUse = this.buildFiltersInUse(results[JOBS].jobs); } @@ -64,10 +114,10 @@ export class FilterManager { // description // item_count // jobs using the filter - const filterStats = []; + const filterStats: FilterStats[] = []; if (results[FILTERS] && results[FILTERS].filters) { - results[FILTERS].filters.forEach(filter => { - const stats = { + results[FILTERS].filters.forEach((filter: Filter) => { + const stats: FilterStats = { filter_id: filter.filter_id, description: filter.description, item_count: filter.items.length, @@ -83,32 +133,32 @@ export class FilterManager { } } - async newFilter(filter) { + async newFilter(filter: FormFilter) { const filterId = filter.filterId; delete filter.filterId; try { // Returns the newly created filter. - return await this.callWithRequest('ml.addFilter', { filterId, body: filter }); + return await this._client('ml.addFilter', { filterId, body: filter }); } catch (error) { throw Boom.badRequest(error); } } - async updateFilter(filterId, description, addItems, removeItems) { + async updateFilter(filterId: string, filter: FormFilter) { try { - const body = {}; - if (description !== undefined) { - body.description = description; + const body: FilterRequest = { filter_id: filterId }; + if (filter.description !== undefined) { + body.description = filter.description; } - if (addItems !== undefined) { - body.add_items = addItems; + if (filter.addItems !== undefined) { + body.add_items = filter.addItems; } - if (removeItems !== undefined) { - body.remove_items = removeItems; + if (filter.removeItems !== undefined) { + body.remove_items = filter.removeItems; } // Returns the newly updated filter. - return await this.callWithRequest('ml.updateFilter', { + return await this._client('ml.updateFilter', { filterId, body, }); @@ -117,13 +167,13 @@ export class FilterManager { } } - async deleteFilter(filterId) { - return this.callWithRequest('ml.deleteFilter', { filterId }); + async deleteFilter(filterId: string) { + return this._client('ml.deleteFilter', { filterId }); } - buildFiltersInUse(jobsList) { + buildFiltersInUse(jobsList: PartialJob[]) { // Build a map of filter_ids against jobs and detectors using that filter. - const filtersInUse = {}; + const filtersInUse: FiltersInUse = {}; jobsList.forEach(job => { const detectors = job.analysis_config.detectors; detectors.forEach(detector => { @@ -131,9 +181,10 @@ export class FilterManager { const rules = detector.custom_rules; rules.forEach(rule => { if (rule.scope) { - const scopeFields = Object.keys(rule.scope); + const ruleScope: DetectorRuleScope = rule.scope; + const scopeFields = Object.keys(ruleScope); scopeFields.forEach(scopeField => { - const filter = rule.scope[scopeField]; + const filter = ruleScope[scopeField]; const filterId = filter.filter_id; if (filtersInUse[filterId] === undefined) { filtersInUse[filterId] = { jobs: [], detectors: [] }; diff --git a/x-pack/legacy/plugins/ml/server/models/filter/index.ts b/x-pack/legacy/plugins/ml/server/models/filter/index.ts new file mode 100644 index 0000000000000..ed4802f6d5ee6 --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/models/filter/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 { FilterManager, Filter, FormFilter } from './filter_manager'; diff --git a/x-pack/legacy/plugins/ml/server/new_platform/filters_schema.ts b/x-pack/legacy/plugins/ml/server/new_platform/filters_schema.ts new file mode 100644 index 0000000000000..dffee56565c73 --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/new_platform/filters_schema.ts @@ -0,0 +1,19 @@ +/* + * 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 { schema } from '@kbn/config-schema'; + +export const createFilterSchema = { + filterId: schema.string(), + description: schema.maybe(schema.string()), + items: schema.arrayOf(schema.string()), +}; + +export const updateFilterSchema = { + description: schema.maybe(schema.string()), + addItems: schema.maybe(schema.arrayOf(schema.string())), + removeItems: schema.maybe(schema.arrayOf(schema.string())), +}; diff --git a/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts b/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts index 68ab88744278e..068bfc40f53e1 100644 --- a/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts +++ b/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts @@ -48,7 +48,6 @@ import { dataVisualizerRoutes } from '../routes/data_visualizer'; import { calendars } from '../routes/calendars'; // @ts-ignore: could not find declaration file for module import { fieldsService } from '../routes/fields_service'; -// @ts-ignore: could not find declaration file for module import { filtersRoutes } from '../routes/filters'; // @ts-ignore: could not find declaration file for module import { resultsServiceRoutes } from '../routes/results_service'; diff --git a/x-pack/legacy/plugins/ml/server/routes/apidoc.json b/x-pack/legacy/plugins/ml/server/routes/apidoc.json index 3fac715fef85a..be1554bf55f78 100644 --- a/x-pack/legacy/plugins/ml/server/routes/apidoc.json +++ b/x-pack/legacy/plugins/ml/server/routes/apidoc.json @@ -57,7 +57,7 @@ "DeleteJobs", "CloseJobs", "JobsSummary", - "JobsWithTimerange", + "JobsWithTimeRange", "CreateFullJobsList", "GetAllGroups", "UpdateGroups", @@ -69,6 +69,13 @@ "GetAllJobAndGroupIds", "GetLookBackProgress", "ValidateCategoryExamples", - "TopCategories" + "TopCategories", + "Filters", + "GetFilters", + "GetFilterById", + "CreateFilter", + "UpdateFilter", + "DeleteFilter", + "GetFiltersStats" ] } diff --git a/x-pack/legacy/plugins/ml/server/routes/filters.js b/x-pack/legacy/plugins/ml/server/routes/filters.js deleted file mode 100644 index b09566c6adfbe..0000000000000 --- a/x-pack/legacy/plugins/ml/server/routes/filters.js +++ /dev/null @@ -1,126 +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 { callWithRequestFactory } from '../client/call_with_request_factory'; -import { wrapError } from '../client/errors'; -import { FilterManager } from '../models/filter'; - -// TODO - add function for returning a list of just the filter IDs. -// TODO - add function for returning a list of filter IDs plus item count. -function getAllFilters(callWithRequest) { - const mgr = new FilterManager(callWithRequest); - return mgr.getAllFilters(); -} - -function getAllFilterStats(callWithRequest) { - const mgr = new FilterManager(callWithRequest); - return mgr.getAllFilterStats(); -} - -function getFilter(callWithRequest, filterId) { - const mgr = new FilterManager(callWithRequest); - return mgr.getFilter(filterId); -} - -function newFilter(callWithRequest, filter) { - const mgr = new FilterManager(callWithRequest); - return mgr.newFilter(filter); -} - -function updateFilter(callWithRequest, filterId, description, addItems, removeItems) { - const mgr = new FilterManager(callWithRequest); - return mgr.updateFilter(filterId, description, addItems, removeItems); -} - -function deleteFilter(callWithRequest, filterId) { - const mgr = new FilterManager(callWithRequest); - return mgr.deleteFilter(filterId); -} - -export function filtersRoutes({ commonRouteConfig, elasticsearchPlugin, route }) { - route({ - method: 'GET', - path: '/api/ml/filters', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - return getAllFilters(callWithRequest).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); - - route({ - method: 'GET', - path: '/api/ml/filters/_stats', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - return getAllFilterStats(callWithRequest).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); - - route({ - method: 'GET', - path: '/api/ml/filters/{filterId}', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - const filterId = request.params.filterId; - return getFilter(callWithRequest, filterId).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); - - route({ - method: 'PUT', - path: '/api/ml/filters', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - const body = request.payload; - return newFilter(callWithRequest, body).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); - - route({ - method: 'PUT', - path: '/api/ml/filters/{filterId}', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - const filterId = request.params.filterId; - const payload = request.payload; - return updateFilter( - callWithRequest, - filterId, - payload.description, - payload.addItems, - payload.removeItems - ).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); - - route({ - method: 'DELETE', - path: '/api/ml/filters/{filterId}', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - const filterId = request.params.filterId; - return deleteFilter(callWithRequest, filterId).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); -} diff --git a/x-pack/legacy/plugins/ml/server/routes/filters.ts b/x-pack/legacy/plugins/ml/server/routes/filters.ts new file mode 100644 index 0000000000000..a06f8d4f8b727 --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/routes/filters.ts @@ -0,0 +1,227 @@ +/* + * 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 { RequestHandlerContext } from 'src/core/server'; +import { schema } from '@kbn/config-schema'; +import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { wrapError } from '../client/error_wrapper'; +import { RouteInitialization } from '../new_platform/plugin'; +import { createFilterSchema, updateFilterSchema } from '../new_platform/filters_schema'; +import { FilterManager, FormFilter } from '../models/filter'; + +// TODO - add function for returning a list of just the filter IDs. +// TODO - add function for returning a list of filter IDs plus item count. +function getAllFilters(context: RequestHandlerContext) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.getAllFilters(); +} + +function getAllFilterStats(context: RequestHandlerContext) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.getAllFilterStats(); +} + +function getFilter(context: RequestHandlerContext, filterId: string) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.getFilter(filterId); +} + +function newFilter(context: RequestHandlerContext, filter: FormFilter) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.newFilter(filter); +} + +function updateFilter(context: RequestHandlerContext, filterId: string, filter: FormFilter) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.updateFilter(filterId, filter); +} + +function deleteFilter(context: RequestHandlerContext, filterId: string) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.deleteFilter(filterId); +} + +export function filtersRoutes({ xpackMainPlugin, router }: RouteInitialization) { + /** + * @apiGroup Filters + * + * @api {get} /api/ml/filters Gets filters + * @apiName GetFilters + * @apiDescription Retrieves the list of filters which are used for custom rules in anomaly detection. + * + * @apiSuccess {Boolean} success + * @apiSuccess {Object[]} filters list of filters + */ + router.get( + { + path: '/api/ml/filters', + validate: false, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const resp = await getAllFilters(context); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup Filters + * + * @api {get} /api/ml/filters/:filterId Gets filter by ID + * @apiName GetFilterById + * @apiDescription Retrieves the filter with the specified ID. + * + * @apiSuccess {Boolean} success + * @apiSuccess {Object} filter the filter with the specified ID + */ + router.get( + { + path: '/api/ml/filters/{filterId}', + validate: { + params: schema.object({ filterId: schema.string() }), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const resp = await getFilter(context, request.params.filterId); + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup Filters + * + * @api {put} /api/ml/filters Creates a filter + * @apiName CreateFilter + * @apiDescription Instantiates a filter, for use by custom rules in anomaly detection. + * + * @apiSuccess {Boolean} success + * @apiSuccess {Object} filter created filter + */ + router.put( + { + path: '/api/ml/filters', + validate: { + body: schema.object(createFilterSchema), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const body = request.body; + const resp = await newFilter(context, body); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup Filters + * + * @api {put} /api/ml/filters/:filterId Updates a filter + * @apiName UpdateFilter + * @apiDescription Updates the description of a filter, adds items or removes items. + * + * @apiSuccess {Boolean} success + * @apiSuccess {Object} filter updated filter + */ + router.put( + { + path: '/api/ml/filters/{filterId}', + validate: { + params: schema.object({ filterId: schema.string() }), + body: schema.object(updateFilterSchema), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const { filterId } = request.params; + const body = request.body; + const resp = await updateFilter(context, filterId, body); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup Filters + * + * @api {delete} /api/ml/filters/:filterId Delete filter + * @apiName DeleteFilter + * @apiDescription Deletes the filter with the specified ID. + * + * @apiParam {String} filterId the ID of the filter to delete + */ + router.delete( + { + path: '/api/ml/filters/{filterId}', + validate: { + params: schema.object({ filterId: schema.string() }), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const { filterId } = request.params; + const resp = await deleteFilter(context, filterId); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup Filters + * + * @api {get} /api/ml/filters/_stats Gets filters stats + * @apiName GetFiltersStats + * @apiDescription Retrieves the list of filters which are used for custom rules in anomaly detection, + * with stats on the list of jobs and detectors which are using each filter. + * + * @apiSuccess {Boolean} success + * @apiSuccess {Object[]} filters list of filters with stats on usage + */ + router.get( + { + path: '/api/ml/filters/_stats', + validate: false, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const resp = await getAllFilterStats(context); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); +} diff --git a/x-pack/legacy/plugins/ml/server/routes/job_service.ts b/x-pack/legacy/plugins/ml/server/routes/job_service.ts index 3af651c92353b..9aa3960e59e4c 100644 --- a/x-pack/legacy/plugins/ml/server/routes/job_service.ts +++ b/x-pack/legacy/plugins/ml/server/routes/job_service.ts @@ -29,7 +29,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/force_start_datafeeds + * @api {post} /api/ml/jobs/force_start_datafeeds Start datafeeds * @apiName ForceStartDatafeeds * @apiDescription Starts one or more datafeeds */ @@ -58,7 +58,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/stop_datafeeds + * @api {post} /api/ml/jobs/stop_datafeeds Stop datafeeds * @apiName StopDatafeeds * @apiDescription Stops one or more datafeeds */ @@ -87,7 +87,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/delete_jobs + * @api {post} /api/ml/jobs/delete_jobs Delete jobs * @apiName DeleteJobs * @apiDescription Deletes an existing anomaly detection job */ @@ -116,7 +116,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/close_jobs + * @api {post} /api/ml/jobs/close_jobs Close jobs * @apiName CloseJobs * @apiDescription Closes one or more anomaly detection jobs */ @@ -145,7 +145,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/jobs_summary + * @api {post} /api/ml/jobs/jobs_summary Jobs summary * @apiName JobsSummary * @apiDescription Creates a summary jobs list. Jobs include job stats, datafeed stats, and calendars. */ @@ -174,9 +174,9 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/jobs_with_time_range - * @apiName JobsWithTimerange - * @apiDescription Creates a list of jobs with data about the job's timerange + * @api {post} /api/ml/jobs/jobs_with_time_range Jobs with time range + * @apiName JobsWithTimeRange + * @apiDescription Creates a list of jobs with data about the job's time range */ router.post( { @@ -203,7 +203,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/jobs + * @api {post} /api/ml/jobs/jobs Create jobs list * @apiName CreateFullJobsList * @apiDescription Creates a list of jobs */ @@ -232,7 +232,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {get} /api/ml/jobs/groups + * @api {get} /api/ml/jobs/groups Get job groups * @apiName GetAllGroups * @apiDescription Returns array of group objects with job ids listed for each group */ @@ -258,7 +258,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/update_groups + * @api {post} /api/ml/jobs/update_groups Update job groups * @apiName UpdateGroups * @apiDescription Updates 'groups' property of an anomaly detection job */ @@ -287,7 +287,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {get} /api/ml/jobs/deleting_jobs_tasks + * @api {get} /api/ml/jobs/deleting_jobs_tasks Get deleting job tasks * @apiName DeletingJobTasks * @apiDescription Gets the ids of deleting anomaly detection jobs */ @@ -313,7 +313,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/jobs_exist + * @api {post} /api/ml/jobs/jobs_exist Check if jobs exist * @apiName JobsExist * @apiDescription Checks if each of the jobs in the specified list of IDs exist */ @@ -342,7 +342,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {get} /api/ml/jobs/new_job_caps/:indexPattern + * @api {get} /api/ml/jobs/new_job_caps/:indexPattern Get new job capabilities * @apiName NewJobCaps * @apiDescription Retrieve the capabilities of fields for indices */ @@ -374,7 +374,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/new_job_line_chart + * @api {post} /api/ml/jobs/new_job_line_chart Get job line chart data * @apiName NewJobLineChart * @apiDescription Returns line chart data for anomaly detection job */ @@ -427,7 +427,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/new_job_population_chart + * @api {post} /api/ml/jobs/new_job_population_chart Get population job chart data * @apiName NewJobPopulationChart * @apiDescription Returns population job chart data */ @@ -477,7 +477,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {get} /api/ml/jobs/all_jobs_and_group_ids + * @api {get} /api/ml/jobs/all_jobs_and_group_ids Get all job and group IDs * @apiName GetAllJobAndGroupIds * @apiDescription Returns a list of all job IDs and all group IDs */ @@ -503,7 +503,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/look_back_progress + * @api {post} /api/ml/jobs/look_back_progress Get lookback progress * @apiName GetLookBackProgress * @apiDescription Returns current progress of anomaly detection job */ @@ -532,7 +532,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/categorization_field_examples + * @api {post} /api/ml/jobs/categorization_field_examples Get categorization field examples * @apiName ValidateCategoryExamples * @apiDescription Validates category examples */ @@ -582,7 +582,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/top_categories + * @api {post} /api/ml/jobs/top_categories Get top categories * @apiName TopCategories * @apiDescription Returns list of top categories */ From fe21356020ee9567e3164869bae768c1220db130 Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Fri, 14 Feb 2020 14:14:39 -0500 Subject: [PATCH 08/32] [Endpoint] Policy List UI route and initial view (#56918) * Initial Policy List view * Add `endpoint/policy` route and displays Policy List * test cases (both unit and functional) Does not yet interact with API (Ingest). --- x-pack/plugins/endpoint/common/types.ts | 2 +- .../endpoint/components/truncate_text.ts | 13 + .../public/applications/endpoint/index.tsx | 2 + .../applications/endpoint/store/action.ts | 3 +- .../applications/endpoint/store/index.ts | 5 + .../endpoint/store/policy_list/action.ts | 27 ++ .../endpoint/store/policy_list/fake_data.ts | 53 ++++ .../endpoint/store/policy_list/index.test.ts | 74 ++++++ .../endpoint/store/policy_list/index.ts | 9 + .../endpoint/store/policy_list/middleware.ts | 45 ++++ .../endpoint/store/policy_list/reducer.ts | 48 ++++ .../endpoint/store/policy_list/selectors.ts | 17 ++ .../applications/endpoint/store/reducer.ts | 2 + .../endpoint/store/routing/action.ts | 7 +- .../public/applications/endpoint/types.ts | 29 +++ .../endpoint/view/policy/index.ts | 7 + .../endpoint/view/policy/policy_hooks.ts | 12 + .../endpoint/view/policy/policy_list.tsx | 232 ++++++++++++++++++ .../applications/endpoint/view/use_page_id.ts | 10 +- x-pack/test/functional/apps/endpoint/index.ts | 1 + .../functional/apps/endpoint/policy_list.ts | 47 ++++ .../functional/page_objects/endpoint_page.ts | 19 ++ 22 files changed, 660 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/components/truncate_text.ts create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/action.ts create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/fake_data.ts create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.test.ts create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.ts create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/reducer.ts create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/selectors.ts create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/policy/index.ts create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_hooks.ts create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx create mode 100644 x-pack/test/functional/apps/endpoint/policy_list.ts diff --git a/x-pack/plugins/endpoint/common/types.ts b/x-pack/plugins/endpoint/common/types.ts index 0dc3fc29ca805..5ef9d22e4dd7b 100644 --- a/x-pack/plugins/endpoint/common/types.ts +++ b/x-pack/plugins/endpoint/common/types.ts @@ -118,4 +118,4 @@ export interface EndpointMetadata { /** * The PageId type is used for the payload when firing userNavigatedToPage actions */ -export type PageId = 'alertsPage' | 'managementPage'; +export type PageId = 'alertsPage' | 'managementPage' | 'policyListPage'; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/truncate_text.ts b/x-pack/plugins/endpoint/public/applications/endpoint/components/truncate_text.ts new file mode 100644 index 0000000000000..83f4bc1e79317 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/components/truncate_text.ts @@ -0,0 +1,13 @@ +/* + * 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 styled from 'styled-components'; + +export const TruncateText = styled.div` + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +`; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx index a86c647e771d4..7bb3b13525914 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx @@ -14,6 +14,7 @@ import { Store } from 'redux'; import { appStoreFactory } from './store'; import { AlertIndex } from './view/alerts'; import { ManagementList } from './view/managing'; +import { PolicyList } from './view/policy'; /** * This module will be loaded asynchronously to reduce the bundle size of your plugin's main bundle. @@ -51,6 +52,7 @@ const AppRoot: React.FunctionComponent = React.memo(({ basename, st /> + ( diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/action.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/action.ts index 04c6cf7fc4634..d099c81317090 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/action.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/action.ts @@ -7,5 +7,6 @@ import { ManagementAction } from './managing'; import { AlertAction } from './alerts'; import { RoutingAction } from './routing'; +import { PolicyListAction } from './policy_list'; -export type AppAction = ManagementAction | AlertAction | RoutingAction; +export type AppAction = ManagementAction | AlertAction | RoutingAction | PolicyListAction; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/index.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/index.ts index 3bbcc3f25a6d8..8fe61ae01d319 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/index.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/index.ts @@ -17,6 +17,7 @@ import { CoreStart } from 'kibana/public'; import { appReducer } from './reducer'; import { alertMiddlewareFactory } from './alerts/middleware'; import { managementMiddlewareFactory } from './managing'; +import { policyListMiddlewareFactory } from './policy_list'; import { GlobalState } from '../types'; import { AppAction } from './action'; @@ -56,6 +57,10 @@ export const appStoreFactory = (coreStart: CoreStart): Store => { substateMiddlewareFactory( globalState => globalState.managementList, managementMiddlewareFactory(coreStart) + ), + substateMiddlewareFactory( + globalState => globalState.policyList, + policyListMiddlewareFactory(coreStart) ) ) ) diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/action.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/action.ts new file mode 100644 index 0000000000000..5ac2a4328b00a --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/action.ts @@ -0,0 +1,27 @@ +/* + * 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 { PolicyData } from '../../types'; + +interface ServerReturnedPolicyListData { + type: 'serverReturnedPolicyListData'; + payload: { + policyItems: PolicyData[]; + total: number; + pageSize: number; + pageIndex: number; + }; +} + +interface UserPaginatedPolicyListTable { + type: 'userPaginatedPolicyListTable'; + payload: { + pageSize: number; + pageIndex: number; + }; +} + +export type PolicyListAction = ServerReturnedPolicyListData | UserPaginatedPolicyListTable; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/fake_data.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/fake_data.ts new file mode 100644 index 0000000000000..62bdd28f30be1 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/fake_data.ts @@ -0,0 +1,53 @@ +/* + * 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. + */ + +// !!!! Should be deleted when https://github.com/elastic/endpoint-app-team/issues/150 +// is implemented + +const dateOffsets = [ + 0, + 1000, + 300000, // 5 minutes + 3.6e6, // 1 hour + 86340000, // 23h, 59m + 9e7, // 25h + 9e7 * 5, // 5d +]; + +const randomNumbers = [5, 50, 500, 5000, 50000]; + +const getRandomDateIsoString = () => { + const randomIndex = Math.floor(Math.random() * Math.floor(dateOffsets.length)); + return new Date(Date.now() - dateOffsets[randomIndex]).toISOString(); +}; + +const getRandomNumber = () => { + const randomIndex = Math.floor(Math.random() * Math.floor(randomNumbers.length)); + return randomNumbers[randomIndex]; +}; + +export const getFakeDatasourceApiResponse = async (page: number, pageSize: number) => { + await new Promise(resolve => setTimeout(resolve, 500)); + + // Emulates the API response - see PR: + // https://github.com/elastic/kibana/pull/56567/files#diff-431549a8739efe0c56763f164c32caeeR25 + return { + items: Array.from({ length: pageSize }, (x, i) => ({ + name: `policy with some protections ${i + 1}`, + total: getRandomNumber(), + pending: getRandomNumber(), + failed: getRandomNumber(), + created_by: `admin ABC`, + created: getRandomDateIsoString(), + updated_by: 'admin 123', + updated: getRandomDateIsoString(), + })), + success: true, + total: pageSize * 10, + page, + perPage: pageSize, + }; +}; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.test.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.test.ts new file mode 100644 index 0000000000000..ae4a0868a68fe --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.test.ts @@ -0,0 +1,74 @@ +/* + * 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 { PolicyListState } from '../../types'; +import { applyMiddleware, createStore, Dispatch, Store } from 'redux'; +import { AppAction } from '../action'; +import { policyListReducer } from './reducer'; +import { policyListMiddlewareFactory } from './middleware'; +import { coreMock } from '../../../../../../../../src/core/public/mocks'; +import { CoreStart } from 'kibana/public'; +import { selectIsLoading } from './selectors'; + +describe('policy list store concerns', () => { + const sleep = () => new Promise(resolve => setTimeout(resolve, 1000)); + let fakeCoreStart: jest.Mocked; + let store: Store; + let getState: typeof store['getState']; + let dispatch: Dispatch; + + beforeEach(() => { + fakeCoreStart = coreMock.createStart({ basePath: '/mock' }); + store = createStore( + policyListReducer, + applyMiddleware(policyListMiddlewareFactory(fakeCoreStart)) + ); + getState = store.getState; + dispatch = store.dispatch; + }); + + test('it sets `isLoading` when `userNavigatedToPage`', async () => { + expect(selectIsLoading(getState())).toBe(false); + dispatch({ type: 'userNavigatedToPage', payload: 'policyListPage' }); + expect(selectIsLoading(getState())).toBe(true); + await sleep(); + expect(selectIsLoading(getState())).toBe(false); + }); + + test('it sets `isLoading` when `userPaginatedPolicyListTable`', async () => { + expect(selectIsLoading(getState())).toBe(false); + dispatch({ + type: 'userPaginatedPolicyListTable', + payload: { + pageSize: 10, + pageIndex: 1, + }, + }); + expect(selectIsLoading(getState())).toBe(true); + await sleep(); + expect(selectIsLoading(getState())).toBe(false); + }); + + test('it resets state on `userNavigatedFromPage` action', async () => { + dispatch({ + type: 'serverReturnedPolicyListData', + payload: { + policyItems: [], + pageIndex: 20, + pageSize: 50, + total: 200, + }, + }); + dispatch({ type: 'userNavigatedFromPage', payload: 'policyListPage' }); + expect(getState()).toEqual({ + policyItems: [], + isLoading: false, + pageIndex: 0, + pageSize: 10, + total: 0, + }); + }); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.ts new file mode 100644 index 0000000000000..8086acc41d2bd --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.ts @@ -0,0 +1,9 @@ +/* + * 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 { policyListReducer } from './reducer'; +export { PolicyListAction } from './action'; +export { policyListMiddlewareFactory } from './middleware'; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts new file mode 100644 index 0000000000000..f8e2b7d07c389 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts @@ -0,0 +1,45 @@ +/* + * 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 { MiddlewareFactory, PolicyListState } from '../../types'; + +export const policyListMiddlewareFactory: MiddlewareFactory = coreStart => { + return ({ getState, dispatch }) => next => async action => { + next(action); + + if ( + (action.type === 'userNavigatedToPage' && action.payload === 'policyListPage') || + action.type === 'userPaginatedPolicyListTable' + ) { + const state = getState(); + let pageSize: number; + let pageIndex: number; + + if (action.type === 'userPaginatedPolicyListTable') { + pageSize = action.payload.pageSize; + pageIndex = action.payload.pageIndex; + } else { + pageSize = state.pageSize; + pageIndex = state.pageIndex; + } + + // Need load data from API and remove fake data below + // Refactor tracked via: https://github.com/elastic/endpoint-app-team/issues/150 + const { getFakeDatasourceApiResponse } = await import('./fake_data'); + const { items: policyItems, total } = await getFakeDatasourceApiResponse(pageIndex, pageSize); + + dispatch({ + type: 'serverReturnedPolicyListData', + payload: { + policyItems, + pageIndex, + pageSize, + total, + }, + }); + } + }; +}; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/reducer.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/reducer.ts new file mode 100644 index 0000000000000..77f536d413ae3 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/reducer.ts @@ -0,0 +1,48 @@ +/* + * 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 { Reducer } from 'redux'; +import { PolicyListState } from '../../types'; +import { AppAction } from '../action'; + +const initialPolicyListState = (): PolicyListState => { + return { + policyItems: [], + isLoading: false, + pageIndex: 0, + pageSize: 10, + total: 0, + }; +}; + +export const policyListReducer: Reducer = ( + state = initialPolicyListState(), + action +) => { + if (action.type === 'serverReturnedPolicyListData') { + return { + ...state, + ...action.payload, + isLoading: false, + }; + } + + if ( + action.type === 'userPaginatedPolicyListTable' || + (action.type === 'userNavigatedToPage' && action.payload === 'policyListPage') + ) { + return { + ...state, + isLoading: true, + }; + } + + if (action.type === 'userNavigatedFromPage' && action.payload === 'policyListPage') { + return initialPolicyListState(); + } + + return state; +}; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/selectors.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/selectors.ts new file mode 100644 index 0000000000000..b9c2edbf5d55b --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/selectors.ts @@ -0,0 +1,17 @@ +/* + * 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 { PolicyListState } from '../../types'; + +export const selectPolicyItems = (state: PolicyListState) => state.policyItems; + +export const selectPageIndex = (state: PolicyListState) => state.pageIndex; + +export const selectPageSize = (state: PolicyListState) => state.pageSize; + +export const selectTotal = (state: PolicyListState) => state.total; + +export const selectIsLoading = (state: PolicyListState) => state.isLoading; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/reducer.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/reducer.ts index 7d738c266fae0..3d9d21c0da9c3 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/reducer.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/reducer.ts @@ -8,8 +8,10 @@ import { managementListReducer } from './managing'; import { AppAction } from './action'; import { alertListReducer } from './alerts'; import { GlobalState } from '../types'; +import { policyListReducer } from './policy_list'; export const appReducer: Reducer = combineReducers({ managementList: managementListReducer, alertList: alertListReducer, + policyList: policyListReducer, }); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts index 263a3f72d57d5..9080af8c91817 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts @@ -11,4 +11,9 @@ interface UserNavigatedToPage { readonly payload: PageId; } -export type RoutingAction = UserNavigatedToPage; +interface UserNavigatedFromPage { + readonly type: 'userNavigatedFromPage'; + readonly payload: PageId; +} + +export type RoutingAction = UserNavigatedToPage | UserNavigatedFromPage; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts index 02a7793fc38b0..6b20012592fd9 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts @@ -29,9 +29,38 @@ export interface ManagementListPagination { pageSize: number; } +// REFACTOR to use Types from Ingest Manager - see: https://github.com/elastic/endpoint-app-team/issues/150 +export interface PolicyData { + name: string; + total: number; + pending: number; + failed: number; + created_by: string; + created: string; + updated_by: string; + updated: string; +} + +/** + * Policy list store state + */ +export interface PolicyListState { + /** Array of policy items */ + policyItems: PolicyData[]; + /** total number of policies */ + total: number; + /** Number of policies per page */ + pageSize: number; + /** page number (zero based) */ + pageIndex: number; + /** data is being retrieved from server */ + isLoading: boolean; +} + export interface GlobalState { readonly managementList: ManagementListState; readonly alertList: AlertListState; + readonly policyList: PolicyListState; } export type AlertListData = AlertResultList; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/index.ts b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/index.ts new file mode 100644 index 0000000000000..d561da7574de0 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/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 * from './policy_list'; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_hooks.ts b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_hooks.ts new file mode 100644 index 0000000000000..14558fb6504bb --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_hooks.ts @@ -0,0 +1,12 @@ +/* + * 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 { useSelector } from 'react-redux'; +import { GlobalState, PolicyListState } from '../../types'; + +export function usePolicyListSelector(selector: (state: PolicyListState) => TSelected) { + return useSelector((state: GlobalState) => selector(state.policyList)); +} diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx new file mode 100644 index 0000000000000..75ffa5e8806e9 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx @@ -0,0 +1,232 @@ +/* + * 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, { useCallback, useMemo } from 'react'; +import { + EuiPage, + EuiPageBody, + EuiPageContent, + EuiPageContentBody, + EuiPageContentHeader, + EuiPageContentHeaderSection, + EuiTitle, + EuiBasicTable, + EuiText, + EuiTableFieldDataColumnType, + EuiToolTip, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { + FormattedMessage, + FormattedDate, + FormattedTime, + FormattedNumber, + FormattedRelative, +} from '@kbn/i18n/react'; +import { useDispatch } from 'react-redux'; +import styled from 'styled-components'; +import { usePageId } from '../use_page_id'; +import { + selectIsLoading, + selectPageIndex, + selectPageSize, + selectPolicyItems, + selectTotal, +} from '../../store/policy_list/selectors'; +import { usePolicyListSelector } from './policy_hooks'; +import { PolicyListAction } from '../../store/policy_list'; +import { PolicyData } from '../../types'; +import { TruncateText } from '../../components/truncate_text'; + +interface TableChangeCallbackArguments { + page: { index: number; size: number }; +} + +const TruncateTooltipText = styled(TruncateText)` + .euiToolTipAnchor { + display: block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } +`; + +const FormattedDateAndTime: React.FC<{ date: Date }> = ({ date }) => { + // If date is greater than or equal to 24h (ago), then show it as a date + // else, show it as relative to "now" + return Date.now() - date.getTime() >= 8.64e7 ? ( + <> + + {' @'} + + + ) : ( + <> + + + ); +}; + +const renderDate = (date: string, _item: PolicyData) => ( + + + + + +); + +const renderFormattedNumber = (value: number, _item: PolicyData) => ( + + + +); + +export const PolicyList = React.memo(() => { + usePageId('policyListPage'); + + const dispatch = useDispatch<(action: PolicyListAction) => void>(); + const policyItems = usePolicyListSelector(selectPolicyItems); + const pageIndex = usePolicyListSelector(selectPageIndex); + const pageSize = usePolicyListSelector(selectPageSize); + const totalItemCount = usePolicyListSelector(selectTotal); + const loading = usePolicyListSelector(selectIsLoading); + + const paginationSetup = useMemo(() => { + return { + pageIndex, + pageSize, + totalItemCount, + pageSizeOptions: [10, 20, 50], + hidePerPageOptions: false, + }; + }, [pageIndex, pageSize, totalItemCount]); + + const handleTableChange = useCallback( + ({ page: { index, size } }: TableChangeCallbackArguments) => { + dispatch({ + type: 'userPaginatedPolicyListTable', + payload: { + pageIndex: index, + pageSize: size, + }, + }); + }, + [dispatch] + ); + + const columns: Array> = useMemo( + () => [ + { + field: 'name', + name: i18n.translate('xpack.endpoint.policyList.nameField', { + defaultMessage: 'Policy Name', + }), + truncateText: true, + }, + { + field: 'total', + name: i18n.translate('xpack.endpoint.policyList.totalField', { + defaultMessage: 'Total', + }), + render: renderFormattedNumber, + dataType: 'number', + truncateText: true, + width: '15ch', + }, + { + field: 'pending', + name: i18n.translate('xpack.endpoint.policyList.pendingField', { + defaultMessage: 'Pending', + }), + render: renderFormattedNumber, + dataType: 'number', + truncateText: true, + width: '15ch', + }, + { + field: 'failed', + name: i18n.translate('xpack.endpoint.policyList.failedField', { + defaultMessage: 'Failed', + }), + render: renderFormattedNumber, + dataType: 'number', + truncateText: true, + width: '15ch', + }, + { + field: 'created_by', + name: i18n.translate('xpack.endpoint.policyList.createdByField', { + defaultMessage: 'Created By', + }), + truncateText: true, + }, + { + field: 'created', + name: i18n.translate('xpack.endpoint.policyList.createdField', { + defaultMessage: 'Created', + }), + render: renderDate, + truncateText: true, + }, + { + field: 'updated_by', + name: i18n.translate('xpack.endpoint.policyList.updatedByField', { + defaultMessage: 'Last Updated By', + }), + truncateText: true, + }, + { + field: 'updated', + name: i18n.translate('xpack.endpoint.policyList.updatedField', { + defaultMessage: 'Last Updated', + }), + render: renderDate, + truncateText: true, + }, + ], + [] + ); + + return ( + + + + + + +

+ +

+ +

+ + + +

+ + + + + + + + + ); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts b/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts index 9e241af4c0445..49c39064c8d9a 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts @@ -10,11 +10,19 @@ import { PageId } from '../../../../common/types'; import { RoutingAction } from '../store/routing'; /** - * Dispatches a 'userNavigatedToPage' action with the given 'pageId' as the action payload + * Dispatches a 'userNavigatedToPage' action with the given 'pageId' as the action payload. + * When the component is un-mounted, a `userNavigatedFromPage` action will be dispatched + * with the given `pageId`. + * + * @param pageId A page id */ export function usePageId(pageId: PageId) { const dispatch: (action: RoutingAction) => unknown = useDispatch(); useEffect(() => { dispatch({ type: 'userNavigatedToPage', payload: pageId }); + + return () => { + dispatch({ type: 'userNavigatedFromPage', payload: pageId }); + }; }, [dispatch, pageId]); } diff --git a/x-pack/test/functional/apps/endpoint/index.ts b/x-pack/test/functional/apps/endpoint/index.ts index 5fdf54b98cda6..0ea9344a67aba 100644 --- a/x-pack/test/functional/apps/endpoint/index.ts +++ b/x-pack/test/functional/apps/endpoint/index.ts @@ -12,5 +12,6 @@ export default function({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./landing_page')); loadTestFile(require.resolve('./management')); + loadTestFile(require.resolve('./policy_list')); }); } diff --git a/x-pack/test/functional/apps/endpoint/policy_list.ts b/x-pack/test/functional/apps/endpoint/policy_list.ts new file mode 100644 index 0000000000000..1fe2492bed5a0 --- /dev/null +++ b/x-pack/test/functional/apps/endpoint/policy_list.ts @@ -0,0 +1,47 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function({ getPageObjects, getService }: FtrProviderContext) { + const pageObjects = getPageObjects(['common', 'endpoint']); + const testSubjects = getService('testSubjects'); + + describe('Endpoint Policy List', function() { + this.tags(['ciGroup7']); + before(async () => { + await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/policy'); + }); + + it('loads the Policy List Page', async () => { + await testSubjects.existOrFail('policyListPage'); + }); + it('displays page title', async () => { + const policyTitle = await testSubjects.getVisibleText('policyViewTitle'); + expect(policyTitle).to.equal('Policies'); + }); + it('shows policy count total', async () => { + const policyTotal = await testSubjects.getVisibleText('policyTotalCount'); + expect(policyTotal).to.equal('0 Policies'); + }); + it('includes policy list table', async () => { + await testSubjects.existOrFail('policyTable'); + }); + it('has correct table headers', async () => { + const allHeaderCells = await pageObjects.endpoint.tableHeaderVisibleText('policyTable'); + expect(allHeaderCells).to.eql([ + 'Policy Name', + 'Total', + 'Pending', + 'Failed', + 'Created By', + 'Created', + 'Last Updated By', + 'Last Updated', + ]); + }); + }); +} diff --git a/x-pack/test/functional/page_objects/endpoint_page.ts b/x-pack/test/functional/page_objects/endpoint_page.ts index a306a855a83eb..54f537dd0e8c3 100644 --- a/x-pack/test/functional/page_objects/endpoint_page.ts +++ b/x-pack/test/functional/page_objects/endpoint_page.ts @@ -11,6 +11,25 @@ export function EndpointPageProvider({ getService }: FtrProviderContext) { const table = getService('table'); return { + /** + * Finds the Table with the given `selector` (test subject) and returns + * back an array containing the table's header column text + * + * @param selector + * @returns Promise + */ + async tableHeaderVisibleText(selector: string) { + const $ = await (await testSubjects.find('policyTable')).parseDomContent(); + return $('thead tr th') + .toArray() + .map(th => + $(th) + .text() + .replace(/ /g, '') + .trim() + ); + }, + async welcomeEndpointTitle() { return await testSubjects.getVisibleText('welcomeTitle'); }, From 52a566d095756883168fc54fe9afa502ff695af2 Mon Sep 17 00:00:00 2001 From: gchaps <33642766+gchaps@users.noreply.github.com> Date: Fri, 14 Feb 2020 11:33:25 -0800 Subject: [PATCH 09/32] [DOCS] Adds link to migration guide (#57702) --- docs/developer/plugin/development-plugin-resources.asciidoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/developer/plugin/development-plugin-resources.asciidoc b/docs/developer/plugin/development-plugin-resources.asciidoc index 71c442aaf52e8..a2fd0e23d0be4 100644 --- a/docs/developer/plugin/development-plugin-resources.asciidoc +++ b/docs/developer/plugin/development-plugin-resources.asciidoc @@ -66,3 +66,8 @@ To enable TypeScript support, create a `tsconfig.json` file at the root of your TypeScript code is automatically converted into JavaScript during development, but not in the distributable version of Kibana. If you use the {repo}blob/{branch}/packages/kbn-plugin-helpers[@kbn/plugin-helpers] to build your plugin, then your `.ts` and `.tsx` files will be permanently transpiled before your plugin is archived. If you have your own build process, make sure to run the TypeScript compiler on your source files and ship the compilation output so that your plugin will work with the distributable version of Kibana. + +==== {kib} platform migration guide + +{repo}blob/{branch}/src/core/MIGRATION.md#migrating-legacy-plugins-to-the-new-platform[This guide] +provides an action plan for moving a legacy plugin to the new platform. From 34ae99b516f7aede7e108cad7cb1fb8d82a7de0f Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Fri, 14 Feb 2020 12:36:08 -0700 Subject: [PATCH 10/32] [Reporting/New Platform] Provide async access to server-side dependencies (#56824) * [Reporting/New Platform] Provide async access to server-side * consistent name for reportingPlugin * Prettier changes * simplify reporting usage collector setup * add more tests * extract internals access to separate core class * fix tests * fix imports for jest and build Co-authored-by: Elastic Machine --- .../execute_job/decrypt_job_headers.test.ts | 2 +- .../get_conditional_headers.test.ts | 59 ++- .../execute_job/get_custom_logo.test.ts | 29 +- .../common/execute_job/get_custom_logo.ts | 18 +- .../common/execute_job/get_full_urls.test.ts | 2 +- .../common/lib/screenshots/index.ts | 18 +- .../export_types/csv/server/create_job.ts | 9 +- .../csv/server/execute_job.test.js | 354 +++++++++++------- .../export_types/csv/server/execute_job.ts | 133 +++---- .../csv/server/lib/field_format_map.ts | 10 +- .../server/create_job/create_job.ts | 4 +- .../server/execute_job.ts | 8 +- .../server/lib/generate_csv.ts | 11 +- .../server/lib/generate_csv_search.ts | 47 +-- .../png/server/create_job/index.ts | 13 +- .../png/server/execute_job/index.test.js | 47 ++- .../png/server/execute_job/index.ts | 16 +- .../printable_pdf/server/create_job/index.ts | 11 +- .../server/execute_job/index.test.js | 60 +-- .../printable_pdf/server/execute_job/index.ts | 18 +- x-pack/legacy/plugins/reporting/index.ts | 2 +- .../legacy/plugins/reporting/reporting.d.ts | 2 +- .../legacy/plugins/reporting/server/core.ts | 122 ++++++ .../legacy/plugins/reporting/server/index.ts | 3 + .../legacy/plugins/reporting/server/legacy.ts | 9 +- .../reporting/server/lib/create_queue.ts | 31 +- .../server/lib/create_worker.test.ts | 38 +- .../reporting/server/lib/create_worker.ts | 36 +- .../reporting/server/lib/enqueue_job.ts | 21 +- .../plugins/reporting/server/lib/get_user.ts | 2 +- .../reporting/server/lib/validate/index.ts | 5 +- .../legacy/plugins/reporting/server/plugin.ts | 109 ++---- .../server/routes/generate_from_jobparams.ts | 2 +- .../routes/generate_from_savedobject.ts | 2 +- .../generate_from_savedobject_immediate.ts | 10 +- .../reporting/server/routes/generation.ts | 26 +- .../plugins/reporting/server/routes/index.ts | 16 +- .../reporting/server/routes/jobs.test.js | 128 +++++-- .../plugins/reporting/server/routes/jobs.ts | 6 +- .../routes/lib/authorized_user_pre_routing.ts | 2 +- .../lib/reporting_feature_pre_routing.ts | 2 +- .../routes/lib/route_config_factories.ts | 2 +- .../plugins/reporting/server/types.d.ts | 50 +++ .../server/usage/decorate_range_stats.ts | 2 +- .../usage/reporting_usage_collector.test.js | 230 +++++++----- .../server/usage/reporting_usage_collector.ts | 25 +- .../create_mock_reportingplugin.ts | 53 +++ .../test_helpers/create_mock_server.ts | 7 - .../plugins/reporting/test_helpers/index.ts | 8 + x-pack/legacy/plugins/reporting/types.d.ts | 36 +- 50 files changed, 1109 insertions(+), 747 deletions(-) create mode 100644 x-pack/legacy/plugins/reporting/server/core.ts create mode 100644 x-pack/legacy/plugins/reporting/server/types.d.ts create mode 100644 x-pack/legacy/plugins/reporting/test_helpers/create_mock_reportingplugin.ts create mode 100644 x-pack/legacy/plugins/reporting/test_helpers/index.ts diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.test.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.test.ts index 1b7ba3c90bab1..468caf93ec5dd 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.test.ts @@ -5,7 +5,7 @@ */ import { cryptoFactory } from '../../../server/lib/crypto'; -import { createMockServer } from '../../../test_helpers/create_mock_server'; +import { createMockServer } from '../../../test_helpers'; import { Logger } from '../../../types'; import { decryptJobHeaders } from './decrypt_job_headers'; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts index 070bdb4314af9..eedb742ad7597 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts @@ -4,13 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createMockServer } from '../../../test_helpers/create_mock_server'; -import { getConditionalHeaders, getCustomLogo } from './index'; +import { createMockReportingCore, createMockServer } from '../../../test_helpers'; +import { ReportingCore } from '../../../server'; import { JobDocPayload } from '../../../types'; import { JobDocPayloadPDF } from '../../printable_pdf/types'; +import { getConditionalHeaders, getCustomLogo } from './index'; +let mockReportingPlugin: ReportingCore; let mockServer: any; -beforeEach(() => { +beforeEach(async () => { + mockReportingPlugin = await createMockReportingCore(); mockServer = createMockServer(''); }); @@ -148,56 +151,76 @@ describe('conditions', () => { }); test('uses basePath from job when creating saved object service', async () => { + const mockGetSavedObjectsClient = jest.fn(); + mockReportingPlugin.getSavedObjectsClient = mockGetSavedObjectsClient; + const permittedHeaders = { foo: 'bar', baz: 'quix', }; - const conditionalHeaders = await getConditionalHeaders({ job: {} as JobDocPayload, filteredHeaders: permittedHeaders, server: mockServer, }); - - const logo = 'custom-logo'; - mockServer.uiSettingsServiceFactory().get.mockReturnValue(logo); - const jobBasePath = '/sbp/s/marketing'; await getCustomLogo({ + reporting: mockReportingPlugin, job: { basePath: jobBasePath } as JobDocPayloadPDF, conditionalHeaders, server: mockServer, }); - expect(mockServer.savedObjects.getScopedSavedObjectsClient.mock.calls[0][0].getBasePath()).toBe( - jobBasePath - ); + const getBasePath = mockGetSavedObjectsClient.mock.calls[0][0].getBasePath; + expect(getBasePath()).toBe(jobBasePath); }); test(`uses basePath from server if job doesn't have a basePath when creating saved object service`, async () => { + const mockGetSavedObjectsClient = jest.fn(); + mockReportingPlugin.getSavedObjectsClient = mockGetSavedObjectsClient; + const permittedHeaders = { foo: 'bar', baz: 'quix', }; - const conditionalHeaders = await getConditionalHeaders({ job: {} as JobDocPayload, filteredHeaders: permittedHeaders, server: mockServer, }); - const logo = 'custom-logo'; - mockServer.uiSettingsServiceFactory().get.mockReturnValue(logo); - await getCustomLogo({ + reporting: mockReportingPlugin, job: {} as JobDocPayloadPDF, conditionalHeaders, server: mockServer, }); - expect(mockServer.savedObjects.getScopedSavedObjectsClient.mock.calls[0][0].getBasePath()).toBe( - '/sbp' - ); + const getBasePath = mockGetSavedObjectsClient.mock.calls[0][0].getBasePath; + expect(getBasePath()).toBe(`/sbp`); + expect(mockGetSavedObjectsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "getBasePath": [Function], + "headers": Object { + "baz": "quix", + "foo": "bar", + }, + "path": "/", + "raw": Object { + "req": Object { + "url": "/", + }, + }, + "route": Object { + "settings": Object {}, + }, + "url": Object { + "href": "/", + }, + }, + ] + `); }); describe('config formatting', () => { diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.test.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.test.ts index ff2c44026315d..fa53f474dfba7 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.test.ts @@ -4,12 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createMockServer } from '../../../test_helpers/create_mock_server'; -import { getConditionalHeaders, getCustomLogo } from './index'; +import { ReportingCore } from '../../../server'; +import { createMockReportingCore, createMockServer } from '../../../test_helpers'; +import { ServerFacade } from '../../../types'; import { JobDocPayloadPDF } from '../../printable_pdf/types'; +import { getConditionalHeaders, getCustomLogo } from './index'; -let mockServer: any; -beforeEach(() => { +let mockReportingPlugin: ReportingCore; +let mockServer: ServerFacade; +beforeEach(async () => { + mockReportingPlugin = await createMockReportingCore(); mockServer = createMockServer(''); }); @@ -19,6 +23,17 @@ test(`gets logo from uiSettings`, async () => { baz: 'quix', }; + const mockGet = jest.fn(); + mockGet.mockImplementationOnce((...args: any[]) => { + if (args[0] === 'xpackReporting:customPdfLogo') { + return 'purple pony'; + } + throw new Error('wrong caller args!'); + }); + mockReportingPlugin.getUiSettingsServiceFactory = jest.fn().mockResolvedValue({ + get: mockGet, + }); + const conditionalHeaders = await getConditionalHeaders({ job: {} as JobDocPayloadPDF, filteredHeaders: permittedHeaders, @@ -26,12 +41,12 @@ test(`gets logo from uiSettings`, async () => { }); const { logo } = await getCustomLogo({ + reporting: mockReportingPlugin, job: {} as JobDocPayloadPDF, conditionalHeaders, server: mockServer, }); - mockServer.uiSettingsServiceFactory().get.mockReturnValue(logo); - - expect(mockServer.uiSettingsServiceFactory().get).toBeCalledWith('xpackReporting:customPdfLogo'); + expect(mockGet).toBeCalledWith('xpackReporting:customPdfLogo'); + expect(logo).toBe('purple pony'); }); diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts index 0059276f6df71..7af5edab41ab7 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts @@ -5,14 +5,17 @@ */ import { UI_SETTINGS_CUSTOM_PDF_LOGO } from '../../../common/constants'; +import { ReportingCore } from '../../../server'; import { ConditionalHeaders, ServerFacade } from '../../../types'; import { JobDocPayloadPDF } from '../../printable_pdf/types'; // Logo is PDF only export const getCustomLogo = async ({ + reporting, server, job, conditionalHeaders, }: { + reporting: ReportingCore; server: ServerFacade; job: JobDocPayloadPDF; conditionalHeaders: ConditionalHeaders; @@ -27,19 +30,12 @@ export const getCustomLogo = async ({ getBasePath: () => job.basePath || serverBasePath, path: '/', route: { settings: {} }, - url: { - href: '/', - }, - raw: { - req: { - url: '/', - }, - }, + url: { href: '/' }, + raw: { req: { url: '/' } }, }; - const savedObjects = server.savedObjects; - const savedObjectsClient = savedObjects.getScopedSavedObjectsClient(fakeRequest); - const uiSettings = server.uiSettingsServiceFactory({ savedObjectsClient }); + const savedObjectsClient = await reporting.getSavedObjectsClient(fakeRequest); + const uiSettings = await reporting.getUiSettingsServiceFactory(savedObjectsClient); const logo: string = await uiSettings.get(UI_SETTINGS_CUSTOM_PDF_LOGO); return { conditionalHeaders, logo }; }; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.test.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.test.ts index 9b2a065427f70..27e772195f726 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createMockServer } from '../../../test_helpers/create_mock_server'; +import { createMockServer } from '../../../test_helpers'; import { ServerFacade } from '../../../types'; import { JobDocPayloadPNG } from '../../png/types'; import { JobDocPayloadPDF } from '../../printable_pdf/types'; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts index 9fd3ee391ddbb..62b5e29e88ecf 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts @@ -5,19 +5,19 @@ */ import * as Rx from 'rxjs'; -import { first, concatMap, take, toArray, mergeMap } from 'rxjs/operators'; -import { ServerFacade, CaptureConfig, HeadlessChromiumDriverFactory } from '../../../../types'; -import { ScreenshotResults, ScreenshotObservableOpts } from './types'; -import { injectCustomCss } from './inject_css'; -import { openUrl } from './open_url'; -import { waitForRenderComplete } from './wait_for_render'; -import { getNumberOfItems } from './get_number_of_items'; -import { waitForElementsToBeInDOM } from './wait_for_dom_elements'; -import { getTimeRange } from './get_time_range'; +import { concatMap, first, mergeMap, take, toArray } from 'rxjs/operators'; +import { CaptureConfig, HeadlessChromiumDriverFactory, ServerFacade } from '../../../../types'; import { getElementPositionAndAttributes } from './get_element_position_data'; +import { getNumberOfItems } from './get_number_of_items'; import { getScreenshots } from './get_screenshots'; +import { getTimeRange } from './get_time_range'; +import { injectCustomCss } from './inject_css'; +import { openUrl } from './open_url'; import { scanPage } from './scan_page'; import { skipTelemetry } from './skip_telemetry'; +import { ScreenshotObservableOpts, ScreenshotResults } from './types'; +import { waitForElementsToBeInDOM } from './wait_for_dom_elements'; +import { waitForRenderComplete } from './wait_for_render'; export function screenshotsObservableFactory( server: ServerFacade, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts index 063ac7f77704c..7ea67277015ab 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts @@ -4,19 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ +import { ReportingCore } from '../../../server'; import { cryptoFactory } from '../../../server/lib/crypto'; import { - CreateJobFactory, ConditionalHeaders, - ServerFacade, - RequestFacade, + CreateJobFactory, ESQueueCreateJobFn, + RequestFacade, + ServerFacade, } from '../../../types'; import { JobParamsDiscoverCsv } from '../types'; export const createJobFactory: CreateJobFactory> = function createJobFactoryFn(server: ServerFacade) { +>> = function createJobFactoryFn(reporting: ReportingCore, server: ServerFacade) { const crypto = cryptoFactory(server); return async function createJob( diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js index b21d628332027..f12916b734dbf 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js @@ -9,6 +9,7 @@ import sinon from 'sinon'; import nodeCrypto from '@elastic/node-crypto'; import { CancellationToken } from '../../../common/cancellation_token'; import { fieldFormats } from '../../../../../../../src/plugins/data/server'; +import { createMockReportingCore } from '../../../test_helpers'; import { LevelLogger } from '../../../server/lib/level_logger'; import { executeJobFactory } from './execute_job'; import { setFieldFormats } from '../../../server/services'; @@ -36,16 +37,19 @@ describe('CSV Execute Job', function() { let encryptedHeaders; let cancellationToken; + let mockReportingPlugin; let mockServer; let clusterStub; let callAsCurrentUserStub; - let uiSettingsGetStub; const mockElasticsearch = { dataClient: { asScoped: () => clusterStub, }, }; + const mockUiSettingsClient = { + get: sinon.stub(), + }; beforeAll(async function() { const crypto = nodeCrypto({ encryptionKey }); @@ -53,6 +57,8 @@ describe('CSV Execute Job', function() { }); beforeEach(async function() { + mockReportingPlugin = await createMockReportingCore(); + mockReportingPlugin.getUiSettingsServiceFactory = () => mockUiSettingsClient; cancellationToken = new CancellationToken(); defaultElasticsearchResponse = { @@ -70,9 +76,8 @@ describe('CSV Execute Job', function() { .resolves(defaultElasticsearchResponse); const configGetStub = sinon.stub(); - uiSettingsGetStub = sinon.stub(); - uiSettingsGetStub.withArgs('csv:separator').returns(','); - uiSettingsGetStub.withArgs('csv:quoteValues').returns(true); + mockUiSettingsClient.get.withArgs('csv:separator').returns(','); + mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(true); setFieldFormats({ fieldFormatServiceFactory: function() { @@ -90,26 +95,11 @@ describe('CSV Execute Job', function() { }); mockServer = { - expose: function() {}, - plugins: { - elasticsearch: { - getCluster: function() { - return clusterStub; - }, - }, - }, config: function() { return { get: configGetStub, }; }, - savedObjects: { - getScopedSavedObjectsClient: sinon.stub(), - }, - uiSettingsServiceFactory: sinon.stub().returns({ - get: uiSettingsGetStub, - }), - log: function() {}, }; mockServer .config() @@ -125,83 +115,14 @@ describe('CSV Execute Job', function() { .returns({}); }); - describe('calls getScopedSavedObjectsClient with request', function() { - it('containing decrypted headers', async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - expect(mockServer.savedObjects.getScopedSavedObjectsClient.calledOnce).toBe(true); - expect(mockServer.savedObjects.getScopedSavedObjectsClient.firstCall.args[0].headers).toEqual( - headers - ); - }); - - it(`containing getBasePath() returning server's basePath if the job doesn't have one`, async function() { - const serverBasePath = '/foo-server/basePath/'; - mockServer - .config() - .get.withArgs('server.basePath') - .returns(serverBasePath); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - expect(mockServer.savedObjects.getScopedSavedObjectsClient.calledOnce).toBe(true); - expect( - mockServer.savedObjects.getScopedSavedObjectsClient.firstCall.args[0].getBasePath() - ).toEqual(serverBasePath); - }); - - it(`containing getBasePath() returning job's basePath if the job has one`, async function() { - const serverBasePath = '/foo-server/basePath/'; - mockServer - .config() - .get.withArgs('server.basePath') - .returns(serverBasePath); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); - const jobBasePath = 'foo-job/basePath/'; - await executeJob( - 'job789', - { - headers: encryptedHeaders, - fields: [], - searchRequest: { index: null, body: null }, - basePath: jobBasePath, - }, - cancellationToken - ); - expect(mockServer.savedObjects.getScopedSavedObjectsClient.calledOnce).toBe(true); - expect( - mockServer.savedObjects.getScopedSavedObjectsClient.firstCall.args[0].getBasePath() - ).toEqual(jobBasePath); - }); - }); - - describe('uiSettings', function() { - it('passed scoped SavedObjectsClient to uiSettingsServiceFactory', async function() { - const returnValue = Symbol(); - mockServer.savedObjects.getScopedSavedObjectsClient.returns(returnValue); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - expect(mockServer.uiSettingsServiceFactory.calledOnce).toBe(true); - expect(mockServer.uiSettingsServiceFactory.firstCall.args[0].savedObjectsClient).toBe( - returnValue - ); - }); - }); - describe('basic Elasticsearch call behavior', function() { it('should decrypt encrypted headers and pass to callAsCurrentUser', async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); await executeJob( 'job456', { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, @@ -217,7 +138,12 @@ describe('CSV Execute Job', function() { testBody: true, }; - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const job = { headers: encryptedHeaders, fields: [], @@ -244,7 +170,12 @@ describe('CSV Execute Job', function() { _scroll_id: scrollId, }); callAsCurrentUserStub.onSecondCall().resolves(defaultElasticsearchResponse); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); await executeJob( 'job456', { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, @@ -258,7 +189,12 @@ describe('CSV Execute Job', function() { }); it('should not execute scroll if there are no hits from the search', async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); await executeJob( 'job456', { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, @@ -288,7 +224,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); await executeJob( 'job456', { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, @@ -323,7 +264,12 @@ describe('CSV Execute Job', function() { _scroll_id: lastScrollId, }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); await executeJob( 'job456', { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, @@ -351,7 +297,12 @@ describe('CSV Execute Job', function() { _scroll_id: lastScrollId, }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -381,7 +332,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -409,7 +365,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['=SUM(A1:A2)', 'two'], @@ -437,7 +398,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -465,7 +431,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -485,7 +456,12 @@ describe('CSV Execute Job', function() { describe('Elasticsearch call errors', function() { it('should reject Promise if search call errors out', async function() { callAsCurrentUserStub.rejects(new Error()); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: [], @@ -504,7 +480,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); callAsCurrentUserStub.onSecondCall().rejects(new Error()); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: [], @@ -525,7 +506,12 @@ describe('CSV Execute Job', function() { _scroll_id: undefined, }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: [], @@ -546,7 +532,12 @@ describe('CSV Execute Job', function() { _scroll_id: undefined, }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: [], @@ -574,7 +565,12 @@ describe('CSV Execute Job', function() { _scroll_id: undefined, }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: [], @@ -602,7 +598,12 @@ describe('CSV Execute Job', function() { _scroll_id: undefined, }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: [], @@ -638,7 +639,12 @@ describe('CSV Execute Job', function() { }); it('should stop calling Elasticsearch when cancellationToken.cancel is called', async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); executeJob( 'job345', { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, @@ -653,7 +659,12 @@ describe('CSV Execute Job', function() { }); it(`shouldn't call clearScroll if it never got a scrollId`, async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); executeJob( 'job345', { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, @@ -667,7 +678,12 @@ describe('CSV Execute Job', function() { }); it('should call clearScroll if it got a scrollId', async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); executeJob( 'job345', { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, @@ -685,7 +701,12 @@ describe('CSV Execute Job', function() { describe('csv content', function() { it('should write column headers to output, even if there are no results', async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -696,8 +717,13 @@ describe('CSV Execute Job', function() { }); it('should use custom uiSettings csv:separator for header', async function() { - uiSettingsGetStub.withArgs('csv:separator').returns(';'); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + mockUiSettingsClient.get.withArgs('csv:separator').returns(';'); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -708,8 +734,13 @@ describe('CSV Execute Job', function() { }); it('should escape column headers if uiSettings csv:quoteValues is true', async function() { - uiSettingsGetStub.withArgs('csv:quoteValues').returns(true); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(true); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one and a half', 'two', 'three-and-four', 'five & six'], @@ -720,8 +751,13 @@ describe('CSV Execute Job', function() { }); it(`shouldn't escape column headers if uiSettings csv:quoteValues is false`, async function() { - uiSettingsGetStub.withArgs('csv:quoteValues').returns(false); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(false); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one and a half', 'two', 'three-and-four', 'five & six'], @@ -732,7 +768,12 @@ describe('CSV Execute Job', function() { }); it('should write column headers to output, when there are results', async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); callAsCurrentUserStub.onFirstCall().resolves({ hits: { hits: [{ one: '1', two: '2' }], @@ -752,7 +793,12 @@ describe('CSV Execute Job', function() { }); it('should use comma separated values of non-nested fields from _source', async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); callAsCurrentUserStub.onFirstCall().resolves({ hits: { hits: [{ _source: { one: 'foo', two: 'bar' } }], @@ -773,7 +819,12 @@ describe('CSV Execute Job', function() { }); it('should concatenate the hits from multiple responses', async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); callAsCurrentUserStub.onFirstCall().resolves({ hits: { hits: [{ _source: { one: 'foo', two: 'bar' } }], @@ -801,7 +852,12 @@ describe('CSV Execute Job', function() { }); it('should use field formatters to format fields', async function() { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); callAsCurrentUserStub.onFirstCall().resolves({ hits: { hits: [{ _source: { one: 'foo', two: 'bar' } }], @@ -846,7 +902,12 @@ describe('CSV Execute Job', function() { .get.withArgs('xpack.reporting.csv.maxSizeBytes') .returns(1); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -879,7 +940,12 @@ describe('CSV Execute Job', function() { .get.withArgs('xpack.reporting.csv.maxSizeBytes') .returns(9); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -919,7 +985,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -948,6 +1019,7 @@ describe('CSV Execute Job', function() { let maxSizeReached; beforeEach(async function() { + mockReportingPlugin.getUiSettingsServiceFactory = () => mockUiSettingsClient; mockServer .config() .get.withArgs('xpack.reporting.csv.maxSizeBytes') @@ -960,7 +1032,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -1000,7 +1077,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -1029,7 +1111,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], @@ -1058,7 +1145,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); + const executeJob = await executeJobFactory( + mockReportingPlugin, + mockServer, + mockElasticsearch, + mockLogger + ); const jobParams = { headers: encryptedHeaders, fields: ['one', 'two'], diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts index 9f94a755cf655..1579985891053 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts @@ -4,20 +4,26 @@ * you may not use this file except in compliance with the Elastic License. */ -import Hapi from 'hapi'; import { i18n } from '@kbn/i18n'; -import { ElasticsearchServiceSetup, KibanaRequest } from '../../../../../../../src/core/server'; +import Hapi from 'hapi'; +import { + ElasticsearchServiceSetup, + IUiSettingsClient, + KibanaRequest, +} from '../../../../../../../src/core/server'; import { CSV_JOB_TYPE } from '../../../common/constants'; +import { ReportingCore } from '../../../server'; import { cryptoFactory } from '../../../server/lib'; +import { getFieldFormats } from '../../../server/services'; import { ESQueueWorkerExecuteFn, ExecuteJobFactory, Logger, ServerFacade } from '../../../types'; import { JobDocPayloadDiscoverCsv } from '../types'; import { fieldFormatMapFactory } from './lib/field_format_map'; import { createGenerateCsv } from './lib/generate_csv'; -import { getFieldFormats } from '../../../server/services'; export const executeJobFactory: ExecuteJobFactory> = function executeJobFactoryFn( +>> = async function executeJobFactoryFn( + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, parentLogger: Logger @@ -40,83 +46,78 @@ export const executeJobFactory: ExecuteJobFactory { + let decryptedHeaders; + try { + decryptedHeaders = await crypto.decrypt(headers); + } catch (err) { + logger.error(err); + throw new Error( + i18n.translate( + 'xpack.reporting.exportTypes.csv.executeJob.failedToDecryptReportJobDataErrorMessage', + { + defaultMessage: 'Failed to decrypt report job data. Please ensure that {encryptionKey} is set and re-generate this report. {err}', + values: { encryptionKey: 'xpack.reporting.encryptionKey', err: err.toString() }, + } + ) + ); // prettier-ignore + } + return decryptedHeaders; + }; - const fakeRequest = { - headers: decryptedHeaders, + const fakeRequest = KibanaRequest.from({ + headers: await decryptHeaders(), // This is used by the spaces SavedObjectClientWrapper to determine the existing space. // We use the basePath from the saved job, which we'll have post spaces being implemented; // or we use the server base path, which uses the default space getBasePath: () => basePath || serverBasePath, path: '/', route: { settings: {} }, - url: { - href: '/', - }, - raw: { - req: { - url: '/', - }, - }, - }; + url: { href: '/' }, + raw: { req: { url: '/' } }, + } as Hapi.Request); + + const { callAsCurrentUser } = elasticsearch.dataClient.asScoped(fakeRequest); + const callEndpoint = (endpoint: string, clientParams = {}, options = {}) => + callAsCurrentUser(endpoint, clientParams, options); - const { callAsCurrentUser } = elasticsearch.dataClient.asScoped( - KibanaRequest.from(fakeRequest as Hapi.Request) - ); - const callEndpoint = (endpoint: string, clientParams = {}, options = {}) => { - return callAsCurrentUser(endpoint, clientParams, options); + const savedObjectsClient = await reporting.getSavedObjectsClient(fakeRequest); + const uiSettingsClient = await reporting.getUiSettingsServiceFactory(savedObjectsClient); + + const getFormatsMap = async (client: IUiSettingsClient) => { + const fieldFormats = await getFieldFormats().fieldFormatServiceFactory(client); + return fieldFormatMapFactory(indexPatternSavedObject, fieldFormats); }; - const savedObjects = server.savedObjects; - const savedObjectsClient = savedObjects.getScopedSavedObjectsClient( - (fakeRequest as unknown) as KibanaRequest - ); - const uiConfig = server.uiSettingsServiceFactory({ - savedObjectsClient, - }); + const getUiSettings = async (client: IUiSettingsClient) => { + const [separator, quoteValues, timezone] = await Promise.all([ + client.get('csv:separator'), + client.get('csv:quoteValues'), + client.get('dateFormat:tz'), + ]); - const [formatsMap, uiSettings] = await Promise.all([ - (async () => { - const fieldFormats = await getFieldFormats().fieldFormatServiceFactory(uiConfig); - return fieldFormatMapFactory(indexPatternSavedObject, fieldFormats); - })(), - (async () => { - const [separator, quoteValues, timezone] = await Promise.all([ - uiConfig.get('csv:separator'), - uiConfig.get('csv:quoteValues'), - uiConfig.get('dateFormat:tz'), - ]); + if (timezone === 'Browser') { + logger.warn( + i18n.translate('xpack.reporting.exportTypes.csv.executeJob.dateFormateSetting', { + defaultMessage: 'Kibana Advanced Setting "{dateFormatTimezone}" is set to "Browser". Dates will be formatted as UTC to avoid ambiguity.', + values: { dateFormatTimezone: 'dateFormat:tz' } + }) + ); // prettier-ignore + } - if (timezone === 'Browser') { - jobLogger.warn( - `Kibana Advanced Setting "dateFormat:tz" is set to "Browser". Dates will be formatted as UTC to avoid ambiguity.` - ); - } + return { + separator, + quoteValues, + timezone, + }; + }; - return { - separator, - quoteValues, - timezone, - }; - })(), + const [formatsMap, uiSettings] = await Promise.all([ + getFormatsMap(uiSettingsClient), + getUiSettings(uiSettingsClient), ]); const generateCsv = createGenerateCsv(jobLogger); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts index e1459e195d9f6..dac963635c469 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts @@ -9,15 +9,7 @@ import { FieldFormatConfig, IFieldFormatsRegistry, } from '../../../../../../../../src/plugins/data/server'; - -interface IndexPatternSavedObject { - attributes: { - fieldFormatMap: string; - }; - id: string; - type: string; - version: string; -} +import { IndexPatternSavedObject } from '../../../../types'; /** * Create a map of FieldFormat instances for index pattern fields diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts index ddef2aa0a6268..17072d311b35f 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts @@ -5,9 +5,10 @@ */ import { notFound, notImplemented } from 'boom'; -import { get } from 'lodash'; import { ElasticsearchServiceSetup } from 'kibana/server'; +import { get } from 'lodash'; import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../../common/constants'; +import { ReportingCore } from '../../../../server'; import { cryptoFactory } from '../../../../server/lib'; import { CreateJobFactory, @@ -37,6 +38,7 @@ interface VisData { export const createJobFactory: CreateJobFactory> = function createJobFactoryFn( + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, parentLogger: Logger diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts index b1b7b7d818200..6bb3e73fcfe84 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import { ElasticsearchServiceSetup } from 'kibana/server'; import { CONTENT_TYPE_CSV, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; +import { ReportingCore } from '../../../server'; import { cryptoFactory } from '../../../server/lib'; import { ExecuteJobFactory, @@ -22,13 +23,15 @@ import { createGenerateCsv } from './lib'; export const executeJobFactory: ExecuteJobFactory> = function executeJobFactoryFn( +>> = async function executeJobFactoryFn( + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, parentLogger: Logger ) { const crypto = cryptoFactory(server); const logger = parentLogger.clone([CSV_FROM_SAVEDOBJECT_JOB_TYPE, 'execute-job']); + const generateCsv = createGenerateCsv(reporting, server, elasticsearch, parentLogger); return async function executeJob( jobId: string | null, @@ -86,11 +89,8 @@ export const executeJobFactory: ExecuteJobFactory { +const getEsQueryConfig = async (config: IUiSettingsClient) => { const configs = await Promise.all([ config.get('query:allowLeadingWildcards'), config.get('query:queryString:options'), @@ -49,7 +53,7 @@ const getEsQueryConfig = async (config: any) => { } as EsQueryConfig; }; -const getUiSettings = async (config: any) => { +const getUiSettings = async (config: IUiSettingsClient) => { const configs = await Promise.all([config.get('csv:separator'), config.get('csv:quoteValues')]); const [separator, quoteValues] = configs; return { separator, quoteValues }; @@ -57,14 +61,14 @@ const getUiSettings = async (config: any) => { export async function generateCsvSearch( req: RequestFacade, + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, logger: Logger, searchPanel: SearchPanel, jobParams: JobParamsDiscoverCsv ): Promise { - const { savedObjects, uiSettingsServiceFactory } = server; - const savedObjectsClient = savedObjects.getScopedSavedObjectsClient( + const savedObjectsClient = await reporting.getSavedObjectsClient( KibanaRequest.from(req.getRawRequest()) ); const { indexPatternSavedObjectId, timerange } = searchPanel; @@ -73,7 +77,8 @@ export async function generateCsvSearch( savedObjectsClient, indexPatternSavedObjectId ); - const uiConfig = uiSettingsServiceFactory({ savedObjectsClient }); + + const uiConfig = await reporting.getUiSettingsServiceFactory(savedObjectsClient); const esQueryConfig = await getEsQueryConfig(uiConfig); const { diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts index 3f03246106d3e..a6911e1f14704 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts @@ -4,20 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ +import { validateUrls } from '../../../../common/validate_urls'; +import { ReportingCore } from '../../../../server'; +import { cryptoFactory } from '../../../../server/lib/crypto'; import { + ConditionalHeaders, CreateJobFactory, - ServerFacade, - RequestFacade, ESQueueCreateJobFn, - ConditionalHeaders, + RequestFacade, + ServerFacade, } from '../../../../types'; -import { validateUrls } from '../../../../common/validate_urls'; -import { cryptoFactory } from '../../../../server/lib/crypto'; import { JobParamsPNG } from '../../types'; export const createJobFactory: CreateJobFactory> = function createJobFactoryFn(server: ServerFacade) { +>> = function createJobFactoryFn(reporting: ReportingCore, server: ServerFacade) { const crypto = cryptoFactory(server); return async function createJob( diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js index bb33ef9c19a1d..c0c21119e1d53 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js @@ -6,6 +6,7 @@ import * as Rx from 'rxjs'; import { memoize } from 'lodash'; +import { createMockReportingCore } from '../../../../test_helpers'; import { cryptoFactory } from '../../../../server/lib/crypto'; import { executeJobFactory } from './index'; import { generatePngObservableFactory } from '../lib/generate_png'; @@ -19,7 +20,11 @@ const cancellationToken = { let config; let mockServer; -beforeEach(() => { +let mockReporting; + +beforeEach(async () => { + mockReporting = await createMockReportingCore(); + config = { 'xpack.reporting.encryptionKey': 'testencryptionkey', 'server.basePath': '/sbp', @@ -27,18 +32,11 @@ beforeEach(() => { 'server.port': 5601, }; mockServer = { - expose: () => {}, // NOTE: this is for oncePerServer config: memoize(() => ({ get: jest.fn() })), info: { protocol: 'http', }, - savedObjects: { - getScopedSavedObjectsClient: jest.fn(), - }, - uiSettingsServiceFactory: jest.fn().mockReturnValue({ get: jest.fn() }), - log: jest.fn(), }; - mockServer.config().get.mockImplementation(key => { return config[key]; }); @@ -67,9 +65,12 @@ test(`passes browserTimezone to generatePng`, async () => { const generatePngObservable = generatePngObservableFactory(); generatePngObservable.mockReturnValue(Rx.of(Buffer.from(''))); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, getMockLogger(), { - browserDriverFactory: {}, - }); + const executeJob = await executeJobFactory( + mockReporting, + mockServer, + mockElasticsearch, + getMockLogger() + ); const browserTimezone = 'UTC'; await executeJob( 'pngJobId', @@ -87,9 +88,15 @@ test(`passes browserTimezone to generatePng`, async () => { }); test(`returns content_type of application/png`, async () => { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, getMockLogger(), { - browserDriverFactory: {}, - }); + const executeJob = await executeJobFactory( + mockReporting, + mockServer, + mockElasticsearch, + getMockLogger(), + { + browserDriverFactory: {}, + } + ); const encryptedHeaders = await encryptHeaders({}); const generatePngObservable = generatePngObservableFactory(); @@ -109,9 +116,15 @@ test(`returns content of generatePng getBuffer base64 encoded`, async () => { const generatePngObservable = generatePngObservableFactory(); generatePngObservable.mockReturnValue(Rx.of(Buffer.from(testContent))); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, getMockLogger(), { - browserDriverFactory: {}, - }); + const executeJob = await executeJobFactory( + mockReporting, + mockServer, + mockElasticsearch, + getMockLogger(), + { + browserDriverFactory: {}, + } + ); const encryptedHeaders = await encryptHeaders({}); const { content } = await executeJob( 'pngJobId', diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts index c9f370197da66..5cde245080914 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts @@ -7,14 +7,9 @@ import * as Rx from 'rxjs'; import { ElasticsearchServiceSetup } from 'kibana/server'; import { catchError, map, mergeMap, takeUntil } from 'rxjs/operators'; +import { ReportingCore } from '../../../../server'; import { PNG_JOB_TYPE } from '../../../../common/constants'; -import { - ServerFacade, - ExecuteJobFactory, - ESQueueWorkerExecuteFn, - HeadlessChromiumDriverFactory, - Logger, -} from '../../../../types'; +import { ServerFacade, ExecuteJobFactory, ESQueueWorkerExecuteFn, Logger } from '../../../../types'; import { decryptJobHeaders, omitBlacklistedHeaders, @@ -26,12 +21,13 @@ import { generatePngObservableFactory } from '../lib/generate_png'; type QueuedPngExecutorFactory = ExecuteJobFactory>; -export const executeJobFactory: QueuedPngExecutorFactory = function executeJobFactoryFn( +export const executeJobFactory: QueuedPngExecutorFactory = async function executeJobFactoryFn( + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, - parentLogger: Logger, - { browserDriverFactory }: { browserDriverFactory: HeadlessChromiumDriverFactory } + parentLogger: Logger ) { + const browserDriverFactory = await reporting.getBrowserDriverFactory(); const generatePngObservable = generatePngObservableFactory(server, browserDriverFactory); const logger = parentLogger.clone([PNG_JOB_TYPE, 'execute']); diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/index.ts index a8cc71175cffe..656c99991e1f6 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/index.ts @@ -4,20 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ +import { validateUrls } from '../../../../common/validate_urls'; +import { ReportingCore } from '../../../../server'; +import { cryptoFactory } from '../../../../server/lib/crypto'; import { + ConditionalHeaders, CreateJobFactory, ESQueueCreateJobFn, - ServerFacade, RequestFacade, - ConditionalHeaders, + ServerFacade, } from '../../../../types'; -import { validateUrls } from '../../../../common/validate_urls'; -import { cryptoFactory } from '../../../../server/lib/crypto'; import { JobParamsPDF } from '../../types'; export const createJobFactory: CreateJobFactory> = function createJobFactoryFn(server: ServerFacade) { +>> = function createJobFactoryFn(reporting: ReportingCore, server: ServerFacade) { const crypto = cryptoFactory(server); return async function createJobFn( diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js index c21d39f4922cb..cc6b298bebdc5 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js @@ -6,6 +6,7 @@ import * as Rx from 'rxjs'; import { memoize } from 'lodash'; +import { createMockReportingCore } from '../../../../test_helpers'; import { cryptoFactory } from '../../../../server/lib/crypto'; import { executeJobFactory } from './index'; import { generatePdfObservableFactory } from '../lib/generate_pdf'; @@ -19,7 +20,11 @@ const cancellationToken = { let config; let mockServer; -beforeEach(() => { +let mockReporting; + +beforeEach(async () => { + mockReporting = await createMockReportingCore(); + config = { 'xpack.reporting.encryptionKey': 'testencryptionkey', 'server.basePath': '/sbp', @@ -27,18 +32,11 @@ beforeEach(() => { 'server.port': 5601, }; mockServer = { - expose: jest.fn(), - log: jest.fn(), config: memoize(() => ({ get: jest.fn() })), info: { protocol: 'http', }, - savedObjects: { - getScopedSavedObjectsClient: jest.fn(), - }, - uiSettingsServiceFactory: jest.fn().mockReturnValue({ get: jest.fn() }), }; - mockServer.config().get.mockImplementation(key => { return config[key]; }); @@ -60,38 +58,13 @@ const encryptHeaders = async headers => { return await crypto.encrypt(headers); }; -test(`passes browserTimezone to generatePdf`, async () => { - const encryptedHeaders = await encryptHeaders({}); - - const generatePdfObservable = generatePdfObservableFactory(); - generatePdfObservable.mockReturnValue(Rx.of(Buffer.from(''))); - - const executeJob = executeJobFactory(mockServer, mockElasticsearch, getMockLogger(), { - browserDriverFactory: {}, - }); - const browserTimezone = 'UTC'; - await executeJob( - 'pdfJobId', - { relativeUrls: [], browserTimezone, headers: encryptedHeaders }, - cancellationToken - ); - - expect(mockServer.uiSettingsServiceFactory().get).toBeCalledWith('xpackReporting:customPdfLogo'); - expect(generatePdfObservable).toBeCalledWith( - expect.any(LevelLogger), - undefined, - [], - browserTimezone, - expect.anything(), - undefined, - undefined - ); -}); - test(`returns content_type of application/pdf`, async () => { - const executeJob = executeJobFactory(mockServer, mockElasticsearch, getMockLogger(), { - browserDriverFactory: {}, - }); + const executeJob = await executeJobFactory( + mockReporting, + mockServer, + mockElasticsearch, + getMockLogger() + ); const encryptedHeaders = await encryptHeaders({}); const generatePdfObservable = generatePdfObservableFactory(); @@ -111,9 +84,12 @@ test(`returns content of generatePdf getBuffer base64 encoded`, async () => { const generatePdfObservable = generatePdfObservableFactory(); generatePdfObservable.mockReturnValue(Rx.of(Buffer.from(testContent))); - const executeJob = executeJobFactory(mockServer, mockElasticsearch, getMockLogger(), { - browserDriverFactory: {}, - }); + const executeJob = await executeJobFactory( + mockReporting, + mockServer, + mockElasticsearch, + getMockLogger() + ); const encryptedHeaders = await encryptHeaders({}); const { content } = await executeJob( 'pdfJobId', diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts index 162376e31216e..e8461862bee82 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts @@ -7,13 +7,8 @@ import * as Rx from 'rxjs'; import { ElasticsearchServiceSetup } from 'kibana/server'; import { catchError, map, mergeMap, takeUntil } from 'rxjs/operators'; -import { - ServerFacade, - ExecuteJobFactory, - ESQueueWorkerExecuteFn, - HeadlessChromiumDriverFactory, - Logger, -} from '../../../../types'; +import { ReportingCore } from '../../../../server'; +import { ServerFacade, ExecuteJobFactory, ESQueueWorkerExecuteFn, Logger } from '../../../../types'; import { JobDocPayloadPDF } from '../../types'; import { PDF_JOB_TYPE } from '../../../../common/constants'; import { generatePdfObservableFactory } from '../lib/generate_pdf'; @@ -27,12 +22,13 @@ import { type QueuedPdfExecutorFactory = ExecuteJobFactory>; -export const executeJobFactory: QueuedPdfExecutorFactory = function executeJobFactoryFn( +export const executeJobFactory: QueuedPdfExecutorFactory = async function executeJobFactoryFn( + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, - parentLogger: Logger, - { browserDriverFactory }: { browserDriverFactory: HeadlessChromiumDriverFactory } + parentLogger: Logger ) { + const browserDriverFactory = await reporting.getBrowserDriverFactory(); const generatePdfObservable = generatePdfObservableFactory(server, browserDriverFactory); const logger = parentLogger.clone([PDF_JOB_TYPE, 'execute']); @@ -43,7 +39,7 @@ export const executeJobFactory: QueuedPdfExecutorFactory = function executeJobFa mergeMap(() => decryptJobHeaders({ server, job, logger })), map(decryptedHeaders => omitBlacklistedHeaders({ job, decryptedHeaders })), map(filteredHeaders => getConditionalHeaders({ server, job, filteredHeaders })), - mergeMap(conditionalHeaders => getCustomLogo({ server, job, conditionalHeaders })), + mergeMap(conditionalHeaders => getCustomLogo({ reporting, server, job, conditionalHeaders })), mergeMap(({ logo, conditionalHeaders }) => { const urls = getFullUrls({ server, job }); diff --git a/x-pack/legacy/plugins/reporting/index.ts b/x-pack/legacy/plugins/reporting/index.ts index cbafc4b1ecc4b..9ce4e807f8ef8 100644 --- a/x-pack/legacy/plugins/reporting/index.ts +++ b/x-pack/legacy/plugins/reporting/index.ts @@ -10,7 +10,7 @@ import { resolve } from 'path'; import { PLUGIN_ID, UI_SETTINGS_CUSTOM_PDF_LOGO } from './common/constants'; import { config as reportingConfig } from './config'; import { legacyInit } from './server/legacy'; -import { ReportingConfigOptions, ReportingPluginSpecOptions } from './types.d'; +import { ReportingConfigOptions, ReportingPluginSpecOptions } from './types'; const kbToBase64Length = (kb: number) => { return Math.floor((kb * 1024 * 8) / 6); diff --git a/x-pack/legacy/plugins/reporting/reporting.d.ts b/x-pack/legacy/plugins/reporting/reporting.d.ts index d4a7943f6d067..ec65c15f53864 100644 --- a/x-pack/legacy/plugins/reporting/reporting.d.ts +++ b/x-pack/legacy/plugins/reporting/reporting.d.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { ReportingPlugin } from './types'; +export { ReportingPlugin } from './server/plugin'; diff --git a/x-pack/legacy/plugins/reporting/server/core.ts b/x-pack/legacy/plugins/reporting/server/core.ts new file mode 100644 index 0000000000000..4506d41e4f5c3 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/server/core.ts @@ -0,0 +1,122 @@ +/* + * 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 * as Rx from 'rxjs'; +import { first, mapTo } from 'rxjs/operators'; +import { + IUiSettingsClient, + KibanaRequest, + SavedObjectsClient, + SavedObjectsServiceStart, + UiSettingsServiceStart, +} from 'src/core/server'; +// @ts-ignore no module definition +import { mirrorPluginStatus } from '../../../server/lib/mirror_plugin_status'; +import { XPackMainPlugin } from '../../xpack_main/server/xpack_main'; +import { PLUGIN_ID } from '../common/constants'; +import { EnqueueJobFn, ESQueueInstance, ReportingPluginSpecOptions, ServerFacade } from '../types'; +import { HeadlessChromiumDriverFactory } from './browsers/chromium/driver_factory'; +import { checkLicenseFactory, getExportTypesRegistry, LevelLogger } from './lib'; +import { registerRoutes } from './routes'; +import { ReportingSetupDeps } from './types'; + +interface ReportingInternalSetup { + browserDriverFactory: HeadlessChromiumDriverFactory; +} +interface ReportingInternalStart { + savedObjects: SavedObjectsServiceStart; + uiSettings: UiSettingsServiceStart; + esqueue: ESQueueInstance; + enqueueJob: EnqueueJobFn; +} + +export class ReportingCore { + private pluginSetupDeps?: ReportingInternalSetup; + private pluginStartDeps?: ReportingInternalStart; + private readonly pluginSetup$ = new Rx.ReplaySubject(); + private readonly pluginStart$ = new Rx.ReplaySubject(); + private exportTypesRegistry = getExportTypesRegistry(); + + constructor(private logger: LevelLogger) {} + + legacySetup( + xpackMainPlugin: XPackMainPlugin, + reporting: ReportingPluginSpecOptions, + __LEGACY: ServerFacade, + plugins: ReportingSetupDeps + ) { + mirrorPluginStatus(xpackMainPlugin, reporting); + const checkLicense = checkLicenseFactory(this.exportTypesRegistry); + (xpackMainPlugin as any).status.once('green', () => { + // Register a function that is called whenever the xpack info changes, + // to re-compute the license check results for this plugin + xpackMainPlugin.info.feature(PLUGIN_ID).registerLicenseCheckResultsGenerator(checkLicense); + }); + // Reporting routes + registerRoutes(this, __LEGACY, plugins, this.logger); + } + + public pluginSetup(reportingSetupDeps: ReportingInternalSetup) { + this.pluginSetup$.next(reportingSetupDeps); + } + + public pluginStart(reportingStartDeps: ReportingInternalStart) { + this.pluginStart$.next(reportingStartDeps); + } + + public pluginHasStarted(): Promise { + return this.pluginStart$.pipe(first(), mapTo(true)).toPromise(); + } + + /* + * Internal module dependencies + */ + public getExportTypesRegistry() { + return this.exportTypesRegistry; + } + + public async getEsqueue(): Promise { + return (await this.getPluginStartDeps()).esqueue; + } + + public async getEnqueueJob(): Promise { + return (await this.getPluginStartDeps()).enqueueJob; + } + + public async getBrowserDriverFactory(): Promise { + return (await this.getPluginSetupDeps()).browserDriverFactory; + } + + /* + * Kibana core module dependencies + */ + private async getPluginSetupDeps() { + if (this.pluginSetupDeps) { + return this.pluginSetupDeps; + } + return await this.pluginSetup$.pipe(first()).toPromise(); + } + + private async getPluginStartDeps() { + if (this.pluginStartDeps) { + return this.pluginStartDeps; + } + return await this.pluginStart$.pipe(first()).toPromise(); + } + + public async getSavedObjectsClient(fakeRequest: KibanaRequest): Promise { + const { savedObjects } = await this.getPluginStartDeps(); + return savedObjects.getScopedClient(fakeRequest) as SavedObjectsClient; + } + + public async getUiSettingsServiceFactory( + savedObjectsClient: SavedObjectsClient + ): Promise { + const { uiSettings: uiSettingsService } = await this.getPluginStartDeps(); + const scopedUiSettingsService = uiSettingsService.asScopedToClient(savedObjectsClient); + return scopedUiSettingsService; + } +} diff --git a/x-pack/legacy/plugins/reporting/server/index.ts b/x-pack/legacy/plugins/reporting/server/index.ts index 438a3fd595a10..24e2a954415d9 100644 --- a/x-pack/legacy/plugins/reporting/server/index.ts +++ b/x-pack/legacy/plugins/reporting/server/index.ts @@ -10,3 +10,6 @@ import { ReportingPlugin as Plugin } from './plugin'; export const plugin = (context: PluginInitializerContext) => { return new Plugin(context); }; + +export { ReportingCore } from './core'; +export { ReportingPlugin } from './plugin'; diff --git a/x-pack/legacy/plugins/reporting/server/legacy.ts b/x-pack/legacy/plugins/reporting/server/legacy.ts index c80aef06cf270..336ff5f4d2ee7 100644 --- a/x-pack/legacy/plugins/reporting/server/legacy.ts +++ b/x-pack/legacy/plugins/reporting/server/legacy.ts @@ -8,7 +8,7 @@ import { PluginInitializerContext } from 'src/core/server'; import { SecurityPluginSetup } from '../../../../plugins/security/server'; import { ReportingPluginSpecOptions } from '../types'; import { plugin } from './index'; -import { LegacySetup, ReportingStartDeps } from './plugin'; +import { LegacySetup, ReportingStartDeps } from './types'; const buildLegacyDependencies = ( server: Legacy.Server, @@ -22,8 +22,6 @@ const buildLegacyDependencies = ( xpack_main: server.plugins.xpack_main, reporting: reportingPlugin, }, - savedObjects: server.savedObjects, - uiSettingsServiceFactory: server.uiSettingsServiceFactory, }); export const legacyInit = async ( @@ -33,17 +31,20 @@ export const legacyInit = async ( const coreSetup = server.newPlatform.setup.core; const pluginInstance = plugin(server.newPlatform.coreContext as PluginInitializerContext); + const __LEGACY = buildLegacyDependencies(server, reportingPlugin); await pluginInstance.setup(coreSetup, { elasticsearch: coreSetup.elasticsearch, security: server.newPlatform.setup.plugins.security as SecurityPluginSetup, usageCollection: server.newPlatform.setup.plugins.usageCollection, - __LEGACY: buildLegacyDependencies(server, reportingPlugin), + __LEGACY, }); // Schedule to call the "start" hook only after start dependencies are ready coreSetup.getStartServices().then(([core, plugins]) => pluginInstance.start(core, { + elasticsearch: coreSetup.elasticsearch, data: (plugins as ReportingStartDeps).data, + __LEGACY, }) ); }; diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts index c4e32b3ebcd99..d593e4625cdf4 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts @@ -5,29 +5,19 @@ */ import { ElasticsearchServiceSetup } from 'kibana/server'; -import { - ServerFacade, - ExportTypesRegistry, - HeadlessChromiumDriverFactory, - QueueConfig, - Logger, -} from '../../types'; +import { ESQueueInstance, ServerFacade, QueueConfig, Logger } from '../../types'; +import { ReportingCore } from '../core'; // @ts-ignore import { Esqueue } from './esqueue'; import { createWorkerFactory } from './create_worker'; import { createTaggedLogger } from './create_tagged_logger'; // TODO remove createTaggedLogger once esqueue is removed -interface CreateQueueFactoryOpts { - exportTypesRegistry: ExportTypesRegistry; - browserDriverFactory: HeadlessChromiumDriverFactory; -} - -export function createQueueFactory( +export async function createQueueFactory( + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, - logger: Logger, - { exportTypesRegistry, browserDriverFactory }: CreateQueueFactoryOpts -): Esqueue { + logger: Logger +): Promise { const queueConfig: QueueConfig = server.config().get('xpack.reporting.queue'); const index = server.config().get('xpack.reporting.index'); @@ -39,15 +29,12 @@ export function createQueueFactory( logger: createTaggedLogger(logger, ['esqueue', 'queue-worker']), }; - const queue: Esqueue = new Esqueue(index, queueOptions); + const queue: ESQueueInstance = new Esqueue(index, queueOptions); if (queueConfig.pollEnabled) { // create workers to poll the index for idle jobs waiting to be claimed and executed - const createWorker = createWorkerFactory(server, elasticsearch, logger, { - exportTypesRegistry, - browserDriverFactory, - }); - createWorker(queue); + const createWorker = createWorkerFactory(reporting, server, elasticsearch, logger); + await createWorker(queue); } else { logger.info( 'xpack.reporting.queue.pollEnabled is set to false. This Kibana instance ' + diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts index f5c42e5505cd1..d4d913243e18d 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts @@ -4,9 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import * as sinon from 'sinon'; import { ElasticsearchServiceSetup } from 'kibana/server'; -import { HeadlessChromiumDriverFactory, ServerFacade } from '../../types'; +import * as sinon from 'sinon'; +import { ReportingCore } from '../../server'; +import { createMockReportingCore } from '../../test_helpers'; +import { ServerFacade } from '../../types'; import { createWorkerFactory } from './create_worker'; // @ts-ignore import { Esqueue } from './esqueue'; @@ -33,34 +35,34 @@ const getMockLogger = jest.fn(); const getMockExportTypesRegistry = ( exportTypes: any[] = [{ executeJobFactory: executeJobFactoryStub }] -) => ({ - getAll: () => exportTypes, -}); +) => + ({ + getAll: () => exportTypes, + } as ExportTypesRegistry); describe('Create Worker', () => { let queue: Esqueue; let client: ClientMock; + let mockReporting: ReportingCore; - beforeEach(() => { + beforeEach(async () => { + mockReporting = await createMockReportingCore(); client = new ClientMock(); queue = new Esqueue('reporting-queue', { client }); executeJobFactoryStub.reset(); }); test('Creates a single Esqueue worker for Reporting', async () => { - const exportTypesRegistry = getMockExportTypesRegistry(); + mockReporting.getExportTypesRegistry = () => getMockExportTypesRegistry(); const createWorker = createWorkerFactory( + mockReporting, getMockServer(), {} as ElasticsearchServiceSetup, - getMockLogger(), - { - exportTypesRegistry: exportTypesRegistry as ExportTypesRegistry, - browserDriverFactory: {} as HeadlessChromiumDriverFactory, - } + getMockLogger() ); const registerWorkerSpy = sinon.spy(queue, 'registerWorker'); - createWorker(queue); + await createWorker(queue); sinon.assert.callCount(executeJobFactoryStub, 1); sinon.assert.callCount(registerWorkerSpy, 1); @@ -88,18 +90,16 @@ Object { { executeJobFactory: executeJobFactoryStub }, { executeJobFactory: executeJobFactoryStub }, ]); + mockReporting.getExportTypesRegistry = () => exportTypesRegistry; const createWorker = createWorkerFactory( + mockReporting, getMockServer(), {} as ElasticsearchServiceSetup, - getMockLogger(), - { - exportTypesRegistry: exportTypesRegistry as ExportTypesRegistry, - browserDriverFactory: {} as HeadlessChromiumDriverFactory, - } + getMockLogger() ); const registerWorkerSpy = sinon.spy(queue, 'registerWorker'); - createWorker(queue); + await createWorker(queue); sinon.assert.callCount(executeJobFactoryStub, 5); sinon.assert.callCount(registerWorkerSpy, 1); diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts index 2ca638f641291..3567712367608 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts @@ -5,34 +5,29 @@ */ import { ElasticsearchServiceSetup } from 'kibana/server'; -import { PLUGIN_ID } from '../../common/constants'; -import { ExportTypesRegistry, HeadlessChromiumDriverFactory } from '../../types'; import { CancellationToken } from '../../common/cancellation_token'; +import { PLUGIN_ID } from '../../common/constants'; import { ESQueueInstance, - QueueConfig, - ExportTypeDefinition, ESQueueWorkerExecuteFn, - JobDocPayload, + ExportTypeDefinition, ImmediateExecuteFn, + JobDocPayload, JobSource, + Logger, + QueueConfig, RequestFacade, ServerFacade, - Logger, } from '../../types'; +import { ReportingCore } from '../core'; // @ts-ignore untyped dependency import { events as esqueueEvents } from './esqueue'; -interface CreateWorkerFactoryOpts { - exportTypesRegistry: ExportTypesRegistry; - browserDriverFactory: HeadlessChromiumDriverFactory; -} - export function createWorkerFactory( + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, - logger: Logger, - { exportTypesRegistry, browserDriverFactory }: CreateWorkerFactoryOpts + logger: Logger ) { type JobDocPayloadType = JobDocPayload; const config = server.config(); @@ -41,20 +36,23 @@ export function createWorkerFactory( const kibanaId: string = config.get('server.uuid'); // Once more document types are added, this will need to be passed in - return function createWorker(queue: ESQueueInstance) { + return async function createWorker(queue: ESQueueInstance) { // export type / execute job map const jobExecutors: Map< string, ImmediateExecuteFn | ESQueueWorkerExecuteFn > = new Map(); - for (const exportType of exportTypesRegistry.getAll() as Array< - ExportTypeDefinition + for (const exportType of reporting.getExportTypesRegistry().getAll() as Array< + ExportTypeDefinition >) { // TODO: the executeJobFn should be unwrapped in the register method of the export types registry - const jobExecutor = exportType.executeJobFactory(server, elasticsearch, logger, { - browserDriverFactory, - }); + const jobExecutor = await exportType.executeJobFactory( + reporting, + server, + elasticsearch, + logger + ); jobExecutors.set(exportType.jobType, jobExecutor); } diff --git a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts index 1da8a3795aacc..c215bdc398904 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts @@ -16,11 +16,11 @@ import { ServerFacade, RequestFacade, Logger, - ExportTypesRegistry, CaptureConfig, QueueConfig, ConditionalHeaders, } from '../../types'; +import { ReportingCore } from '../core'; interface ConfirmedJob { id: string; @@ -29,16 +29,11 @@ interface ConfirmedJob { _primary_term: number; } -interface EnqueueJobFactoryOpts { - exportTypesRegistry: ExportTypesRegistry; - esqueue: any; -} - export function enqueueJobFactory( + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, - parentLogger: Logger, - { exportTypesRegistry, esqueue }: EnqueueJobFactoryOpts + parentLogger: Logger ): EnqueueJobFn { const logger = parentLogger.clone(['queue-job']); const config = server.config(); @@ -56,14 +51,20 @@ export function enqueueJobFactory( ): Promise { type CreateJobFn = ESQueueCreateJobFn | ImmediateCreateJobFn; - const exportType = exportTypesRegistry.getById(exportTypeId); + const esqueue = await reporting.getEsqueue(); + const exportType = reporting.getExportTypesRegistry().getById(exportTypeId); if (exportType == null) { throw new Error(`Export type ${exportTypeId} does not exist in the registry!`); } // TODO: the createJobFn should be unwrapped in the register method of the export types registry - const createJob = exportType.createJobFactory(server, elasticsearch, logger) as CreateJobFn; + const createJob = exportType.createJobFactory( + reporting, + server, + elasticsearch, + logger + ) as CreateJobFn; const payload = await createJob(jobParams, headers, request); const options = { diff --git a/x-pack/legacy/plugins/reporting/server/lib/get_user.ts b/x-pack/legacy/plugins/reporting/server/lib/get_user.ts index ab02dfe0743f0..49d5c568c3981 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/get_user.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/get_user.ts @@ -7,7 +7,7 @@ import { Legacy } from 'kibana'; import { KibanaRequest } from '../../../../../../src/core/server'; import { ServerFacade } from '../../types'; -import { ReportingSetupDeps } from '../plugin'; +import { ReportingSetupDeps } from '../types'; export function getUserFactory(server: ServerFacade, security: ReportingSetupDeps['security']) { /* diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts index 028d8fa143487..0fdbd858b8e3c 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts @@ -16,8 +16,8 @@ import { validateServerHost } from './validate_server_host'; export async function runValidations( server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, - logger: Logger, - browserFactory: HeadlessChromiumDriverFactory + browserFactory: HeadlessChromiumDriverFactory, + logger: Logger ) { try { await Promise.all([ @@ -32,6 +32,7 @@ export async function runValidations( }) ); } catch (err) { + logger.error(err); logger.warning( i18n.translate('xpack.reporting.selfCheck.warning', { defaultMessage: `Reporting plugin self-check generated a warning: {err}`, diff --git a/x-pack/legacy/plugins/reporting/server/plugin.ts b/x-pack/legacy/plugins/reporting/server/plugin.ts index ef7b01f8e9c15..4f24cc16b2277 100644 --- a/x-pack/legacy/plugins/reporting/server/plugin.ts +++ b/x-pack/legacy/plugins/reporting/server/plugin.ts @@ -4,97 +4,66 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Legacy } from 'kibana'; -import { - CoreSetup, - CoreStart, - ElasticsearchServiceSetup, - Plugin, - PluginInitializerContext, -} from 'src/core/server'; -import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { PluginStart as DataPluginStart } from '../../../../../src/plugins/data/server'; -import { SecurityPluginSetup } from '../../../../plugins/security/server'; -// @ts-ignore -import { mirrorPluginStatus } from '../../../server/lib/mirror_plugin_status'; -import { XPackMainPlugin } from '../../xpack_main/server/xpack_main'; -import { PLUGIN_ID } from '../common/constants'; +import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'src/core/server'; import { logConfiguration } from '../log_configuration'; -import { ReportingPluginSpecOptions } from '../types.d'; import { createBrowserDriverFactory } from './browsers'; -import { checkLicenseFactory, getExportTypesRegistry, LevelLogger, runValidations } from './lib'; -import { registerRoutes } from './routes'; +import { ReportingCore } from './core'; +import { createQueueFactory, enqueueJobFactory, LevelLogger, runValidations } from './lib'; import { setFieldFormats } from './services'; +import { ReportingSetup, ReportingSetupDeps, ReportingStart, ReportingStartDeps } from './types'; import { registerReportingUsageCollector } from './usage'; +// @ts-ignore no module definition +import { mirrorPluginStatus } from '../../../server/lib/mirror_plugin_status'; -export interface ReportingSetupDeps { - elasticsearch: ElasticsearchServiceSetup; - usageCollection: UsageCollectionSetup; - security: SecurityPluginSetup; - __LEGACY: LegacySetup; -} - -export interface ReportingStartDeps { - data: DataPluginStart; -} - -export interface LegacySetup { - config: Legacy.Server['config']; - info: Legacy.Server['info']; - plugins: { - elasticsearch: Legacy.Server['plugins']['elasticsearch']; - xpack_main: XPackMainPlugin & { - status?: any; - }; - reporting: ReportingPluginSpecOptions; - }; - route: Legacy.Server['route']; - savedObjects: Legacy.Server['savedObjects']; - uiSettingsServiceFactory: Legacy.Server['uiSettingsServiceFactory']; -} +export class ReportingPlugin + implements Plugin { + private logger: LevelLogger; + private reportingCore: ReportingCore; -export class ReportingPlugin implements Plugin { - constructor(private context: PluginInitializerContext) {} + constructor(context: PluginInitializerContext) { + this.logger = new LevelLogger(context.logger.get('reporting')); + this.reportingCore = new ReportingCore(this.logger); + } public async setup(core: CoreSetup, plugins: ReportingSetupDeps) { const { elasticsearch, usageCollection, __LEGACY } = plugins; - const exportTypesRegistry = getExportTypesRegistry(); - let isCollectorReady = false; + const browserDriverFactory = await createBrowserDriverFactory(__LEGACY, this.logger); // required for validations :( + runValidations(__LEGACY, elasticsearch, browserDriverFactory, this.logger); // this must run early, as it sets up config defaults + + const { xpack_main: xpackMainLegacy, reporting: reportingLegacy } = __LEGACY.plugins; + this.reportingCore.legacySetup(xpackMainLegacy, reportingLegacy, __LEGACY, plugins); // Register a function with server to manage the collection of usage stats - registerReportingUsageCollector( - usageCollection, - __LEGACY, - () => isCollectorReady, - exportTypesRegistry - ); + registerReportingUsageCollector(this.reportingCore, __LEGACY, usageCollection); - const logger = new LevelLogger(this.context.logger.get('reporting')); - const browserDriverFactory = await createBrowserDriverFactory(__LEGACY, logger); + // regsister setup internals + this.reportingCore.pluginSetup({ browserDriverFactory }); - logConfiguration(__LEGACY, logger); - runValidations(__LEGACY, elasticsearch, logger, browserDriverFactory); + return {}; + } - const { xpack_main: xpackMainPlugin, reporting } = __LEGACY.plugins; - mirrorPluginStatus(xpackMainPlugin, reporting); + public async start(core: CoreStart, plugins: ReportingStartDeps) { + const { reportingCore, logger } = this; + const { elasticsearch, __LEGACY } = plugins; - const checkLicense = checkLicenseFactory(exportTypesRegistry); + const esqueue = await createQueueFactory(reportingCore, __LEGACY, elasticsearch, logger); + const enqueueJob = enqueueJobFactory(reportingCore, __LEGACY, elasticsearch, logger); - (xpackMainPlugin as any).status.once('green', () => { - // Register a function that is called whenever the xpack info changes, - // to re-compute the license check results for this plugin - xpackMainPlugin.info.feature(PLUGIN_ID).registerLicenseCheckResultsGenerator(checkLicense); + this.reportingCore.pluginStart({ + savedObjects: core.savedObjects, + uiSettings: core.uiSettings, + esqueue, + enqueueJob, }); - // Post initialization of the above code, the collector is now ready to fetch its data - isCollectorReady = true; + setFieldFormats(plugins.data.fieldFormats); + logConfiguration(__LEGACY, this.logger); - // Reporting routes - registerRoutes(__LEGACY, plugins, exportTypesRegistry, browserDriverFactory, logger); + return {}; } - public start(core: CoreStart, plugins: ReportingStartDeps) { - setFieldFormats(plugins.data.fieldFormats); + public getReportingCore() { + return this.reportingCore; } } diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts index ed761b1e684ae..49868bb7ad5d5 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts @@ -10,7 +10,7 @@ import { Legacy } from 'kibana'; import rison from 'rison-node'; import { API_BASE_URL } from '../../common/constants'; import { Logger, ReportingResponseToolkit, ServerFacade } from '../../types'; -import { ReportingSetupDeps } from '../plugin'; +import { ReportingSetupDeps } from '../types'; import { makeRequestFacade } from './lib/make_request_facade'; import { GetRouteConfigFactoryFn, diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts index 8696f36a45c62..415b6b7d64366 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts @@ -9,7 +9,7 @@ import { get } from 'lodash'; import { API_BASE_GENERATE_V1, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../common/constants'; import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject/server/lib/get_job_params_from_request'; import { Logger, ReportingResponseToolkit, ServerFacade } from '../../types'; -import { ReportingSetupDeps } from '../plugin'; +import { ReportingSetupDeps } from '../types'; import { makeRequestFacade } from './lib/make_request_facade'; import { getRouteOptionsCsv } from './lib/route_config_factories'; import { HandlerErrorFunction, HandlerFunction, QueuedJobPayload } from './types'; diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts index fd1d85fef0f21..5d17fa2e82b8c 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts @@ -10,14 +10,13 @@ import { createJobFactory, executeJobFactory } from '../../export_types/csv_from import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject/server/lib/get_job_params_from_request'; import { JobDocPayloadPanelCsv } from '../../export_types/csv_from_savedobject/types'; import { - HeadlessChromiumDriverFactory, JobDocOutput, Logger, ReportingResponseToolkit, ResponseFacade, ServerFacade, } from '../../types'; -import { ReportingSetupDeps } from '../plugin'; +import { ReportingSetupDeps, ReportingCore } from '../types'; import { makeRequestFacade } from './lib/make_request_facade'; import { getRouteOptionsCsv } from './lib/route_config_factories'; @@ -31,6 +30,7 @@ import { getRouteOptionsCsv } from './lib/route_config_factories'; * - local (transient) changes the user made to the saved object */ export function registerGenerateCsvFromSavedObjectImmediate( + reporting: ReportingCore, server: ServerFacade, plugins: ReportingSetupDeps, parentLogger: Logger @@ -58,10 +58,8 @@ export function registerGenerateCsvFromSavedObjectImmediate( * * Calling an execute job factory requires passing a browserDriverFactory option, so we should not call the factory from here */ - const createJobFn = createJobFactory(server, elasticsearch, logger); - const executeJobFn = executeJobFactory(server, elasticsearch, logger, { - browserDriverFactory: {} as HeadlessChromiumDriverFactory, - }); + const createJobFn = createJobFactory(reporting, server, elasticsearch, logger); + const executeJobFn = await executeJobFactory(reporting, server, elasticsearch, logger); const jobDocPayload: JobDocPayloadPanelCsv = await createJobFn( jobParams, request.headers, diff --git a/x-pack/legacy/plugins/reporting/server/routes/generation.ts b/x-pack/legacy/plugins/reporting/server/routes/generation.ts index 02a9541484bc6..096ba84b63d1a 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generation.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generation.ts @@ -8,15 +8,8 @@ import boom from 'boom'; import { errors as elasticsearchErrors } from 'elasticsearch'; import { Legacy } from 'kibana'; import { API_BASE_URL } from '../../common/constants'; -import { - ExportTypesRegistry, - HeadlessChromiumDriverFactory, - Logger, - ReportingResponseToolkit, - ServerFacade, -} from '../../types'; -import { createQueueFactory, enqueueJobFactory } from '../lib'; -import { ReportingSetupDeps } from '../plugin'; +import { Logger, ReportingResponseToolkit, ServerFacade } from '../../types'; +import { ReportingSetupDeps, ReportingCore } from '../types'; import { registerGenerateFromJobParams } from './generate_from_jobparams'; import { registerGenerateCsvFromSavedObject } from './generate_from_savedobject'; import { registerGenerateCsvFromSavedObjectImmediate } from './generate_from_savedobject_immediate'; @@ -25,23 +18,13 @@ import { makeRequestFacade } from './lib/make_request_facade'; const esErrors = elasticsearchErrors as Record; export function registerJobGenerationRoutes( + reporting: ReportingCore, server: ServerFacade, plugins: ReportingSetupDeps, - exportTypesRegistry: ExportTypesRegistry, - browserDriverFactory: HeadlessChromiumDriverFactory, logger: Logger ) { const config = server.config(); const DOWNLOAD_BASE_URL = config.get('server.basePath') + `${API_BASE_URL}/jobs/download`; - const { elasticsearch } = plugins; - const esqueue = createQueueFactory(server, elasticsearch, logger, { - exportTypesRegistry, - browserDriverFactory, - }); - const enqueueJob = enqueueJobFactory(server, elasticsearch, logger, { - exportTypesRegistry, - esqueue, - }); /* * Generates enqueued job details to use in responses @@ -56,6 +39,7 @@ export function registerJobGenerationRoutes( const user = request.pre.user; const headers = request.headers; + const enqueueJob = await reporting.getEnqueueJob(); const job = await enqueueJob(exportTypeId, jobParams, user, headers, request); // return the queue's job information @@ -87,6 +71,6 @@ export function registerJobGenerationRoutes( // Register beta panel-action download-related API's if (config.get('xpack.reporting.csv.enablePanelActionDownload')) { registerGenerateCsvFromSavedObject(server, plugins, handler, handleError, logger); - registerGenerateCsvFromSavedObjectImmediate(server, plugins, logger); + registerGenerateCsvFromSavedObjectImmediate(reporting, server, plugins, logger); } } diff --git a/x-pack/legacy/plugins/reporting/server/routes/index.ts b/x-pack/legacy/plugins/reporting/server/routes/index.ts index 4cfa9dd465eab..610ab4907d369 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/index.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/index.ts @@ -4,23 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - ExportTypesRegistry, - HeadlessChromiumDriverFactory, - Logger, - ServerFacade, -} from '../../types'; -import { ReportingSetupDeps } from '../plugin'; +import { Logger, ServerFacade } from '../../types'; +import { ReportingCore, ReportingSetupDeps } from '../types'; import { registerJobGenerationRoutes } from './generation'; import { registerJobInfoRoutes } from './jobs'; export function registerRoutes( + reporting: ReportingCore, server: ServerFacade, plugins: ReportingSetupDeps, - exportTypesRegistry: ExportTypesRegistry, - browserDriverFactory: HeadlessChromiumDriverFactory, logger: Logger ) { - registerJobGenerationRoutes(server, plugins, exportTypesRegistry, browserDriverFactory, logger); - registerJobInfoRoutes(server, plugins, exportTypesRegistry, logger); + registerJobGenerationRoutes(reporting, server, plugins, logger); + registerJobInfoRoutes(reporting, server, plugins, logger); } diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js b/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js index 811c81c502b81..071b401d2321b 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js @@ -5,30 +5,30 @@ */ import Hapi from 'hapi'; -import { difference, memoize } from 'lodash'; -import { registerJobInfoRoutes } from './jobs'; +import { memoize } from 'lodash'; +import { createMockReportingCore } from '../../test_helpers'; import { ExportTypesRegistry } from '../lib/export_types_registry'; -jest.mock('./lib/authorized_user_pre_routing', () => { - return { - authorizedUserPreRoutingFactory: () => () => ({}), - }; -}); -jest.mock('./lib/reporting_feature_pre_routing', () => { - return { - reportingFeaturePreRoutingFactory: () => () => () => ({ - jobTypes: ['unencodedJobType', 'base64EncodedJobType'], - }), - }; -}); + +jest.mock('./lib/authorized_user_pre_routing', () => ({ + authorizedUserPreRoutingFactory: () => () => ({}), +})); +jest.mock('./lib/reporting_feature_pre_routing', () => ({ + reportingFeaturePreRoutingFactory: () => () => () => ({ + jobTypes: ['unencodedJobType', 'base64EncodedJobType'], + }), +})); + +import { registerJobInfoRoutes } from './jobs'; let mockServer; let exportTypesRegistry; +let mockReportingPlugin; const mockLogger = { error: jest.fn(), debug: jest.fn(), }; -beforeEach(() => { +beforeEach(async () => { mockServer = new Hapi.Server({ debug: false, port: 8080, routes: { log: { collect: true } } }); mockServer.config = memoize(() => ({ get: jest.fn() })); exportTypesRegistry = new ExportTypesRegistry(); @@ -43,6 +43,8 @@ beforeEach(() => { jobContentEncoding: 'base64', jobContentExtension: 'pdf', }); + mockReportingPlugin = await createMockReportingCore(); + mockReportingPlugin.getExportTypesRegistry = () => exportTypesRegistry; }); const mockPlugins = { @@ -60,12 +62,15 @@ const getHits = (...sources) => { }; }; +const getErrorsFromRequest = request => + request.logs.filter(log => log.tags.includes('error')).map(log => log.error); + test(`returns 404 if job not found`, async () => { mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(getHits())), }; - registerJobInfoRoutes(mockServer, mockPlugins, exportTypesRegistry, mockLogger); + registerJobInfoRoutes(mockReportingPlugin, mockServer, mockPlugins, mockLogger); const request = { method: 'GET', @@ -84,7 +89,7 @@ test(`returns 401 if not valid job type`, async () => { .mockReturnValue(Promise.resolve(getHits({ jobtype: 'invalidJobType' }))), }; - registerJobInfoRoutes(mockServer, mockPlugins, exportTypesRegistry, mockLogger); + registerJobInfoRoutes(mockReportingPlugin, mockServer, mockPlugins, mockLogger); const request = { method: 'GET', @@ -105,7 +110,7 @@ describe(`when job is incomplete`, () => { ), }; - registerJobInfoRoutes(mockServer, mockPlugins, exportTypesRegistry, mockLogger); + registerJobInfoRoutes(mockReportingPlugin, mockServer, mockPlugins, mockLogger); const request = { method: 'GET', @@ -147,7 +152,7 @@ describe(`when job is failed`, () => { callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(hits)), }; - registerJobInfoRoutes(mockServer, mockPlugins, exportTypesRegistry, mockLogger); + registerJobInfoRoutes(mockReportingPlugin, mockServer, mockPlugins, mockLogger); const request = { method: 'GET', @@ -192,7 +197,7 @@ describe(`when job is completed`, () => { callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(hits)), }; - registerJobInfoRoutes(mockServer, mockPlugins, exportTypesRegistry, mockLogger); + registerJobInfoRoutes(mockReportingPlugin, mockServer, mockPlugins, mockLogger); const request = { method: 'GET', @@ -203,72 +208,115 @@ describe(`when job is completed`, () => { }; test(`sets statusCode to 200`, async () => { - const { statusCode } = await getCompletedResponse(); + const { statusCode, request } = await getCompletedResponse(); + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toEqual([]); expect(statusCode).toBe(200); }); test(`doesn't encode output content for not-specified jobTypes`, async () => { - const { payload } = await getCompletedResponse({ + const { payload, request } = await getCompletedResponse({ jobType: 'unencodedJobType', outputContent: 'test', }); + + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toEqual([]); + expect(payload).toBe('test'); }); test(`base64 encodes output content for configured jobTypes`, async () => { - const { payload } = await getCompletedResponse({ + const { payload, request } = await getCompletedResponse({ jobType: 'base64EncodedJobType', outputContent: 'test', }); + + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toEqual([]); + expect(payload).toBe(Buffer.from('test', 'base64').toString()); }); test(`specifies text/csv; charset=utf-8 contentType header from the job output`, async () => { - const { headers } = await getCompletedResponse({ outputContentType: 'text/csv' }); + const { headers, request } = await getCompletedResponse({ outputContentType: 'text/csv' }); + + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toEqual([]); + expect(headers['content-type']).toBe('text/csv; charset=utf-8'); }); test(`specifies default filename in content-disposition header if no title`, async () => { - const { headers } = await getCompletedResponse({}); + const { headers, request } = await getCompletedResponse({}); + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toEqual([]); expect(headers['content-disposition']).toBe('inline; filename="report.csv"'); }); test(`specifies payload title in content-disposition header`, async () => { - const { headers } = await getCompletedResponse({ title: 'something' }); + const { headers, request } = await getCompletedResponse({ title: 'something' }); + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toEqual([]); expect(headers['content-disposition']).toBe('inline; filename="something.csv"'); }); test(`specifies jobContentExtension in content-disposition header`, async () => { - const { headers } = await getCompletedResponse({ jobType: 'base64EncodedJobType' }); + const { headers, request } = await getCompletedResponse({ jobType: 'base64EncodedJobType' }); + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toEqual([]); expect(headers['content-disposition']).toBe('inline; filename="report.pdf"'); }); test(`specifies application/pdf contentType header from the job output`, async () => { - const { headers } = await getCompletedResponse({ outputContentType: 'application/pdf' }); + const { headers, request } = await getCompletedResponse({ + outputContentType: 'application/pdf', + }); + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toEqual([]); expect(headers['content-type']).toBe('application/pdf'); }); describe(`when non-whitelisted contentType specified in job output`, () => { test(`sets statusCode to 500`, async () => { - const { statusCode } = await getCompletedResponse({ outputContentType: 'application/html' }); + const { statusCode, request } = await getCompletedResponse({ + outputContentType: 'application/html', + }); + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toMatchInlineSnapshot(` + Array [ + [Error: Unsupported content-type of application/html specified by job output], + [Error: Unsupported content-type of application/html specified by job output], + ] + `); expect(statusCode).toBe(500); }); test(`doesn't include job output content in payload`, async () => { - const { payload } = await getCompletedResponse({ outputContentType: 'application/html' }); - expect(payload).not.toMatch(/job output content/); + const { payload, request } = await getCompletedResponse({ + outputContentType: 'application/html', + }); + expect(payload).toMatchInlineSnapshot( + `"{\\"statusCode\\":500,\\"error\\":\\"Internal Server Error\\",\\"message\\":\\"An internal server error occurred\\"}"` + ); + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toMatchInlineSnapshot(` + Array [ + [Error: Unsupported content-type of application/html specified by job output], + [Error: Unsupported content-type of application/html specified by job output], + ] + `); }); test(`logs error message about invalid content type`, async () => { - const { - request: { logs }, - } = await getCompletedResponse({ outputContentType: 'application/html' }); - const errorLogs = logs.filter( - log => difference(['internal', 'implementation', 'error'], log.tags).length === 0 - ); - expect(errorLogs).toHaveLength(1); - expect(errorLogs[0].error).toBeInstanceOf(Error); - expect(errorLogs[0].error.message).toMatch(/Unsupported content-type of application\/html/); + const { request } = await getCompletedResponse({ outputContentType: 'application/html' }); + const errorLogs = getErrorsFromRequest(request); + expect(errorLogs).toMatchInlineSnapshot(` + Array [ + [Error: Unsupported content-type of application/html specified by job output], + [Error: Unsupported content-type of application/html specified by job output], + ] + `); }); }); }); diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts index daabc2cf22f4e..2de420e6577c3 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts @@ -9,7 +9,6 @@ import { ResponseObject } from 'hapi'; import { Legacy } from 'kibana'; import { API_BASE_URL } from '../../common/constants'; import { - ExportTypesRegistry, JobDocOutput, JobSource, ListQuery, @@ -18,7 +17,7 @@ import { ServerFacade, } from '../../types'; import { jobsQueryFactory } from '../lib/jobs_query'; -import { ReportingSetupDeps } from '../plugin'; +import { ReportingSetupDeps, ReportingCore } from '../types'; import { jobResponseHandlerFactory } from './lib/job_response_handler'; import { makeRequestFacade } from './lib/make_request_facade'; import { @@ -33,9 +32,9 @@ function isResponse(response: Boom | ResponseObject): response is Response } export function registerJobInfoRoutes( + reporting: ReportingCore, server: ServerFacade, plugins: ReportingSetupDeps, - exportTypesRegistry: ExportTypesRegistry, logger: Logger ) { const { elasticsearch } = plugins; @@ -138,6 +137,7 @@ export function registerJobInfoRoutes( }); // trigger a download of the output from a job + const exportTypesRegistry = reporting.getExportTypesRegistry(); const jobResponseHandler = jobResponseHandlerFactory(server, elasticsearch, exportTypesRegistry); server.route({ path: `${MAIN_ENTRY}/download/{docId}`, diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts index 57c3fcee222da..c5f8c78016f61 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts @@ -9,7 +9,7 @@ import { Legacy } from 'kibana'; import { AuthenticatedUser } from '../../../../../../plugins/security/server'; import { Logger, ServerFacade } from '../../../types'; import { getUserFactory } from '../../lib/get_user'; -import { ReportingSetupDeps } from '../../plugin'; +import { ReportingSetupDeps } from '../../types'; const superuserRole = 'superuser'; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts index 7367fceb50857..9e618ff1fe40a 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts @@ -7,7 +7,7 @@ import Boom from 'boom'; import { Legacy } from 'kibana'; import { Logger, ServerFacade } from '../../../types'; -import { ReportingSetupDeps } from '../../plugin'; +import { ReportingSetupDeps } from '../../types'; export type GetReportingFeatureIdFn = (request: Legacy.Request) => string; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts index 931f642397bf8..82ba9ba22c706 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts @@ -7,7 +7,7 @@ import Joi from 'joi'; import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; import { Logger, ServerFacade } from '../../../types'; -import { ReportingSetupDeps } from '../../plugin'; +import { ReportingSetupDeps } from '../../types'; import { authorizedUserPreRoutingFactory } from './authorized_user_pre_routing'; import { GetReportingFeatureIdFn, diff --git a/x-pack/legacy/plugins/reporting/server/types.d.ts b/x-pack/legacy/plugins/reporting/server/types.d.ts new file mode 100644 index 0000000000000..20673423aa448 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/server/types.d.ts @@ -0,0 +1,50 @@ +/* + * 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 { Legacy } from 'kibana'; +import { + ElasticsearchServiceSetup, + SavedObjectsServiceStart, + UiSettingsServiceStart, +} from 'src/core/server'; +import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { PluginStart as DataPluginStart } from '../../../../../src/plugins/data/server'; +import { SecurityPluginSetup } from '../../../../plugins/security/server'; +import { XPackMainPlugin } from '../../xpack_main/server/xpack_main'; +import { EnqueueJobFn, ESQueueInstance, ReportingPluginSpecOptions } from '../types'; +import { HeadlessChromiumDriverFactory } from './browsers/chromium/driver_factory'; + +export interface ReportingSetupDeps { + elasticsearch: ElasticsearchServiceSetup; + security: SecurityPluginSetup; + usageCollection: UsageCollectionSetup; + __LEGACY: LegacySetup; +} + +export interface ReportingStartDeps { + elasticsearch: ElasticsearchServiceSetup; + data: DataPluginStart; + __LEGACY: LegacySetup; +} + +export type ReportingSetup = object; + +export type ReportingStart = object; + +export interface LegacySetup { + config: Legacy.Server['config']; + info: Legacy.Server['info']; + plugins: { + elasticsearch: Legacy.Server['plugins']['elasticsearch']; + xpack_main: XPackMainPlugin & { + status?: any; + }; + reporting: ReportingPluginSpecOptions; + }; + route: Legacy.Server['route']; +} + +export { ReportingCore } from './core'; diff --git a/x-pack/legacy/plugins/reporting/server/usage/decorate_range_stats.ts b/x-pack/legacy/plugins/reporting/server/usage/decorate_range_stats.ts index 0118dea38d985..359bcc45230c3 100644 --- a/x-pack/legacy/plugins/reporting/server/usage/decorate_range_stats.ts +++ b/x-pack/legacy/plugins/reporting/server/usage/decorate_range_stats.ts @@ -6,7 +6,7 @@ import { uniq } from 'lodash'; import { CSV_JOB_TYPE, PDF_JOB_TYPE, PNG_JOB_TYPE } from '../../common/constants'; -import { AvailableTotal, FeatureAvailabilityMap, RangeStats, ExportType } from './types.d'; +import { AvailableTotal, FeatureAvailabilityMap, RangeStats, ExportType } from './types'; function getForFeature( range: Partial, diff --git a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js index f761f0d2d270b..a6d753f9b107a 100644 --- a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js +++ b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js @@ -3,9 +3,14 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import sinon from 'sinon'; +import { createMockReportingCore } from '../../test_helpers'; import { getExportTypesRegistry } from '../lib/export_types_registry'; -import { getReportingUsageCollector } from './reporting_usage_collector'; +import { + registerReportingUsageCollector, + getReportingUsageCollector, +} from './reporting_usage_collector'; const exportTypesRegistry = getExportTypesRegistry(); @@ -70,9 +75,8 @@ describe('license checks', () => { const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock())); const usageCollection = getMockUsageCollection(); const { fetch: getReportingUsage } = getReportingUsageCollector( - usageCollection, serverWithBasicLicenseMock, - () => {}, + usageCollection, exportTypesRegistry ); usageStats = await getReportingUsage(callClusterMock, exportTypesRegistry); @@ -101,9 +105,8 @@ describe('license checks', () => { const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock())); const usageCollection = getMockUsageCollection(); const { fetch: getReportingUsage } = getReportingUsageCollector( - usageCollection, serverWithNoLicenseMock, - () => {}, + usageCollection, exportTypesRegistry ); usageStats = await getReportingUsage(callClusterMock, exportTypesRegistry); @@ -132,9 +135,8 @@ describe('license checks', () => { const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock())); const usageCollection = getMockUsageCollection(); const { fetch: getReportingUsage } = getReportingUsageCollector( - usageCollection, serverWithPlatinumLicenseMock, - () => {}, + usageCollection, exportTypesRegistry ); usageStats = await getReportingUsage(callClusterMock, exportTypesRegistry); @@ -163,9 +165,8 @@ describe('license checks', () => { const callClusterMock = jest.fn(() => Promise.resolve({})); const usageCollection = getMockUsageCollection(); const { fetch: getReportingUsage } = getReportingUsageCollector( - usageCollection, serverWithBasicLicenseMock, - () => {}, + usageCollection, exportTypesRegistry ); usageStats = await getReportingUsage(callClusterMock, exportTypesRegistry); @@ -190,9 +191,8 @@ describe('data modeling', () => { .stub() .returns('platinum'); ({ fetch: getReportingUsage } = getReportingUsageCollector( - usageCollection, serverWithPlatinumLicenseMock, - () => {}, + usageCollection, exportTypesRegistry )); }); @@ -322,94 +322,124 @@ describe('data modeling', () => { const usageStats = await getReportingUsage(callClusterMock); expect(usageStats).toMatchInlineSnapshot(` -Object { - "PNG": Object { - "available": true, - "total": 4, - }, - "_all": 54, - "available": true, - "browser_type": undefined, - "csv": Object { - "available": true, - "total": 27, - }, - "enabled": true, - "last7Days": Object { - "PNG": Object { - "available": true, - "total": 4, - }, - "_all": 27, - "csv": Object { - "available": true, - "total": 10, - }, - "printable_pdf": Object { - "app": Object { - "dashboard": 13, - "visualization": 0, - }, - "available": true, - "layout": Object { - "preserve_layout": 3, - "print": 10, - }, - "total": 13, - }, - "status": Object { - "completed": 0, - "failed": 0, - "pending": 27, - }, - }, - "lastDay": Object { - "PNG": Object { - "available": true, - "total": 4, - }, - "_all": 11, - "csv": Object { - "available": true, - "total": 5, - }, - "printable_pdf": Object { - "app": Object { - "dashboard": 2, - "visualization": 0, - }, - "available": true, - "layout": Object { - "preserve_layout": 0, - "print": 2, - }, - "total": 2, - }, - "status": Object { - "completed": 0, - "failed": 0, - "pending": 11, - }, - }, - "printable_pdf": Object { - "app": Object { - "dashboard": 23, - "visualization": 0, - }, - "available": true, - "layout": Object { - "preserve_layout": 13, - "print": 10, - }, - "total": 23, - }, - "status": Object { - "completed": 20, - "failed": 0, - "pending": 33, - "processing": 1, - }, -} -`); + Object { + "PNG": Object { + "available": true, + "total": 4, + }, + "_all": 54, + "available": true, + "browser_type": undefined, + "csv": Object { + "available": true, + "total": 27, + }, + "enabled": true, + "last7Days": Object { + "PNG": Object { + "available": true, + "total": 4, + }, + "_all": 27, + "csv": Object { + "available": true, + "total": 10, + }, + "printable_pdf": Object { + "app": Object { + "dashboard": 13, + "visualization": 0, + }, + "available": true, + "layout": Object { + "preserve_layout": 3, + "print": 10, + }, + "total": 13, + }, + "status": Object { + "completed": 0, + "failed": 0, + "pending": 27, + }, + }, + "lastDay": Object { + "PNG": Object { + "available": true, + "total": 4, + }, + "_all": 11, + "csv": Object { + "available": true, + "total": 5, + }, + "printable_pdf": Object { + "app": Object { + "dashboard": 2, + "visualization": 0, + }, + "available": true, + "layout": Object { + "preserve_layout": 0, + "print": 2, + }, + "total": 2, + }, + "status": Object { + "completed": 0, + "failed": 0, + "pending": 11, + }, + }, + "printable_pdf": Object { + "app": Object { + "dashboard": 23, + "visualization": 0, + }, + "available": true, + "layout": Object { + "preserve_layout": 13, + "print": 10, + }, + "total": 23, + }, + "status": Object { + "completed": 20, + "failed": 0, + "pending": 33, + "processing": 1, + }, + } + `); + }); +}); + +describe('Ready for collection observable', () => { + let mockReporting; + + beforeEach(async () => { + mockReporting = await createMockReportingCore(); + }); + + test('converts observable to promise', async () => { + const serverWithBasicLicenseMock = getServerMock(); + const makeCollectorSpy = sinon.spy(); + const usageCollection = { + makeUsageCollector: makeCollectorSpy, + registerCollector: sinon.stub(), + }; + registerReportingUsageCollector(mockReporting, serverWithBasicLicenseMock, usageCollection); + + const [args] = makeCollectorSpy.firstCall.args; + expect(args).toMatchInlineSnapshot(` + Object { + "fetch": [Function], + "formatForBulkUpload": [Function], + "isReady": [Function], + "type": "reporting", + } + `); + + await expect(args.isReady()).resolves.toBe(true); }); }); diff --git a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.ts b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.ts index 567838391d2e7..14202530fb6c7 100644 --- a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.ts +++ b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.ts @@ -5,8 +5,9 @@ */ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { ServerFacade, ExportTypesRegistry, ESCallCluster } from '../../types'; import { KIBANA_REPORTING_TYPE } from '../../common/constants'; +import { ReportingCore } from '../../server'; +import { ESCallCluster, ExportTypesRegistry, ServerFacade } from '../../types'; import { getReportingUsage } from './get_reporting_usage'; import { RangeStats } from './types'; @@ -18,16 +19,16 @@ const METATYPE = 'kibana_stats'; * @return {Object} kibana usage stats type collection object */ export function getReportingUsageCollector( - usageCollection: UsageCollectionSetup, server: ServerFacade, - isReady: () => boolean, - exportTypesRegistry: ExportTypesRegistry + usageCollection: UsageCollectionSetup, + exportTypesRegistry: ExportTypesRegistry, + isReady: () => Promise ) { return usageCollection.makeUsageCollector({ type: KIBANA_REPORTING_TYPE, - isReady, fetch: (callCluster: ESCallCluster) => getReportingUsage(server, callCluster, exportTypesRegistry), + isReady, /* * Format the response data into a model for internal upload @@ -50,16 +51,18 @@ export function getReportingUsageCollector( } export function registerReportingUsageCollector( - usageCollection: UsageCollectionSetup, + reporting: ReportingCore, server: ServerFacade, - isReady: () => boolean, - exportTypesRegistry: ExportTypesRegistry + usageCollection: UsageCollectionSetup ) { + const exportTypesRegistry = reporting.getExportTypesRegistry(); + const collectionIsReady = reporting.pluginHasStarted.bind(reporting); + const collector = getReportingUsageCollector( - usageCollection, server, - isReady, - exportTypesRegistry + usageCollection, + exportTypesRegistry, + collectionIsReady ); usageCollection.registerCollector(collector); } diff --git a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_reportingplugin.ts b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_reportingplugin.ts new file mode 100644 index 0000000000000..2cd129d47b3f9 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_reportingplugin.ts @@ -0,0 +1,53 @@ +/* + * 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. + */ + +jest.mock('../server/routes'); +jest.mock('../server/usage'); +jest.mock('../server/browsers'); +jest.mock('../server/browsers'); +jest.mock('../server/lib/create_queue'); +jest.mock('../server/lib/enqueue_job'); +jest.mock('../server/lib/validate'); +jest.mock('../log_configuration'); + +import { EventEmitter } from 'events'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { coreMock } from 'src/core/server/mocks'; +import { ReportingPlugin, ReportingCore } from '../server'; +import { ReportingSetupDeps, ReportingStartDeps } from '../server/types'; + +export const createMockSetupDeps = (setupMock?: any): ReportingSetupDeps => ({ + elasticsearch: setupMock.elasticsearch, + security: setupMock.security, + usageCollection: {} as any, + __LEGACY: { plugins: { xpack_main: { status: new EventEmitter() } } } as any, +}); + +export const createMockStartDeps = (startMock?: any): ReportingStartDeps => ({ + data: startMock.data, + elasticsearch: startMock.elasticsearch, + __LEGACY: {} as any, +}); + +const createMockReportingPlugin = async (config = {}): Promise => { + const plugin = new ReportingPlugin(coreMock.createPluginInitializerContext(config)); + const setupMock = coreMock.createSetup(); + const coreStartMock = coreMock.createStart(); + const startMock = { + ...coreStartMock, + data: { fieldFormats: {} }, + }; + + await plugin.setup(setupMock, createMockSetupDeps(setupMock)); + await plugin.start(startMock, createMockStartDeps(startMock)); + + return plugin; +}; + +export const createMockReportingCore = async (config = {}): Promise => { + const plugin = await createMockReportingPlugin(config); + return plugin.getReportingCore(); +}; diff --git a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts index 226355f5edc61..bb7851ba036a9 100644 --- a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts +++ b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts @@ -8,9 +8,6 @@ import { ServerFacade } from '../types'; export const createMockServer = ({ settings = {} }: any): ServerFacade => { const mockServer = { - expose: () => { - ' '; - }, config: memoize(() => ({ get: jest.fn() })), info: { protocol: 'http', @@ -24,10 +21,6 @@ export const createMockServer = ({ settings = {} }: any): ServerFacade => { }), }, }, - savedObjects: { - getScopedSavedObjectsClient: jest.fn(), - }, - uiSettingsServiceFactory: jest.fn().mockReturnValue({ get: jest.fn() }), }; const defaultSettings: any = { diff --git a/x-pack/legacy/plugins/reporting/test_helpers/index.ts b/x-pack/legacy/plugins/reporting/test_helpers/index.ts new file mode 100644 index 0000000000000..7fbc5661d5211 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/test_helpers/index.ts @@ -0,0 +1,8 @@ +/* + * 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 { createMockServer } from './create_mock_server'; +export { createMockReportingCore } from './create_mock_reportingplugin'; diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index a4ff39b23747d..1549c173b3d6e 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -6,16 +6,15 @@ import { EventEmitter } from 'events'; import { ResponseObject } from 'hapi'; -import { ElasticsearchServiceSetup } from 'kibana/server'; import { Legacy } from 'kibana'; +import { ElasticsearchServiceSetup } from 'kibana/server'; import { CallCluster } from '../../../../src/legacy/core_plugins/elasticsearch'; import { CancellationToken } from './common/cancellation_token'; import { HeadlessChromiumDriverFactory } from './server/browsers/chromium/driver_factory'; import { BrowserType } from './server/browsers/types'; import { LevelLogger } from './server/lib/level_logger'; -import { LegacySetup, ReportingSetupDeps } from './server/plugin'; - -export type ReportingPlugin = object; // For Plugin contract +import { ReportingCore } from './server/core'; +import { LegacySetup, ReportingStartDeps, ReportingSetup, ReportingStart } from './server/types'; export type Job = EventEmitter & { id: string; @@ -65,6 +64,7 @@ interface GenerateExportTypePayload { /* * Legacy System + * TODO: move to server/types */ export type ServerFacade = LegacySetup; @@ -179,6 +179,15 @@ export interface CryptoFactory { decrypt: (headers?: string) => any; } +export interface IndexPatternSavedObject { + attributes: { + fieldFormatMap: string; + }; + id: string; + type: string; + version: string; +} + export interface TimeRangeParams { timezone: string; min: Date | string | number; @@ -214,10 +223,6 @@ export interface JobDocOutput { size: number; } -export interface ESQueue { - addJob: (type: string, payload: object, options: object) => Job; -} - export interface ESQueueWorker { on: (event: string, handler: any) => void; } @@ -267,8 +272,9 @@ type GenericWorkerFn = ( ...workerRestArgs: any[] ) => void | Promise; -export interface ESQueueInstance { - registerWorker: ( +export interface ESQueueInstance { + addJob: (type: string, payload: unknown, options: object) => Job; + registerWorker: ( pluginId: string, workerFn: GenericWorkerFn, workerOptions: ESQueueWorkerOptions @@ -276,18 +282,17 @@ export interface ESQueueInstance { } export type CreateJobFactory = ( + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, logger: LevelLogger ) => CreateJobFnType; export type ExecuteJobFactory = ( + reporting: ReportingCore, server: ServerFacade, elasticsearch: ElasticsearchServiceSetup, - logger: LevelLogger, - opts: { - browserDriverFactory: HeadlessChromiumDriverFactory; - } -) => ExecuteJobFnType; + logger: LevelLogger +) => Promise; export interface ExportTypeDefinition< JobParamsType, @@ -309,7 +314,6 @@ export { CancellationToken } from './common/cancellation_token'; export { HeadlessChromiumDriver } from './server/browsers/chromium/driver'; export { HeadlessChromiumDriverFactory } from './server/browsers/chromium/driver_factory'; export { ExportTypesRegistry } from './server/lib/export_types_registry'; - // Prefer to import this type using: `import { LevelLogger } from 'relative/path/server/lib';` export { LevelLogger as Logger }; From 918c0dec9f1f24ca9b347f33f1b832e132d44218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= Date: Fri, 14 Feb 2020 15:38:45 -0500 Subject: [PATCH 11/32] Increase stability when initializing the Elasticsearch index for the event log (#57465) * Fix ILM policy creation * Handle errors thrown in scenario multiple Kibana instances are started at the same time * Fix tests and cleanup * Start adding tests * Refactor tests, add index template failure test * Create cluster client adapter to facilitate testing and isolation * Fix places calling callEs still Co-authored-by: Elastic Machine --- .../server/es/cluster_client_adapter.mock.ts | 24 +++ .../server/es/cluster_client_adapter.test.ts | 196 ++++++++++++++++++ .../server/es/cluster_client_adapter.ts | 126 +++++++++++ .../event_log/server/es/context.mock.ts | 60 ++---- x-pack/plugins/event_log/server/es/context.ts | 30 +-- .../event_log/server/es/documents.test.ts | 14 +- .../plugins/event_log/server/es/documents.ts | 7 +- .../plugins/event_log/server/es/init.test.ts | 64 ++++++ x-pack/plugins/event_log/server/es/init.ts | 121 +++-------- .../plugins/event_log/server/es/names.mock.ts | 23 ++ .../server/event_log_service.test.ts | 8 +- .../event_log/server/event_logger.test.ts | 5 +- .../plugins/event_log/server/event_logger.ts | 2 +- 13 files changed, 495 insertions(+), 185 deletions(-) create mode 100644 x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts create mode 100644 x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts create mode 100644 x-pack/plugins/event_log/server/es/cluster_client_adapter.ts create mode 100644 x-pack/plugins/event_log/server/es/init.test.ts create mode 100644 x-pack/plugins/event_log/server/es/names.mock.ts diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts new file mode 100644 index 0000000000000..87e8fb0f521a9 --- /dev/null +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts @@ -0,0 +1,24 @@ +/* + * 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 { IClusterClientAdapter } from './cluster_client_adapter'; + +const createClusterClientMock = () => { + const mock: jest.Mocked = { + indexDocument: jest.fn(), + doesIlmPolicyExist: jest.fn(), + createIlmPolicy: jest.fn(), + doesIndexTemplateExist: jest.fn(), + createIndexTemplate: jest.fn(), + doesAliasExist: jest.fn(), + createIndex: jest.fn(), + }; + return mock; +}; + +export const clusterClientAdapterMock = { + create: createClusterClientMock, +}; diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts new file mode 100644 index 0000000000000..ecefd4bfa271e --- /dev/null +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts @@ -0,0 +1,196 @@ +/* + * 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 { ClusterClient, Logger } from '../../../../../src/core/server'; +import { elasticsearchServiceMock, loggingServiceMock } from '../../../../../src/core/server/mocks'; +import { ClusterClientAdapter, IClusterClientAdapter } from './cluster_client_adapter'; + +type EsClusterClient = Pick, 'callAsInternalUser' | 'asScoped'>; + +let logger: Logger; +let clusterClient: EsClusterClient; +let clusterClientAdapter: IClusterClientAdapter; + +beforeEach(() => { + logger = loggingServiceMock.createLogger(); + clusterClient = elasticsearchServiceMock.createClusterClient(); + clusterClientAdapter = new ClusterClientAdapter({ + logger, + clusterClient, + }); +}); + +describe('indexDocument', () => { + test('should call cluster client with given doc', async () => { + await clusterClientAdapter.indexDocument({ args: true }); + expect(clusterClient.callAsInternalUser).toHaveBeenCalledWith('index', { + args: true, + }); + }); + + test('should throw error when cluster client throws an error', async () => { + clusterClient.callAsInternalUser.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.indexDocument({ args: true }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"Fail"`); + }); +}); + +describe('doesIlmPolicyExist', () => { + const notFoundError = new Error('Not found') as any; + notFoundError.statusCode = 404; + + test('should call cluster with proper arguments', async () => { + await clusterClientAdapter.doesIlmPolicyExist('foo'); + expect(clusterClient.callAsInternalUser).toHaveBeenCalledWith('transport.request', { + method: 'GET', + path: '_ilm/policy/foo', + }); + }); + + test('should return false when 404 error is returned by Elasticsearch', async () => { + clusterClient.callAsInternalUser.mockRejectedValue(notFoundError); + await expect(clusterClientAdapter.doesIlmPolicyExist('foo')).resolves.toEqual(false); + }); + + test('should throw error when error is not 404', async () => { + clusterClient.callAsInternalUser.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.doesIlmPolicyExist('foo') + ).rejects.toThrowErrorMatchingInlineSnapshot(`"error checking existance of ilm policy: Fail"`); + }); + + test('should return true when no error is thrown', async () => { + await expect(clusterClientAdapter.doesIlmPolicyExist('foo')).resolves.toEqual(true); + }); +}); + +describe('createIlmPolicy', () => { + test('should call cluster client with given policy', async () => { + clusterClient.callAsInternalUser.mockResolvedValue({ success: true }); + await clusterClientAdapter.createIlmPolicy('foo', { args: true }); + expect(clusterClient.callAsInternalUser).toHaveBeenCalledWith('transport.request', { + method: 'PUT', + path: '_ilm/policy/foo', + body: { args: true }, + }); + }); + + test('should throw error when call cluster client throws', async () => { + clusterClient.callAsInternalUser.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.createIlmPolicy('foo', { args: true }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"error creating ilm policy: Fail"`); + }); +}); + +describe('doesIndexTemplateExist', () => { + test('should call cluster with proper arguments', async () => { + await clusterClientAdapter.doesIndexTemplateExist('foo'); + expect(clusterClient.callAsInternalUser).toHaveBeenCalledWith('indices.existsTemplate', { + name: 'foo', + }); + }); + + test('should return true when call cluster returns true', async () => { + clusterClient.callAsInternalUser.mockResolvedValue(true); + await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(true); + }); + + test('should return false when call cluster returns false', async () => { + clusterClient.callAsInternalUser.mockResolvedValue(false); + await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(false); + }); + + test('should throw error when call cluster throws an error', async () => { + clusterClient.callAsInternalUser.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.doesIndexTemplateExist('foo') + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"error checking existance of index template: Fail"` + ); + }); +}); + +describe('createIndexTemplate', () => { + test('should call cluster with given template', async () => { + await clusterClientAdapter.createIndexTemplate('foo', { args: true }); + expect(clusterClient.callAsInternalUser).toHaveBeenCalledWith('indices.putTemplate', { + name: 'foo', + create: true, + body: { args: true }, + }); + }); + + test(`should throw error if index template still doesn't exist after error is thrown`, async () => { + clusterClient.callAsInternalUser.mockRejectedValueOnce(new Error('Fail')); + clusterClient.callAsInternalUser.mockResolvedValueOnce(false); + await expect( + clusterClientAdapter.createIndexTemplate('foo', { args: true }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"error creating index template: Fail"`); + }); + + test('should not throw error if index template exists after error is thrown', async () => { + clusterClient.callAsInternalUser.mockRejectedValueOnce(new Error('Fail')); + clusterClient.callAsInternalUser.mockResolvedValueOnce(true); + await clusterClientAdapter.createIndexTemplate('foo', { args: true }); + }); +}); + +describe('doesAliasExist', () => { + test('should call cluster with proper arguments', async () => { + await clusterClientAdapter.doesAliasExist('foo'); + expect(clusterClient.callAsInternalUser).toHaveBeenCalledWith('indices.existsAlias', { + name: 'foo', + }); + }); + + test('should return true when call cluster returns true', async () => { + clusterClient.callAsInternalUser.mockResolvedValueOnce(true); + await expect(clusterClientAdapter.doesAliasExist('foo')).resolves.toEqual(true); + }); + + test('should return false when call cluster returns false', async () => { + clusterClient.callAsInternalUser.mockResolvedValueOnce(false); + await expect(clusterClientAdapter.doesAliasExist('foo')).resolves.toEqual(false); + }); + + test('should throw error when call cluster throws an error', async () => { + clusterClient.callAsInternalUser.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.doesAliasExist('foo') + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"error checking existance of initial index: Fail"` + ); + }); +}); + +describe('createIndex', () => { + test('should call cluster with proper arguments', async () => { + await clusterClientAdapter.createIndex('foo'); + expect(clusterClient.callAsInternalUser).toHaveBeenCalledWith('indices.create', { + index: 'foo', + }); + }); + + test('should throw error when not getting an error of type resource_already_exists_exception', async () => { + clusterClient.callAsInternalUser.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.createIndex('foo') + ).rejects.toThrowErrorMatchingInlineSnapshot(`"error creating initial index: Fail"`); + }); + + test(`shouldn't throw when an error of type resource_already_exists_exception is thrown`, async () => { + const err = new Error('Already exists') as any; + err.body = { + error: { + type: 'resource_already_exists_exception', + }, + }; + clusterClient.callAsInternalUser.mockRejectedValue(err); + await clusterClientAdapter.createIndex('foo'); + }); +}); diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts new file mode 100644 index 0000000000000..c74eeacc9bb19 --- /dev/null +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts @@ -0,0 +1,126 @@ +/* + * 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 { Logger, ClusterClient } from '../../../../../src/core/server'; + +export type EsClusterClient = Pick; +export type IClusterClientAdapter = PublicMethodsOf; + +export interface ConstructorOpts { + logger: Logger; + clusterClient: EsClusterClient; +} + +export class ClusterClientAdapter { + private readonly logger: Logger; + private readonly clusterClient: EsClusterClient; + + constructor(opts: ConstructorOpts) { + this.logger = opts.logger; + this.clusterClient = opts.clusterClient; + } + + public async indexDocument(doc: any): Promise { + await this.callEs('index', doc); + } + + public async doesIlmPolicyExist(policyName: string): Promise { + const request = { + method: 'GET', + path: `_ilm/policy/${policyName}`, + }; + try { + await this.callEs('transport.request', request); + } catch (err) { + if (err.statusCode === 404) return false; + throw new Error(`error checking existance of ilm policy: ${err.message}`); + } + return true; + } + + public async createIlmPolicy(policyName: string, policy: any): Promise { + const request = { + method: 'PUT', + path: `_ilm/policy/${policyName}`, + body: policy, + }; + try { + await this.callEs('transport.request', request); + } catch (err) { + throw new Error(`error creating ilm policy: ${err.message}`); + } + } + + public async doesIndexTemplateExist(name: string): Promise { + let result; + try { + result = await this.callEs('indices.existsTemplate', { name }); + } catch (err) { + throw new Error(`error checking existance of index template: ${err.message}`); + } + return result as boolean; + } + + public async createIndexTemplate(name: string, template: any): Promise { + const addTemplateParams = { + name, + create: true, + body: template, + }; + try { + await this.callEs('indices.putTemplate', addTemplateParams); + } catch (err) { + // The error message doesn't have a type attribute we can look to guarantee it's due + // to the template already existing (only long message) so we'll check ourselves to see + // if the template now exists. This scenario would happen if you startup multiple Kibana + // instances at the same time. + const existsNow = await this.doesIndexTemplateExist(name); + if (!existsNow) { + throw new Error(`error creating index template: ${err.message}`); + } + } + } + + public async doesAliasExist(name: string): Promise { + let result; + try { + result = await this.callEs('indices.existsAlias', { name }); + } catch (err) { + throw new Error(`error checking existance of initial index: ${err.message}`); + } + return result as boolean; + } + + public async createIndex(name: string): Promise { + try { + await this.callEs('indices.create', { index: name }); + } catch (err) { + if (err.body?.error?.type !== 'resource_already_exists_exception') { + throw new Error(`error creating initial index: ${err.message}`); + } + } + } + + private async callEs(operation: string, body?: any): Promise { + try { + this.debug(`callEs(${operation}) calls:`, body); + const result = await this.clusterClient.callAsInternalUser(operation, body); + this.debug(`callEs(${operation}) result:`, result); + return result; + } catch (err) { + this.debug(`callEs(${operation}) error:`, { + message: err.message, + statusCode: err.statusCode, + }); + throw err; + } + } + + private debug(message: string, object?: any) { + const objectString = object == null ? '' : JSON.stringify(object); + this.logger.debug(`esContext: ${message} ${objectString}`); + } +} diff --git a/x-pack/plugins/event_log/server/es/context.mock.ts b/x-pack/plugins/event_log/server/es/context.mock.ts index fb894ce6e7787..6581cd689e43d 100644 --- a/x-pack/plugins/event_log/server/es/context.mock.ts +++ b/x-pack/plugins/event_log/server/es/context.mock.ts @@ -4,43 +4,25 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger, ClusterClient } from '../../../../../src/core/server'; import { EsContext } from './context'; - -import { EsNames } from './names'; - -export type EsClusterClient = Pick; - -export interface EsError { - readonly statusCode: number; - readonly message: string; -} - -interface CreateMockEsContextParams { - logger: Logger; - esNames: EsNames; -} - -export function createMockEsContext(params: CreateMockEsContextParams): EsContext { - return new EsContextMock(params); -} - -class EsContextMock implements EsContext { - public logger: Logger; - public esNames: EsNames; - - constructor(params: CreateMockEsContextParams) { - this.logger = params.logger; - this.esNames = params.esNames; - } - - initialize() {} - - async waitTillReady(): Promise { - return true; - } - - async callEs(operation: string, body?: any): Promise { - return {}; - } -} +import { namesMock } from './names.mock'; +import { IClusterClientAdapter } from './cluster_client_adapter'; +import { loggingServiceMock } from '../../../../../src/core/server/mocks'; +import { clusterClientAdapterMock } from './cluster_client_adapter.mock'; + +const createContextMock = () => { + const mock: jest.Mocked & { + esAdapter: jest.Mocked; + } = { + logger: loggingServiceMock.createLogger(), + esNames: namesMock.create(), + initialize: jest.fn(), + waitTillReady: jest.fn(), + esAdapter: clusterClientAdapterMock.create(), + }; + return mock; +}; + +export const contextMock = { + create: createContextMock, +}; diff --git a/x-pack/plugins/event_log/server/es/context.ts b/x-pack/plugins/event_log/server/es/context.ts index b93c1892d0206..144f44ac8e5ea 100644 --- a/x-pack/plugins/event_log/server/es/context.ts +++ b/x-pack/plugins/event_log/server/es/context.ts @@ -8,6 +8,7 @@ import { Logger, ClusterClient } from 'src/core/server'; import { EsNames, getEsNames } from './names'; import { initializeEs } from './init'; +import { ClusterClientAdapter, IClusterClientAdapter } from './cluster_client_adapter'; import { createReadySignal, ReadySignal } from '../lib/ready_signal'; export type EsClusterClient = Pick; @@ -15,9 +16,9 @@ export type EsClusterClient = Pick; - callEs(operation: string, body?: any): Promise; } export interface EsError { @@ -38,16 +39,19 @@ export interface EsContextCtorParams { class EsContextImpl implements EsContext { public readonly logger: Logger; public readonly esNames: EsNames; - private readonly clusterClient: EsClusterClient; + public esAdapter: IClusterClientAdapter; private readonly readySignal: ReadySignal; private initialized: boolean; constructor(params: EsContextCtorParams) { this.logger = params.logger; this.esNames = getEsNames(params.indexNameRoot); - this.clusterClient = params.clusterClient; this.readySignal = createReadySignal(); this.initialized = false; + this.esAdapter = new ClusterClientAdapter({ + logger: params.logger, + clusterClient: params.clusterClient, + }); } initialize() { @@ -73,27 +77,7 @@ class EsContextImpl implements EsContext { return await this.readySignal.wait(); } - async callEs(operation: string, body?: any): Promise { - try { - this.debug(`callEs(${operation}) calls:`, body); - const result = await this.clusterClient.callAsInternalUser(operation, body); - this.debug(`callEs(${operation}) result:`, result); - return result; - } catch (err) { - this.debug(`callEs(${operation}) error:`, { - message: err.message, - statusCode: err.statusCode, - }); - throw err; - } - } - private async _initialize() { await initializeEs(this); } - - private debug(message: string, object?: any) { - const objectString = object == null ? '' : JSON.stringify(object); - this.logger.debug(`esContext: ${message} ${objectString}`); - } } diff --git a/x-pack/plugins/event_log/server/es/documents.test.ts b/x-pack/plugins/event_log/server/es/documents.test.ts index 2dec23c61de2f..7edca4b3943a6 100644 --- a/x-pack/plugins/event_log/server/es/documents.test.ts +++ b/x-pack/plugins/event_log/server/es/documents.test.ts @@ -21,23 +21,13 @@ describe('getIndexTemplate()', () => { const esNames = getEsNames('XYZ'); test('returns the correct details of the index template', () => { - const indexTemplate = getIndexTemplate(esNames, true); + const indexTemplate = getIndexTemplate(esNames); expect(indexTemplate.index_patterns).toEqual([esNames.indexPattern]); expect(indexTemplate.aliases[esNames.alias]).toEqual({}); expect(indexTemplate.settings.number_of_shards).toBeGreaterThanOrEqual(0); expect(indexTemplate.settings.number_of_replicas).toBeGreaterThanOrEqual(0); - expect(indexTemplate.mappings).toMatchObject({}); - }); - - test('returns correct index template bits for ilm when ilm is supported', () => { - const indexTemplate = getIndexTemplate(esNames, true); expect(indexTemplate.settings['index.lifecycle.name']).toBe(esNames.ilmPolicy); expect(indexTemplate.settings['index.lifecycle.rollover_alias']).toBe(esNames.alias); - }); - - test('returns correct index template bits for ilm when ilm is not supported', () => { - const indexTemplate = getIndexTemplate(esNames, false); - expect(indexTemplate.settings['index.lifecycle.name']).toBeUndefined(); - expect(indexTemplate.settings['index.lifecycle.rollover_alias']).toBeUndefined(); + expect(indexTemplate.mappings).toMatchObject({}); }); }); diff --git a/x-pack/plugins/event_log/server/es/documents.ts b/x-pack/plugins/event_log/server/es/documents.ts index dfc544f8a41cb..09dd7383c4c5e 100644 --- a/x-pack/plugins/event_log/server/es/documents.ts +++ b/x-pack/plugins/event_log/server/es/documents.ts @@ -8,7 +8,7 @@ import { EsNames } from './names'; import mappings from '../../generated/mappings.json'; // returns the body of an index template used in an ES indices.putTemplate call -export function getIndexTemplate(esNames: EsNames, ilmExists: boolean) { +export function getIndexTemplate(esNames: EsNames) { const indexTemplateBody: any = { index_patterns: [esNames.indexPattern], aliases: { @@ -23,11 +23,6 @@ export function getIndexTemplate(esNames: EsNames, ilmExists: boolean) { mappings, }; - if (!ilmExists) { - delete indexTemplateBody.settings['index.lifecycle.name']; - delete indexTemplateBody.settings['index.lifecycle.rollover_alias']; - } - return indexTemplateBody; } diff --git a/x-pack/plugins/event_log/server/es/init.test.ts b/x-pack/plugins/event_log/server/es/init.test.ts new file mode 100644 index 0000000000000..ad237e522c0a5 --- /dev/null +++ b/x-pack/plugins/event_log/server/es/init.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { contextMock } from './context.mock'; +import { initializeEs } from './init'; + +describe('initializeEs', () => { + let esContext = contextMock.create(); + + beforeEach(() => { + esContext = contextMock.create(); + }); + + test(`should create ILM policy if it doesn't exist`, async () => { + esContext.esAdapter.doesIlmPolicyExist.mockResolvedValue(false); + + await initializeEs(esContext); + expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled(); + expect(esContext.esAdapter.createIlmPolicy).toHaveBeenCalled(); + }); + + test(`shouldn't create ILM policy if it exists`, async () => { + esContext.esAdapter.doesIlmPolicyExist.mockResolvedValue(true); + + await initializeEs(esContext); + expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled(); + expect(esContext.esAdapter.createIlmPolicy).not.toHaveBeenCalled(); + }); + + test(`should create index template if it doesn't exist`, async () => { + esContext.esAdapter.doesIndexTemplateExist.mockResolvedValue(false); + + await initializeEs(esContext); + expect(esContext.esAdapter.doesIndexTemplateExist).toHaveBeenCalled(); + expect(esContext.esAdapter.createIndexTemplate).toHaveBeenCalled(); + }); + + test(`shouldn't create index template if it already exists`, async () => { + esContext.esAdapter.doesIndexTemplateExist.mockResolvedValue(true); + + await initializeEs(esContext); + expect(esContext.esAdapter.doesIndexTemplateExist).toHaveBeenCalled(); + expect(esContext.esAdapter.createIndexTemplate).not.toHaveBeenCalled(); + }); + + test(`should create initial index if it doesn't exist`, async () => { + esContext.esAdapter.doesAliasExist.mockResolvedValue(false); + + await initializeEs(esContext); + expect(esContext.esAdapter.doesAliasExist).toHaveBeenCalled(); + expect(esContext.esAdapter.createIndex).toHaveBeenCalled(); + }); + + test(`shouldn't create initial index if it already exists`, async () => { + esContext.esAdapter.doesAliasExist.mockResolvedValue(true); + + await initializeEs(esContext); + expect(esContext.esAdapter.doesAliasExist).toHaveBeenCalled(); + expect(esContext.esAdapter.createIndex).not.toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/event_log/server/es/init.ts b/x-pack/plugins/event_log/server/es/init.ts index d87f5bce03475..7094277f7aa9f 100644 --- a/x-pack/plugins/event_log/server/es/init.ts +++ b/x-pack/plugins/event_log/server/es/init.ts @@ -23,25 +23,10 @@ export async function initializeEs(esContext: EsContext): Promise { async function initializeEsResources(esContext: EsContext) { const steps = new EsInitializationSteps(esContext); - let ilmExists: boolean; - // create the ilm policy, if required - ilmExists = await steps.doesIlmPolicyExist(); - if (!ilmExists) { - ilmExists = await steps.createIlmPolicy(); - } - - if (!(await steps.doesIndexTemplateExist())) { - await steps.createIndexTemplate({ ilmExists }); - } - - if (!(await steps.doesInitialIndexExist())) { - await steps.createInitialIndex(); - } -} - -interface AddTemplateOpts { - ilmExists: boolean; + await steps.createIlmPolicyIfNotExists(); + await steps.createIndexTemplateIfNotExists(); + await steps.createInitialIndexIfNotExists(); } class EsInitializationSteps { @@ -49,89 +34,35 @@ class EsInitializationSteps { this.esContext = esContext; } - async doesIlmPolicyExist(): Promise { - const request = { - method: 'GET', - path: `_ilm/policy/${this.esContext.esNames.ilmPolicy}`, - }; - try { - await this.esContext.callEs('transport.request', request); - } catch (err) { - if (err.statusCode === 404) return false; - // TODO: remove following once kibana user can access ilm - if (err.statusCode === 403) return false; - - throw new Error(`error checking existance of ilm policy: ${err.message}`); - } - return true; - } - - async createIlmPolicy(): Promise { - const request = { - method: 'PUT', - path: `_ilm/policy/${this.esContext.esNames.ilmPolicy}`, - body: getIlmPolicy(), - }; - try { - await this.esContext.callEs('transport.request', request); - } catch (err) { - // TODO: remove following once kibana user can access ilm - if (err.statusCode === 403) return false; - throw new Error(`error creating ilm policy: ${err.message}`); + async createIlmPolicyIfNotExists(): Promise { + const exists = await this.esContext.esAdapter.doesIlmPolicyExist( + this.esContext.esNames.ilmPolicy + ); + if (!exists) { + await this.esContext.esAdapter.createIlmPolicy( + this.esContext.esNames.ilmPolicy, + getIlmPolicy() + ); } - return true; } - async doesIndexTemplateExist(): Promise { - const name = this.esContext.esNames.indexTemplate; - let result; - try { - result = await this.esContext.callEs('indices.existsTemplate', { name }); - } catch (err) { - throw new Error(`error checking existance of index template: ${err.message}`); + async createIndexTemplateIfNotExists(): Promise { + const exists = await this.esContext.esAdapter.doesIndexTemplateExist( + this.esContext.esNames.indexTemplate + ); + if (!exists) { + const templateBody = getIndexTemplate(this.esContext.esNames); + await this.esContext.esAdapter.createIndexTemplate( + this.esContext.esNames.indexTemplate, + templateBody + ); } - return result as boolean; } - async createIndexTemplate(opts: AddTemplateOpts): Promise { - const templateBody = getIndexTemplate(this.esContext.esNames, opts.ilmExists); - const addTemplateParams = { - create: true, - name: this.esContext.esNames.indexTemplate, - body: templateBody, - }; - try { - await this.esContext.callEs('indices.putTemplate', addTemplateParams); - } catch (err) { - throw new Error(`error creating index template: ${err.message}`); + async createInitialIndexIfNotExists(): Promise { + const exists = await this.esContext.esAdapter.doesAliasExist(this.esContext.esNames.alias); + if (!exists) { + await this.esContext.esAdapter.createIndex(this.esContext.esNames.initialIndex); } } - - async doesInitialIndexExist(): Promise { - const name = this.esContext.esNames.alias; - let result; - try { - result = await this.esContext.callEs('indices.existsAlias', { name }); - } catch (err) { - throw new Error(`error checking existance of initial index: ${err.message}`); - } - return result as boolean; - } - - async createInitialIndex(): Promise { - const index = this.esContext.esNames.initialIndex; - try { - await this.esContext.callEs('indices.create', { index }); - } catch (err) { - throw new Error(`error creating initial index: ${err.message}`); - } - } - - debug(message: string) { - this.esContext.logger.debug(message); - } - - warn(message: string) { - this.esContext.logger.warn(message); - } } diff --git a/x-pack/plugins/event_log/server/es/names.mock.ts b/x-pack/plugins/event_log/server/es/names.mock.ts new file mode 100644 index 0000000000000..7b013a0d263da --- /dev/null +++ b/x-pack/plugins/event_log/server/es/names.mock.ts @@ -0,0 +1,23 @@ +/* + * 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 { EsNames } from './names'; + +const createNamesMock = () => { + const mock: jest.Mocked = { + base: '.kibana', + alias: '.kibana-event-log', + ilmPolicy: '.kibana-event-log-policy', + indexPattern: '.kibana-event-log-*', + initialIndex: '.kibana-event-log-000001', + indexTemplate: '.kibana-event-log-template', + }; + return mock; +}; + +export const namesMock = { + create: createNamesMock, +}; diff --git a/x-pack/plugins/event_log/server/event_log_service.test.ts b/x-pack/plugins/event_log/server/event_log_service.test.ts index c7e752d1a652b..3b250b7462009 100644 --- a/x-pack/plugins/event_log/server/event_log_service.test.ts +++ b/x-pack/plugins/event_log/server/event_log_service.test.ts @@ -6,18 +6,14 @@ import { IEventLogConfig } from './types'; import { EventLogService } from './event_log_service'; -import { getEsNames } from './es/names'; -import { createMockEsContext } from './es/context.mock'; +import { contextMock } from './es/context.mock'; import { loggingServiceMock } from '../../../../src/core/server/logging/logging_service.mock'; const loggingService = loggingServiceMock.create(); const systemLogger = loggingService.get(); describe('EventLogService', () => { - const esContext = createMockEsContext({ - esNames: getEsNames('ABC'), - logger: systemLogger, - }); + const esContext = contextMock.create(); function getService(config: IEventLogConfig) { const { enabled, logEntries, indexEntries } = config; diff --git a/x-pack/plugins/event_log/server/event_logger.test.ts b/x-pack/plugins/event_log/server/event_logger.test.ts index 97e52ad04dd08..673bac4f396e1 100644 --- a/x-pack/plugins/event_log/server/event_logger.test.ts +++ b/x-pack/plugins/event_log/server/event_logger.test.ts @@ -7,9 +7,8 @@ import { IEvent, IEventLogger, IEventLogService } from './index'; import { ECS_VERSION } from './types'; import { EventLogService } from './event_log_service'; -import { getEsNames } from './es/names'; import { EsContext } from './es/context'; -import { createMockEsContext } from './es/context.mock'; +import { contextMock } from './es/context.mock'; import { loggerMock, MockedLogger } from '../../../../src/core/server/logging/logger.mock'; import { delay } from './lib/delay'; import { EVENT_LOGGED_PREFIX } from './event_logger'; @@ -24,7 +23,7 @@ describe('EventLogger', () => { beforeEach(() => { systemLogger = loggerMock.create(); - esContext = createMockEsContext({ esNames: getEsNames('ABC'), logger: systemLogger }); + esContext = contextMock.create(); service = new EventLogService({ esContext, systemLogger, diff --git a/x-pack/plugins/event_log/server/event_logger.ts b/x-pack/plugins/event_log/server/event_logger.ts index 891abda947fc8..f5149da069953 100644 --- a/x-pack/plugins/event_log/server/event_logger.ts +++ b/x-pack/plugins/event_log/server/event_logger.ts @@ -171,7 +171,7 @@ function indexEventDoc(esContext: EsContext, doc: Doc): void { async function indexLogEventDoc(esContext: EsContext, doc: any) { esContext.logger.debug(`writing to event log: ${JSON.stringify(doc)}`); await esContext.waitTillReady(); - await esContext.callEs('index', doc); + await esContext.esAdapter.indexDocument(doc); esContext.logger.debug(`writing to event log complete`); } From e319269e18aab3be72c13138efa062102a7454ae Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Fri, 14 Feb 2020 16:07:44 -0500 Subject: [PATCH 12/32] [Monitoring] Support shipping directly to the monitoring cluster (#57022) * Support shipping directly to the monitoring cluster * Add timestamp * PR feedback * Use utc --- .../plugins/monitoring/common/constants.ts | 2 +- x-pack/legacy/plugins/monitoring/config.js | 41 +++++++++ x-pack/legacy/plugins/monitoring/index.ts | 7 +- .../es_client/parse_elasticsearch_config.ts | 9 +- .../__tests__/bulk_uploader.js | 92 +++++++++++++++++++ .../server/kibana_monitoring/bulk_uploader.js | 29 +++++- .../lib/send_bulk_payload.js | 55 ++++++++++- .../plugins/monitoring/server/plugin.js | 16 ++-- 8 files changed, 233 insertions(+), 18 deletions(-) diff --git a/x-pack/legacy/plugins/monitoring/common/constants.ts b/x-pack/legacy/plugins/monitoring/common/constants.ts index 1fc322a0de395..1fb6acdb915b8 100644 --- a/x-pack/legacy/plugins/monitoring/common/constants.ts +++ b/x-pack/legacy/plugins/monitoring/common/constants.ts @@ -17,7 +17,7 @@ export const KIBANA_MONITORING_LOGGING_TAG = 'kibana-monitoring'; * The Monitoring API version is the expected API format that we export and expect to import. * @type {string} */ -export const MONITORING_SYSTEM_API_VERSION = '6'; +export const MONITORING_SYSTEM_API_VERSION = '7'; /** * The type name used within the Monitoring index to publish Kibana ops stats. * @type {string} diff --git a/x-pack/legacy/plugins/monitoring/config.js b/x-pack/legacy/plugins/monitoring/config.js index ec4c00ccbea11..bd35d5271132d 100644 --- a/x-pack/legacy/plugins/monitoring/config.js +++ b/x-pack/legacy/plugins/monitoring/config.js @@ -84,6 +84,47 @@ export const config = Joi => { interval: Joi.number().default(10000), // op status metrics get buffered at `ops.interval` and flushed to the bulk endpoint at this interval }).default(), }).default(), + elasticsearch: Joi.object({ + customHeaders: Joi.object().default({}), + logQueries: Joi.boolean().default(false), + requestHeadersWhitelist: Joi.array() + .items() + .single() + .default(DEFAULT_REQUEST_HEADERS), + sniffOnStart: Joi.boolean().default(false), + sniffInterval: Joi.number() + .allow(false) + .default(false), + sniffOnConnectionFault: Joi.boolean().default(false), + hosts: Joi.array() + .items(Joi.string().uri({ scheme: ['http', 'https'] })) + .single(), // if empty, use Kibana's connection config + username: Joi.string(), + password: Joi.string(), + requestTimeout: Joi.number().default(30000), + pingTimeout: Joi.number().default(30000), + ssl: Joi.object({ + verificationMode: Joi.string() + .valid('none', 'certificate', 'full') + .default('full'), + certificateAuthorities: Joi.array() + .single() + .items(Joi.string()), + certificate: Joi.string(), + key: Joi.string(), + keyPassphrase: Joi.string(), + keystore: Joi.object({ + path: Joi.string(), + password: Joi.string(), + }).default(), + truststore: Joi.object({ + path: Joi.string(), + password: Joi.string(), + }).default(), + alwaysPresentCertificate: Joi.boolean().default(false), + }).default(), + apiVersion: Joi.string().default('master'), + }).default(), cluster_alerts: Joi.object({ enabled: Joi.boolean().default(true), email_notifications: Joi.object({ diff --git a/x-pack/legacy/plugins/monitoring/index.ts b/x-pack/legacy/plugins/monitoring/index.ts index c596beb117971..1186fde52dc46 100644 --- a/x-pack/legacy/plugins/monitoring/index.ts +++ b/x-pack/legacy/plugins/monitoring/index.ts @@ -44,6 +44,8 @@ const validConfigOptions: string[] = [ 'monitoring.ui.container.logstash.enabled', 'monitoring.tests.cloud_detector.enabled', 'monitoring.kibana.collection.interval', + 'monitoring.elasticsearch.hosts', + 'monitoring.elasticsearch', 'monitoring.ui.elasticsearch.hosts', 'monitoring.ui.elasticsearch', 'monitoring.xpack_api_polling_frequency_millis', @@ -77,7 +79,7 @@ export const monitoring = (kibana: LegacyPluginApi): LegacyPluginSpec => { uiExports: getUiExports(), deprecations, - init(server: Server) { + async init(server: Server) { const serverConfig = server.config(); const { getOSInfo, plugins, injectUiAppVars } = server as typeof server & { getOSInfo?: any }; const log = (...args: Parameters) => server.log(...args); @@ -127,7 +129,8 @@ export const monitoring = (kibana: LegacyPluginApi): LegacyPluginSpec => { }, }; - new Plugin().setup(coreSetup, pluginsSetup, __LEGACY); + const plugin = new Plugin(); + await plugin.setup(coreSetup, pluginsSetup, __LEGACY); }, postInit(server: Server) { diff --git a/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.ts b/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.ts index 728b3433bf06c..87b225e48c158 100644 --- a/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.ts +++ b/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.ts @@ -16,10 +16,13 @@ const KEY = 'monitoring.ui.elasticsearch'; * TODO: this code can be removed when this plugin is migrated to the Kibana Platform, * at that point the ElasticsearchClient and ElasticsearchConfig should be used instead */ -export const parseElasticsearchConfig = (config: any) => { - const es = config.get(KEY); +export const parseElasticsearchConfig = (config: any, configKey: string = KEY) => { + const es = config.get(configKey); + if (!es) { + return {}; + } - const errorPrefix = `[config validation of [${KEY}].ssl]`; + const errorPrefix = `[config validation of [${configKey}].ssl]`; if (es.ssl?.key && es.ssl?.keystore?.path) { throw new Error(`${errorPrefix}: cannot use [key] when [keystore.path] is specified`); } diff --git a/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js b/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js index ef7d3f1224fab..2fefdbd4f0943 100644 --- a/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js +++ b/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js @@ -6,8 +6,10 @@ import { noop } from 'lodash'; import sinon from 'sinon'; +import moment from 'moment'; import expect from '@kbn/expect'; import { BulkUploader } from '../bulk_uploader'; +import { MONITORING_SYSTEM_API_VERSION } from '../../../common/constants'; const FETCH_INTERVAL = 300; const CHECK_DELAY = 500; @@ -52,6 +54,9 @@ describe('BulkUploader', () => { server = { log: sinon.spy(), + config: { + get: sinon.spy(), + }, elasticsearchPlugin: { createCluster: () => cluster, getCluster: () => cluster, @@ -307,5 +312,92 @@ describe('BulkUploader', () => { done(); }, CHECK_DELAY); }); + + it('uses a direct connection to the monitoring cluster, when configured', done => { + const dateInIndex = '2020.02.10'; + const oldNow = moment.now; + moment.now = () => 1581310800000; + const prodClusterUuid = '1sdfd5'; + const prodCluster = { + callWithInternalUser: sinon + .stub() + .withArgs('monitoring.bulk') + .callsFake(arg => { + let resolution = null; + if (arg === 'info') { + resolution = { cluster_uuid: prodClusterUuid }; + } + return new Promise(resolve => resolve(resolution)); + }), + }; + const monitoringCluster = { + callWithInternalUser: sinon + .stub() + .withArgs('bulk') + .callsFake(() => { + return new Promise(resolve => setTimeout(resolve, CHECK_DELAY + 1)); + }), + }; + + const collectorFetch = sinon.stub().returns({ + type: 'kibana_stats', + result: { type: 'kibana_stats', payload: { testData: 12345 } }, + }); + + const collectors = new MockCollectorSet(server, [ + { + fetch: collectorFetch, + isReady: () => true, + formatForBulkUpload: result => result, + isUsageCollector: false, + }, + ]); + const customServer = { + ...server, + elasticsearchPlugin: { + createCluster: () => monitoringCluster, + getCluster: name => { + if (name === 'admin' || name === 'data') { + return prodCluster; + } + return monitoringCluster; + }, + }, + config: { + get: key => { + if (key === 'monitoring.elasticsearch') { + return { + hosts: ['http://localhost:9200'], + username: 'tester', + password: 'testing', + ssl: {}, + }; + } + return null; + }, + }, + }; + const kbnServerStatus = { toJSON: () => ({ overall: { state: 'green' } }) }; + const kbnServerVersion = 'master'; + const uploader = new BulkUploader({ + ...customServer, + interval: FETCH_INTERVAL, + kbnServerStatus, + kbnServerVersion, + }); + uploader.start(collectors); + setTimeout(() => { + uploader.stop(); + const firstCallArgs = monitoringCluster.callWithInternalUser.firstCall.args; + expect(firstCallArgs[0]).to.be('bulk'); + expect(firstCallArgs[1].body[0].index._index).to.be( + `.monitoring-kibana-${MONITORING_SYSTEM_API_VERSION}-${dateInIndex}` + ); + expect(firstCallArgs[1].body[1].type).to.be('kibana_stats'); + expect(firstCallArgs[1].body[1].cluster_uuid).to.be(prodClusterUuid); + moment.now = oldNow; + done(); + }, CHECK_DELAY); + }); }); }); diff --git a/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js b/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js index cf68ec073bebc..7417e6ca804d9 100644 --- a/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js +++ b/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { defaultsDeep, uniq, compact } from 'lodash'; +import { defaultsDeep, uniq, compact, get } from 'lodash'; import { callClusterFactory } from '../../../xpack_main'; import { @@ -14,6 +14,8 @@ import { } from '../../common/constants'; import { sendBulkPayload, monitoringBulk, getKibanaInfoForStats } from './lib'; +import { parseElasticsearchConfig } from '../es_client/parse_elasticsearch_config'; +import { hasMonitoringCluster } from '../es_client/instantiate_client'; const LOGGING_TAGS = [LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG]; @@ -39,6 +41,8 @@ export class BulkUploader { throw new Error('interval number of milliseconds is required'); } + this._hasDirectConnectionToMonitoringCluster = false; + this._productionClusterUuid = null; this._timer = null; // Hold sending and fetching usage until monitoring.bulk is successful. This means that we // send usage data on the second tick. But would save a lot of bandwidth fetching usage on @@ -60,6 +64,19 @@ export class BulkUploader { plugins: [monitoringBulk], }); + const directConfig = parseElasticsearchConfig(config, 'monitoring.elasticsearch'); + if (hasMonitoringCluster(directConfig)) { + this._log.info(`Detected direct connection to monitoring cluster`); + this._hasDirectConnectionToMonitoringCluster = true; + this._cluster = elasticsearchPlugin.createCluster('monitoring-direct', directConfig); + elasticsearchPlugin + .getCluster('admin') + .callWithInternalUser('info') + .then(data => { + this._productionClusterUuid = get(data, 'cluster_uuid'); + }); + } + this._callClusterWithInternalUser = callClusterFactory({ plugins: { elasticsearch: elasticsearchPlugin }, }).getCallClusterInternal(); @@ -151,7 +168,6 @@ export class BulkUploader { const data = await usageCollection.bulkFetch(this._callClusterWithInternalUser); const payload = this.toBulkUploadFormat(compact(data), usageCollection); - if (payload) { try { this._log.debug(`Uploading bulk stats payload to the local cluster`); @@ -182,7 +198,14 @@ export class BulkUploader { } async _onPayload(payload) { - return await sendBulkPayload(this._cluster, this._interval, payload); + return await sendBulkPayload( + this._cluster, + this._interval, + payload, + this._log, + this._hasDirectConnectionToMonitoringCluster, + this._productionClusterUuid + ); } /* diff --git a/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/lib/send_bulk_payload.js b/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/lib/send_bulk_payload.js index 3e5c64905da0d..c378c0ad0fa08 100644 --- a/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/lib/send_bulk_payload.js +++ b/x-pack/legacy/plugins/monitoring/server/kibana_monitoring/lib/send_bulk_payload.js @@ -3,13 +3,64 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import moment from 'moment'; +import { chunk, get } from 'lodash'; +import { + MONITORING_SYSTEM_API_VERSION, + KIBANA_SYSTEM_ID, + KIBANA_STATS_TYPE_MONITORING, + KIBANA_SETTINGS_TYPE, +} from '../../../common/constants'; -import { MONITORING_SYSTEM_API_VERSION, KIBANA_SYSTEM_ID } from '../../../common/constants'; +const SUPPORTED_TYPES = [KIBANA_STATS_TYPE_MONITORING, KIBANA_SETTINGS_TYPE]; +export function formatForNormalBulkEndpoint(payload, productionClusterUuid) { + const dateSuffix = moment.utc().format('YYYY.MM.DD'); + return chunk(payload, 2).reduce((accum, chunk) => { + const type = get(chunk[0], 'index._type'); + if (!type || !SUPPORTED_TYPES.includes(type)) { + return accum; + } + + const { timestamp } = chunk[1]; + + accum.push({ + index: { + _index: `.monitoring-kibana-${MONITORING_SYSTEM_API_VERSION}-${dateSuffix}`, + }, + }); + accum.push({ + [type]: chunk[1], + type, + timestamp, + cluster_uuid: productionClusterUuid, + }); + return accum; + }, []); +} /* * Send the Kibana usage data to the ES Monitoring Bulk endpoint */ -export function sendBulkPayload(cluster, interval, payload) { +export async function sendBulkPayload( + cluster, + interval, + payload, + log, + hasDirectConnectionToMonitoringCluster = false, + productionClusterUuid = null +) { + if (hasDirectConnectionToMonitoringCluster) { + if (productionClusterUuid === null) { + log.warn( + `Unable to determine production cluster uuid to use for shipping monitoring data. Kibana monitoring data will appear in a standalone cluster in the Stack Monitoring UI.` + ); + } + const formattedPayload = formatForNormalBulkEndpoint(payload, productionClusterUuid); + return await cluster.callWithInternalUser('bulk', { + body: formattedPayload, + }); + } + return cluster.callWithInternalUser('monitoring.bulk', { system_id: KIBANA_SYSTEM_ID, system_api_version: MONITORING_SYSTEM_API_VERSION, diff --git a/x-pack/legacy/plugins/monitoring/server/plugin.js b/x-pack/legacy/plugins/monitoring/server/plugin.js index c2aed7365f3af..304d2c08a1688 100644 --- a/x-pack/legacy/plugins/monitoring/server/plugin.js +++ b/x-pack/legacy/plugins/monitoring/server/plugin.js @@ -19,7 +19,7 @@ import { getLicenseExpiration } from './alerts/license_expiration'; import { parseElasticsearchConfig } from './es_client/parse_elasticsearch_config'; export class Plugin { - setup(_coreSetup, pluginsSetup, __LEGACY) { + async setup(_coreSetup, pluginsSetup, __LEGACY) { const { plugins, _kbnServer: kbnServer, @@ -59,6 +59,14 @@ export class Plugin { */ const elasticsearchConfig = parseElasticsearchConfig(config); + // Create the dedicated client + await instantiateClient({ + log, + events, + elasticsearchConfig, + elasticsearchPlugin: plugins.elasticsearch, + }); + xpackMainPlugin.status.once('green', async () => { // first time xpack_main turns green /* @@ -67,12 +75,6 @@ export class Plugin { const uiEnabled = config.get('monitoring.ui.enabled'); if (uiEnabled) { - await instantiateClient({ - log, - events, - elasticsearchConfig, - elasticsearchPlugin: plugins.elasticsearch, - }); // Instantiate the dedicated ES client await initMonitoringXpackInfo({ config, log, From 78bff535e03806bc8a452ba69642a55a33ce3066 Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Fri, 14 Feb 2020 18:16:50 -0500 Subject: [PATCH 13/32] moving visualize/utils to new platform (#56650) --- .../public/search/aggs/buckets/date_range.ts | 21 +-- .../public/search/aggs/buckets/ip_range.ts | 16 +- .../search/aggs/buckets/lib/date_range.ts | 36 +++++ .../search/aggs/buckets/lib/ip_range.ts | 32 ++++ .../components/metric_vis_component.test.tsx | 10 ++ .../public/metric_vis_type.test.ts | 3 + .../vis_type_vislib/public/legacy_imports.ts | 3 +- .../vislib/components/legend/legend.tsx | 14 +- .../loader/pipeline_helpers/utilities.ts | 149 +----------------- .../field_formats/field_formats_registry.ts | 9 +- .../data/common/field_formats/index.ts | 2 +- .../data/common/field_formats/utils/index.ts | 6 + .../common/field_formats/utils/serialize.ts | 53 +++++++ .../field_formats/field_formats_service.ts | 10 +- .../public/field_formats/utils/deserialize.ts | 129 +++++++++++++++ src/plugins/data/public/index.ts | 4 +- .../index_patterns/index_pattern.test.ts | 5 +- src/plugins/data/public/mocks.ts | 1 + .../query_string_input.test.tsx.snap | 6 + src/plugins/data/server/index.ts | 3 + src/test_utils/public/stub_field_formats.ts | 7 +- .../translations/translations/ja-JP.json | 3 +- .../translations/translations/zh-CN.json | 3 +- 23 files changed, 336 insertions(+), 189 deletions(-) create mode 100644 src/legacy/core_plugins/data/public/search/aggs/buckets/lib/date_range.ts create mode 100644 src/legacy/core_plugins/data/public/search/aggs/buckets/lib/ip_range.ts create mode 100644 src/plugins/data/common/field_formats/utils/serialize.ts create mode 100644 src/plugins/data/public/field_formats/utils/deserialize.ts diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts index 40ef7329dee6b..1dc24ca80035c 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts @@ -20,21 +20,19 @@ import { get } from 'lodash'; import moment from 'moment-timezone'; import { i18n } from '@kbn/i18n'; import { npStart } from 'ui/new_platform'; +import { convertDateRangeToString, DateRangeKey } from './lib/date_range'; import { BUCKET_TYPES } from './bucket_agg_types'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { createFilterDateRange } from './create_filter/date_range'; import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../../../plugins/data/public'; +export { convertDateRangeToString, DateRangeKey }; + const dateRangeTitle = i18n.translate('data.search.aggs.buckets.dateRangeTitle', { defaultMessage: 'Date Range', }); -export interface DateRangeKey { - from: number; - to: number; -} - export const dateRangeBucketAgg = new BucketAggType({ name: BUCKET_TYPES.DATE_RANGE, title: dateRangeTitle, @@ -106,16 +104,3 @@ export const dateRangeBucketAgg = new BucketAggType({ }, ], }); - -export const convertDateRangeToString = ( - { from, to }: DateRangeKey, - format: (val: any) => string -) => { - if (!from) { - return 'Before ' + format(to); - } else if (!to) { - return 'After ' + format(from); - } else { - return format(from) + ' to ' + format(to); - } -}; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts index e5497bef49165..91bdf53e7f809 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts @@ -20,21 +20,19 @@ import { noop, map, omit, isNull } from 'lodash'; import { i18n } from '@kbn/i18n'; import { npStart } from 'ui/new_platform'; +import { IpRangeKey, convertIPRangeToString } from './lib/ip_range'; import { BucketAggType } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; // @ts-ignore import { createFilterIpRange } from './create_filter/ip_range'; import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../../../plugins/data/public'; +export { IpRangeKey, convertIPRangeToString }; const ipRangeTitle = i18n.translate('data.search.aggs.buckets.ipRangeTitle', { defaultMessage: 'IPv4 Range', }); -export type IpRangeKey = - | { type: 'mask'; mask: string } - | { type: 'range'; from: string; to: string }; - export const ipRangeBucketAgg = new BucketAggType({ name: BUCKET_TYPES.IP_RANGE, title: ipRangeTitle, @@ -97,13 +95,3 @@ export const ipRangeBucketAgg = new BucketAggType({ }, ], }); - -export const convertIPRangeToString = (range: IpRangeKey, format: (val: any) => string) => { - if (range.type === 'mask') { - return format(range.mask); - } - const from = range.from ? format(range.from) : '-Infinity'; - const to = range.to ? format(range.to) : 'Infinity'; - - return `${from} to ${to}`; -}; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/lib/date_range.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/lib/date_range.ts new file mode 100644 index 0000000000000..01b853fc669b5 --- /dev/null +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/lib/date_range.ts @@ -0,0 +1,36 @@ +/* + * 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 interface DateRangeKey { + from: number; + to: number; +} + +export const convertDateRangeToString = ( + { from, to }: DateRangeKey, + format: (val: any) => string +) => { + if (!from) { + return 'Before ' + format(to); + } else if (!to) { + return 'After ' + format(from); + } else { + return format(from) + ' to ' + format(to); + } +}; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/lib/ip_range.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/lib/ip_range.ts new file mode 100644 index 0000000000000..be1ac28934c7c --- /dev/null +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/lib/ip_range.ts @@ -0,0 +1,32 @@ +/* + * 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 type IpRangeKey = + | { type: 'mask'; mask: string } + | { type: 'range'; from: string; to: string }; + +export const convertIPRangeToString = (range: IpRangeKey, format: (val: any) => string) => { + if (range.type === 'mask') { + return format(range.mask); + } + const from = range.from ? format(range.from) : '-Infinity'; + const to = range.to ? format(range.to) : 'Infinity'; + + return `${from} to ${to}`; +}; diff --git a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.test.tsx b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.test.tsx index 32c99f68a066e..6a466c9cd0211 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.test.tsx +++ b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.test.tsx @@ -22,6 +22,10 @@ import { shallow } from 'enzyme'; import { Vis } from 'src/legacy/core_plugins/visualizations/public'; import { MetricVisComponent, MetricVisComponentProps } from './metric_vis_component'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { npStart } from 'ui/new_platform'; +import { fieldFormats } from '../../../../../plugins/data/public'; +import { identity } from 'lodash'; jest.mock('ui/new_platform'); @@ -62,6 +66,12 @@ describe('MetricVisComponent', function() { return shallow(); }; + beforeAll(() => { + (npStart.plugins.data.fieldFormats.deserialize as jest.Mock).mockImplementation(() => { + return new (fieldFormats.FieldFormat.from(identity))(); + }); + }); + it('should render component', () => { expect(getComponent().exists()).toBe(true); }); diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts index 28565e0181b84..15cd920b79e4a 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts @@ -44,6 +44,9 @@ describe('metric_vis - createMetricVisTypeDefinition', () => { (npStart.plugins.data.fieldFormats.getType as jest.Mock).mockImplementation(() => { return fieldFormats.UrlFormat; }); + (npStart.plugins.data.fieldFormats.deserialize as jest.Mock).mockImplementation(mapping => { + return new fieldFormats.UrlFormat(mapping ? mapping.params : {}); + }); }); const setup = () => { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts index 3d04c04f9b1a6..9c79be98a320c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts @@ -18,10 +18,11 @@ */ export { AggType, AggGroupNames, IAggConfig, IAggType, Schemas } from 'ui/agg_types'; -export { getFormat, getTableAggs } from 'ui/visualize/loader/pipeline_helpers/utilities'; +export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; // @ts-ignore export { tabifyAggResponse } from 'ui/agg_response/tabify'; // @ts-ignore export { buildHierarchicalData } from 'ui/agg_response/hierarchical/build_hierarchical_data'; // @ts-ignore export { buildPointSeriesData } from 'ui/agg_response/point_series/point_series'; +export { tabifyGetColumns } from '../../../ui/public/agg_response/tabify/_get_columns'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx index a170af33583df..c1563625c3b8c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx @@ -22,14 +22,24 @@ import { compact, uniq, map } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiPopoverProps, EuiIcon, keyCodes, htmlIdGenerator } from '@elastic/eui'; +import { IAggConfig } from '../../../../../data/public'; // @ts-ignore -// eslint-disable-next-line @kbn/eslint/no-restricted-paths import { createFiltersFromEvent } from '../../../../../data/public/actions/filters/create_filters_from_event'; import { CUSTOM_LEGEND_VIS_TYPES, LegendItem } from './models'; import { VisLegendItem } from './legend_item'; import { getPieNames } from './pie_utils'; -import { getTableAggs } from '../../../legacy_imports'; + +import { Vis } from '../../../../../visualizations/public'; +import { tabifyGetColumns } from '../../../legacy_imports'; + +const getTableAggs = (vis: Vis): IAggConfig[] => { + if (!vis.aggs || !vis.aggs.getResponseAggs) { + return []; + } + const columns = tabifyGetColumns(vis.aggs.getResponseAggs(), !vis.isHierarchical()); + return columns.map(c => c.aggConfig); +}; export interface VisLegendProps { vis: any; diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts index 7228e506accb9..cb25c66dfd2fe 100644 --- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts +++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts @@ -17,150 +17,15 @@ * under the License. */ -import { i18n } from '@kbn/i18n'; -import { identity } from 'lodash'; -import { IAggConfig } from 'ui/agg_types'; import { npStart } from 'ui/new_platform'; -import { SerializedFieldFormat } from 'src/plugins/expressions/public'; -import { - fieldFormats, - IFieldFormat, - FieldFormatId, - FieldFormatsContentType, -} from '../../../../../../plugins/data/public'; -import { Vis } from '../../../../../core_plugins/visualizations/public'; +import { fieldFormats, IFieldFormat } from '../../../../../../plugins/data/public'; +import { SerializedFieldFormat } from '../../../../../../plugins/expressions/common/types'; -import { tabifyGetColumns } from '../../../agg_response/tabify/_get_columns'; -import { DateRangeKey, convertDateRangeToString } from '../../../agg_types'; -import { IpRangeKey, convertIPRangeToString } from '../../../agg_types'; +type FormatFactory = (mapping?: SerializedFieldFormat) => IFieldFormat; -interface TermsFieldFormatParams { - otherBucketLabel: string; - missingBucketLabel: string; - id: string; -} - -function isTermsFieldFormat( - serializedFieldFormat: SerializedFieldFormat -): serializedFieldFormat is SerializedFieldFormat { - return serializedFieldFormat.id === 'terms'; -} - -const getConfig = (key: string, defaultOverride?: any): any => - npStart.core.uiSettings.get(key, defaultOverride); -const DefaultFieldFormat = fieldFormats.FieldFormat.from(identity); - -const getFieldFormat = (id?: FieldFormatId, params: object = {}): IFieldFormat => { - const fieldFormatsService = npStart.plugins.data.fieldFormats; - - if (id) { - const Format = fieldFormatsService.getType(id); - - if (Format) { - return new Format(params, getConfig); - } - } - - return new DefaultFieldFormat(); -}; - -export const createFormat = (agg: IAggConfig): SerializedFieldFormat => { - const format: SerializedFieldFormat = agg.params.field ? agg.params.field.format.toJSON() : {}; - const formats: Record SerializedFieldFormat> = { - date_range: () => ({ id: 'date_range', params: format }), - ip_range: () => ({ id: 'ip_range', params: format }), - percentile_ranks: () => ({ id: 'percent' }), - count: () => ({ id: 'number' }), - cardinality: () => ({ id: 'number' }), - date_histogram: () => ({ - id: 'date', - params: { - pattern: (agg as any).buckets.getScaledDateFormat(), - }, - }), - terms: () => ({ - id: 'terms', - params: { - id: format.id, - otherBucketLabel: agg.params.otherBucketLabel, - missingBucketLabel: agg.params.missingBucketLabel, - ...format.params, - }, - }), - range: () => ({ - id: 'range', - params: { id: format.id, ...format.params }, - }), - }; - - return formats[agg.type.name] ? formats[agg.type.name]() : format; -}; - -export type FormatFactory = (mapping?: SerializedFieldFormat) => IFieldFormat; - -export const getFormat: FormatFactory = mapping => { - if (!mapping) { - return new DefaultFieldFormat(); - } - const { id } = mapping; - if (id === 'range') { - const RangeFormat = fieldFormats.FieldFormat.from((range: any) => { - const format = getFieldFormat(id, mapping.params); - const gte = '\u2265'; - const lt = '\u003c'; - return i18n.translate('common.ui.aggTypes.rangesFormatMessage', { - defaultMessage: '{gte} {from} and {lt} {to}', - values: { - gte, - from: format.convert(range.gte), - lt, - to: format.convert(range.lt), - }, - }); - }); - return new RangeFormat(); - } else if (id === 'date_range') { - const nestedFormatter = mapping.params as SerializedFieldFormat; - const DateRangeFormat = fieldFormats.FieldFormat.from((range: DateRangeKey) => { - const format = getFieldFormat(nestedFormatter.id, nestedFormatter.params); - return convertDateRangeToString(range, format.convert.bind(format)); - }); - return new DateRangeFormat(); - } else if (id === 'ip_range') { - const nestedFormatter = mapping.params as SerializedFieldFormat; - const IpRangeFormat = fieldFormats.FieldFormat.from((range: IpRangeKey) => { - const format = getFieldFormat(nestedFormatter.id, nestedFormatter.params); - return convertIPRangeToString(range, format.convert.bind(format)); - }); - return new IpRangeFormat(); - } else if (isTermsFieldFormat(mapping) && mapping.params) { - const { params } = mapping; - const convert = (val: string, type: FieldFormatsContentType) => { - const format = getFieldFormat(params.id, mapping.params); - - if (val === '__other__') { - return params.otherBucketLabel; - } - if (val === '__missing__') { - return params.missingBucketLabel; - } - - return format.convert(val, type); - }; - - return { - convert, - getConverterFor: (type: FieldFormatsContentType) => (val: string) => convert(val, type), - } as IFieldFormat; - } else { - return getFieldFormat(id, mapping.params); - } +const createFormat = fieldFormats.serialize; +const getFormat: FormatFactory = (mapping?) => { + return npStart.plugins.data.fieldFormats.deserialize(mapping as any); }; -export const getTableAggs = (vis: Vis): IAggConfig[] => { - if (!vis.aggs || !vis.aggs.getResponseAggs) { - return []; - } - const columns = tabifyGetColumns(vis.aggs.getResponseAggs(), !vis.isHierarchical()); - return columns.map(c => c.aggConfig); -}; +export { getFormat, createFormat, FormatFactory }; diff --git a/src/plugins/data/common/field_formats/field_formats_registry.ts b/src/plugins/data/common/field_formats/field_formats_registry.ts index 6e4880a221c46..9fe9a31307b6a 100644 --- a/src/plugins/data/common/field_formats/field_formats_registry.ts +++ b/src/plugins/data/common/field_formats/field_formats_registry.ts @@ -18,9 +18,9 @@ */ // eslint-disable-next-line max-classes-per-file -import { forOwn, isFunction, memoize } from 'lodash'; +import { forOwn, isFunction, memoize, identity } from 'lodash'; -import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../../common'; +import { ES_FIELD_TYPES, IFieldFormat, KBN_FIELD_TYPES } from '../../common'; import { FieldFormatsGetConfigFn, @@ -32,12 +32,17 @@ import { } from './types'; import { baseFormatters } from './constants/base_formatters'; import { FieldFormat } from './field_format'; +import { SerializedFieldFormat } from '../../../expressions/common/types'; export class FieldFormatsRegistry { protected fieldFormats: Map = new Map(); protected defaultMap: Record = {}; protected metaParamsOptions: Record = {}; protected getConfig?: FieldFormatsGetConfigFn; + // overriden on the public contract + public deserialize: (mapping: SerializedFieldFormat) => IFieldFormat = () => { + return new (FieldFormat.from(identity))(); + }; init( getConfig: FieldFormatsGetConfigFn, diff --git a/src/plugins/data/common/field_formats/index.ts b/src/plugins/data/common/field_formats/index.ts index 0847ac0db745f..d7858966f2620 100644 --- a/src/plugins/data/common/field_formats/index.ts +++ b/src/plugins/data/common/field_formats/index.ts @@ -41,7 +41,7 @@ export { TruncateFormat, } from './converters'; -export { getHighlightRequest } from './utils'; +export { getHighlightRequest, serializeFieldFormat } from './utils'; export { DEFAULT_CONVERTER_COLOR } from './constants/color_default'; export { FIELD_FORMAT_IDS } from './types'; diff --git a/src/plugins/data/common/field_formats/utils/index.ts b/src/plugins/data/common/field_formats/utils/index.ts index 81b33115a44bb..3832c941ffad7 100644 --- a/src/plugins/data/common/field_formats/utils/index.ts +++ b/src/plugins/data/common/field_formats/utils/index.ts @@ -17,5 +17,11 @@ * under the License. */ +import { SerializedFieldFormat } from '../../../../expressions/common/types'; +import { IFieldFormat } from '../index'; + export { asPrettyString } from './as_pretty_string'; export { getHighlightHtml, getHighlightRequest } from './highlight'; +export { serializeFieldFormat } from './serialize'; + +export type FormatFactory = (mapping?: SerializedFieldFormat) => IFieldFormat; diff --git a/src/plugins/data/common/field_formats/utils/serialize.ts b/src/plugins/data/common/field_formats/utils/serialize.ts new file mode 100644 index 0000000000000..9931f55c30a9e --- /dev/null +++ b/src/plugins/data/common/field_formats/utils/serialize.ts @@ -0,0 +1,53 @@ +/* + * 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 { IAggConfig } from '../../../../../legacy/ui/public/agg_types'; +import { SerializedFieldFormat } from '../../../../expressions/common/types'; + +export const serializeFieldFormat = (agg: IAggConfig): SerializedFieldFormat => { + const format: SerializedFieldFormat = agg.params.field ? agg.params.field.format.toJSON() : {}; + const formats: Record SerializedFieldFormat> = { + date_range: () => ({ id: 'date_range', params: format }), + ip_range: () => ({ id: 'ip_range', params: format }), + percentile_ranks: () => ({ id: 'percent' }), + count: () => ({ id: 'number' }), + cardinality: () => ({ id: 'number' }), + date_histogram: () => ({ + id: 'date', + params: { + pattern: (agg as any).buckets.getScaledDateFormat(), + }, + }), + terms: () => ({ + id: 'terms', + params: { + id: format.id, + otherBucketLabel: agg.params.otherBucketLabel, + missingBucketLabel: agg.params.missingBucketLabel, + ...format.params, + }, + }), + range: () => ({ + id: 'range', + params: { id: format.id, ...format.params }, + }), + }; + + return formats[agg.type.name] ? formats[agg.type.name]() : format; +}; diff --git a/src/plugins/data/public/field_formats/field_formats_service.ts b/src/plugins/data/public/field_formats/field_formats_service.ts index 1c43ce2198645..785bedf9b35d3 100644 --- a/src/plugins/data/public/field_formats/field_formats_service.ts +++ b/src/plugins/data/public/field_formats/field_formats_service.ts @@ -19,6 +19,8 @@ import { CoreSetup } from 'src/core/public'; import { FieldFormatsRegistry } from '../../common/field_formats'; +import { deserializeFieldFormat } from './utils/deserialize'; +import { FormatFactory } from '../../common/field_formats/utils'; export class FieldFormatsService { private readonly fieldFormatsRegistry: FieldFormatsRegistry = new FieldFormatsRegistry(); @@ -44,6 +46,10 @@ export class FieldFormatsService { } public start() { + this.fieldFormatsRegistry.deserialize = deserializeFieldFormat.bind( + this.fieldFormatsRegistry as FieldFormatsStart + ); + return this.fieldFormatsRegistry as FieldFormatsStart; } } @@ -52,4 +58,6 @@ export class FieldFormatsService { export type FieldFormatsSetup = Pick; /** @public */ -export type FieldFormatsStart = Omit; +export type FieldFormatsStart = Omit & { + deserialize: FormatFactory; +}; diff --git a/src/plugins/data/public/field_formats/utils/deserialize.ts b/src/plugins/data/public/field_formats/utils/deserialize.ts new file mode 100644 index 0000000000000..c10ebfbe3eb1e --- /dev/null +++ b/src/plugins/data/public/field_formats/utils/deserialize.ts @@ -0,0 +1,129 @@ +/* + * 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 { identity } from 'lodash'; +import { i18n } from '@kbn/i18n'; +import { + convertDateRangeToString, + DateRangeKey, +} from '../../../../../legacy/core_plugins/data/public/search/aggs/buckets/lib/date_range'; +import { + convertIPRangeToString, + IpRangeKey, +} from '../../../../../legacy/core_plugins/data/public/search/aggs/buckets/lib/ip_range'; +import { SerializedFieldFormat } from '../../../../expressions/common/types'; +import { FieldFormatId, FieldFormatsContentType, IFieldFormat } from '../..'; +import { FieldFormat } from '../../../common'; +import { DataPublicPluginStart } from '../../../public'; +import { getUiSettings } from '../../../public/services'; +import { FormatFactory } from '../../../common/field_formats/utils'; + +interface TermsFieldFormatParams { + otherBucketLabel: string; + missingBucketLabel: string; + id: string; +} + +function isTermsFieldFormat( + serializedFieldFormat: SerializedFieldFormat +): serializedFieldFormat is SerializedFieldFormat { + return serializedFieldFormat.id === 'terms'; +} + +const getConfig = (key: string, defaultOverride?: any): any => + getUiSettings().get(key, defaultOverride); +const DefaultFieldFormat = FieldFormat.from(identity); + +const getFieldFormat = ( + fieldFormatsService: DataPublicPluginStart['fieldFormats'], + id?: FieldFormatId, + params: object = {} +): IFieldFormat => { + if (id) { + const Format = fieldFormatsService.getType(id); + + if (Format) { + return new Format(params, getConfig); + } + } + + return new DefaultFieldFormat(); +}; + +export const deserializeFieldFormat: FormatFactory = function( + this: DataPublicPluginStart['fieldFormats'], + mapping?: SerializedFieldFormat +) { + if (!mapping) { + return new DefaultFieldFormat(); + } + const { id } = mapping; + if (id === 'range') { + const RangeFormat = FieldFormat.from((range: any) => { + const format = getFieldFormat(this, id, mapping.params); + const gte = '\u2265'; + const lt = '\u003c'; + return i18n.translate('data.aggTypes.buckets.ranges.rangesFormatMessage', { + defaultMessage: '{gte} {from} and {lt} {to}', + values: { + gte, + from: format.convert(range.gte), + lt, + to: format.convert(range.lt), + }, + }); + }); + return new RangeFormat(); + } else if (id === 'date_range') { + const nestedFormatter = mapping.params as SerializedFieldFormat; + const DateRangeFormat = FieldFormat.from((range: DateRangeKey) => { + const format = getFieldFormat(this, nestedFormatter.id, nestedFormatter.params); + return convertDateRangeToString(range, format.convert.bind(format)); + }); + return new DateRangeFormat(); + } else if (id === 'ip_range') { + const nestedFormatter = mapping.params as SerializedFieldFormat; + const IpRangeFormat = FieldFormat.from((range: IpRangeKey) => { + const format = getFieldFormat(this, nestedFormatter.id, nestedFormatter.params); + return convertIPRangeToString(range, format.convert.bind(format)); + }); + return new IpRangeFormat(); + } else if (isTermsFieldFormat(mapping) && mapping.params) { + const { params } = mapping; + const convert = (val: string, type: FieldFormatsContentType) => { + const format = getFieldFormat(this, params.id, mapping.params); + + if (val === '__other__') { + return params.otherBucketLabel; + } + if (val === '__missing__') { + return params.missingBucketLabel; + } + + return format.convert(val, type); + }; + + return { + convert, + getConverterFor: (type: FieldFormatsContentType) => (val: string) => convert(val, type), + } as IFieldFormat; + } else { + return getFieldFormat(this, id, mapping.params); + } +}; diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 8704ca08ae905..cdc4167f545af 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -168,6 +168,7 @@ import { UrlFormat, StringFormat, TruncateFormat, + serializeFieldFormat, } from '../common/field_formats'; // Field formats helpers namespace: @@ -175,6 +176,8 @@ export const fieldFormats = { FieldFormat, FieldFormatsRegistry, // exported only for tests. Consider mock. + serialize: serializeFieldFormat, + DEFAULT_CONVERTER_COLOR, HTML_CONTEXT_TYPE, TEXT_CONTEXT_TYPE, @@ -305,7 +308,6 @@ export { TimeHistoryContract, } from './query'; export * from './ui'; - export { // kbn field types castEsToKbnFieldTypeName, diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts index 103f9d385b3f9..b6ca91169a933 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts @@ -31,7 +31,7 @@ import { setNotifications, setFieldFormats } from '../../services'; // Temporary disable eslint, will be removed after moving to new platform folder // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { notificationServiceMock } from '../../../../../core/public/notifications/notifications_service.mock'; -import { FieldFormatsRegistry } from '../../../common/field_formats'; +import { FieldFormatsStart } from '../../field_formats'; jest.mock('../../../../kibana_utils/public', () => { const originalModule = jest.requireActual('../../../../kibana_utils/public'); @@ -125,7 +125,8 @@ describe('IndexPattern', () => { setNotifications(notifications); setFieldFormats(({ getDefaultInstance: jest.fn(), - } as unknown) as FieldFormatsRegistry); + deserialize: jest.fn() as any, + } as unknown) as FieldFormatsStart); return create(indexPatternId).then((pattern: IndexPattern) => { indexPattern = pattern; diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 0a093644c3939..c723c34cd0a22 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -49,6 +49,7 @@ const fieldFormatsMock: IFieldFormatsRegistry = { init: jest.fn(), register: jest.fn(), parseDefaultTypeMap: jest.fn(), + deserialize: jest.fn(), }; const createSetupContract = (): Setup => { diff --git a/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap b/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap index eebbc63f6f1e4..990386687bade 100644 --- a/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap +++ b/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap @@ -173,6 +173,7 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA "hasQuerySuggestions": [MockFunction], }, "fieldFormats": Object { + "deserialize": [MockFunction], "getByFieldType": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], @@ -825,6 +826,7 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA "hasQuerySuggestions": [MockFunction], }, "fieldFormats": Object { + "deserialize": [MockFunction], "getByFieldType": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], @@ -1459,6 +1461,7 @@ exports[`QueryStringInput Should pass the query language to the language switche "hasQuerySuggestions": [MockFunction], }, "fieldFormats": Object { + "deserialize": [MockFunction], "getByFieldType": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], @@ -2108,6 +2111,7 @@ exports[`QueryStringInput Should pass the query language to the language switche "hasQuerySuggestions": [MockFunction], }, "fieldFormats": Object { + "deserialize": [MockFunction], "getByFieldType": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], @@ -2742,6 +2746,7 @@ exports[`QueryStringInput Should render the given query 1`] = ` "hasQuerySuggestions": [MockFunction], }, "fieldFormats": Object { + "deserialize": [MockFunction], "getByFieldType": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], @@ -3391,6 +3396,7 @@ exports[`QueryStringInput Should render the given query 1`] = ` "hasQuerySuggestions": [MockFunction], }, "fieldFormats": Object { + "deserialize": [MockFunction], "getByFieldType": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index e8f422d94909f..3ee98a318de35 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -95,12 +95,15 @@ import { UrlFormat, StringFormat, TruncateFormat, + serializeFieldFormat, } from '../common/field_formats'; export const fieldFormats = { FieldFormatsRegistry, FieldFormat, + serializeFieldFormat, + BoolFormat, BytesFormat, ColorFormat, diff --git a/src/test_utils/public/stub_field_formats.ts b/src/test_utils/public/stub_field_formats.ts index 32bdca1eea258..5a20823134ebd 100644 --- a/src/test_utils/public/stub_field_formats.ts +++ b/src/test_utils/public/stub_field_formats.ts @@ -17,7 +17,8 @@ * under the License. */ import { CoreSetup } from 'kibana/public'; -import { fieldFormats } from '../../plugins/data/public'; +import { DataPublicPluginStart, fieldFormats } from '../../plugins/data/public'; +import { deserializeFieldFormat } from '../../plugins/data/public/field_formats/utils/deserialize'; export const getFieldFormatsRegistry = (core: CoreSetup) => { const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry(); @@ -25,5 +26,9 @@ export const getFieldFormatsRegistry = (core: CoreSetup) => { fieldFormatsRegistry.init(getConfig, {}); + fieldFormatsRegistry.deserialize = deserializeFieldFormat.bind( + fieldFormatsRegistry as DataPublicPluginStart['fieldFormats'] + ); + return fieldFormatsRegistry; }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 79b826bc4524f..ee2abeff74496 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -77,7 +77,6 @@ }, "messages": { "common.ui.aggResponse.allDocsTitle": "すべてのドキュメント", - "common.ui.aggTypes.rangesFormatMessage": "{gte} {from} と {lt} {to}", "common.ui.directives.paginate.size.allDropDownOptionLabel": "すべて", "common.ui.dualRangeControl.mustSetBothErrorMessage": "下と上の値の両方を設定する必要があります", "common.ui.dualRangeControl.outsideOfRangeErrorMessage": "値は {min} と {max} の間でなければなりません", @@ -13176,4 +13175,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。", "xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index ce1c713adc4bc..3210c619d3e52 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -77,7 +77,6 @@ }, "messages": { "common.ui.aggResponse.allDocsTitle": "所有文档", - "common.ui.aggTypes.rangesFormatMessage": "{gte} {from} 且 {lt} {to}", "common.ui.directives.paginate.size.allDropDownOptionLabel": "全部", "common.ui.dualRangeControl.mustSetBothErrorMessage": "下限值和上限值都须设置", "common.ui.dualRangeControl.outsideOfRangeErrorMessage": "值必须是在 {min} 到 {max} 的范围内", @@ -13175,4 +13174,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} \ No newline at end of file +} From 5d99576ab1a75956c3a77363781c61718840d46f Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 14 Feb 2020 16:17:07 -0700 Subject: [PATCH 14/32] [kbn/optimizer] throw errors into stream on invalid completion (#57735) --- .../kbn-optimizer/src/common/rxjs_helpers.ts | 6 +- .../handle_optimizer_completion.test.ts | 104 ++++++++++++++++++ .../optimizer/handle_optimizer_completion.ts | 56 ++++++++++ packages/kbn-optimizer/src/optimizer/index.ts | 1 + packages/kbn-optimizer/src/run_optimizer.ts | 4 +- 5 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts create mode 100644 packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.ts diff --git a/packages/kbn-optimizer/src/common/rxjs_helpers.ts b/packages/kbn-optimizer/src/common/rxjs_helpers.ts index 1114f65bacb19..f37bebb49efe9 100644 --- a/packages/kbn-optimizer/src/common/rxjs_helpers.ts +++ b/packages/kbn-optimizer/src/common/rxjs_helpers.ts @@ -24,9 +24,9 @@ type Operator = (source: Rx.Observable) => Rx.Observable; type MapFn = (item: T1, index: number) => T2; /** - * Wrap an operator chain in a closure so that is can have some local - * state. The `fn` is called each time the final observable is - * subscribed so the pipeline/closure is setup for each subscription. + * Wrap an operator chain in a closure so that it can have some local + * state. The `fn` is called each time the returned observable is + * subscribed; the closure is recreated for each subscription. */ export const pipeClosure = (fn: Operator): Operator => { return (source: Rx.Observable) => { diff --git a/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts b/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts new file mode 100644 index 0000000000000..7a8575a6c91fe --- /dev/null +++ b/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts @@ -0,0 +1,104 @@ +/* + * 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 * as Rx from 'rxjs'; +import { REPO_ROOT } from '@kbn/dev-utils'; + +import { Update } from '../common'; + +import { OptimizerState } from './optimizer_reducer'; +import { OptimizerConfig } from './optimizer_config'; +import { handleOptimizerCompletion } from './handle_optimizer_completion'; +import { toArray } from 'rxjs/operators'; + +const createUpdate$ = (phase: OptimizerState['phase']) => + Rx.of>({ + state: { + phase, + compilerStates: [], + durSec: 0, + offlineBundles: [], + onlineBundles: [], + startTime: Date.now(), + }, + }); + +const config = (watch?: boolean) => + OptimizerConfig.create({ + repoRoot: REPO_ROOT, + watch, + }); +const collect = (stream: Rx.Observable): Promise => stream.pipe(toArray()).toPromise(); + +it('errors if the optimizer completes when in watch mode', async () => { + const update$ = createUpdate$('success'); + + await expect( + collect(update$.pipe(handleOptimizerCompletion(config(true)))) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"optimizer unexpectedly completed when in watch mode"` + ); +}); + +it('errors if the optimizer completes in phase "issue"', async () => { + const update$ = createUpdate$('issue'); + + await expect( + collect(update$.pipe(handleOptimizerCompletion(config()))) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"webpack issue"`); +}); + +it('errors if the optimizer completes in phase "initializing"', async () => { + const update$ = createUpdate$('initializing'); + + await expect( + collect(update$.pipe(handleOptimizerCompletion(config()))) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"optimizer unexpectedly exit in phase \\"initializing\\""` + ); +}); + +it('errors if the optimizer completes in phase "reallocating"', async () => { + const update$ = createUpdate$('reallocating'); + + await expect( + collect(update$.pipe(handleOptimizerCompletion(config()))) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"optimizer unexpectedly exit in phase \\"reallocating\\""` + ); +}); + +it('errors if the optimizer completes in phase "running"', async () => { + const update$ = createUpdate$('running'); + + await expect( + collect(update$.pipe(handleOptimizerCompletion(config()))) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"optimizer unexpectedly exit in phase \\"running\\""` + ); +}); + +it('passes through errors on the source stream', async () => { + const error = new Error('foo'); + const update$ = Rx.throwError(error); + + await expect(collect(update$.pipe(handleOptimizerCompletion(config())))).rejects.toThrowError( + error + ); +}); diff --git a/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.ts b/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.ts new file mode 100644 index 0000000000000..fe2fa320818a2 --- /dev/null +++ b/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.ts @@ -0,0 +1,56 @@ +/* + * 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 * as Rx from 'rxjs'; +import { tap } from 'rxjs/operators'; +import { createFailError } from '@kbn/dev-utils'; + +import { pipeClosure, Update } from '../common'; + +import { OptimizerState } from './optimizer_reducer'; +import { OptimizerConfig } from './optimizer_config'; + +export function handleOptimizerCompletion(config: OptimizerConfig) { + return pipeClosure((source$: Rx.Observable>) => { + let prevState: OptimizerState | undefined; + + return source$.pipe( + tap({ + next: update => { + prevState = update.state; + }, + complete: () => { + if (config.watch) { + throw new Error('optimizer unexpectedly completed when in watch mode'); + } + + if (prevState?.phase === 'success') { + return; + } + + if (prevState?.phase === 'issue') { + throw createFailError('webpack issue'); + } + + throw new Error(`optimizer unexpectedly exit in phase "${prevState?.phase}"`); + }, + }) + ); + }); +} diff --git a/packages/kbn-optimizer/src/optimizer/index.ts b/packages/kbn-optimizer/src/optimizer/index.ts index b7f14cf3c517f..3df8ed9302668 100644 --- a/packages/kbn-optimizer/src/optimizer/index.ts +++ b/packages/kbn-optimizer/src/optimizer/index.ts @@ -24,3 +24,4 @@ export * from './cache_keys'; export * from './watch_bundles_for_changes'; export * from './run_workers'; export * from './bundle_cache'; +export * from './handle_optimizer_completion'; diff --git a/packages/kbn-optimizer/src/run_optimizer.ts b/packages/kbn-optimizer/src/run_optimizer.ts index e6cce8d306e35..d2daa79feab7e 100644 --- a/packages/kbn-optimizer/src/run_optimizer.ts +++ b/packages/kbn-optimizer/src/run_optimizer.ts @@ -32,6 +32,7 @@ import { runWorkers, OptimizerInitializedEvent, createOptimizerReducer, + handleOptimizerCompletion, } from './optimizer'; export type OptimizerUpdate = Update; @@ -77,6 +78,7 @@ export function runOptimizer(config: OptimizerConfig) { }, createOptimizerReducer(config) ); - }) + }), + handleOptimizerCompletion(config) ); } From 96c39a5a14fbc867f43f46fe3d7d9acb37a0ded6 Mon Sep 17 00:00:00 2001 From: Patrick Mueller Date: Fri, 14 Feb 2020 18:29:50 -0500 Subject: [PATCH 15/32] change slack action to only report on whitelisted host name (#57582) Previously, when using the slack action with a url which was not whitelisted, the entire URL was reported in the error. With this change, only the hostname is reported in the error. --- .../server/builtin_action_types/slack.test.ts | 12 ++++++--- .../server/builtin_action_types/slack.ts | 12 ++++++++- .../actions/builtin_action_types/slack.ts | 26 +++++++++++++++++-- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts b/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts index d33574666cebd..919f0800c291c 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts @@ -74,6 +74,12 @@ describe('validateActionTypeSecrets()', () => { }).toThrowErrorMatchingInlineSnapshot( `"error validating action type secrets: [webhookUrl]: expected value of type [string] but got [number]"` ); + + expect(() => { + validateSecrets(actionType, { webhookUrl: 'fee-fi-fo-fum' }); + }).toThrowErrorMatchingInlineSnapshot( + `"error validating action type secrets: error configuring slack action: unable to parse host name from webhookUrl"` + ); }); test('should validate and pass when the slack webhookUrl is whitelisted', () => { @@ -95,8 +101,8 @@ describe('validateActionTypeSecrets()', () => { actionType = getActionType({ configurationUtilities: { ...configUtilsMock, - ensureWhitelistedUri: url => { - throw new Error(`target url is not whitelisted`); + ensureWhitelistedHostname: url => { + throw new Error(`target hostname is not whitelisted`); }, }, }); @@ -104,7 +110,7 @@ describe('validateActionTypeSecrets()', () => { expect(() => { validateSecrets(actionType, { webhookUrl: 'https://api.slack.com/' }); }).toThrowErrorMatchingInlineSnapshot( - `"error validating action type secrets: error configuring slack action: target url is not whitelisted"` + `"error validating action type secrets: error configuring slack action: target hostname is not whitelisted"` ); }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/slack.ts b/x-pack/plugins/actions/server/builtin_action_types/slack.ts index b8989e59a2257..042853796695d 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/slack.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/slack.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { URL } from 'url'; import { curry } from 'lodash'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; @@ -66,8 +67,17 @@ function valdiateActionTypeConfig( configurationUtilities: ActionsConfigurationUtilities, secretsObject: ActionTypeSecretsType ) { + let url: URL; try { - configurationUtilities.ensureWhitelistedUri(secretsObject.webhookUrl); + url = new URL(secretsObject.webhookUrl); + } catch (err) { + return i18n.translate('xpack.actions.builtin.slack.slackConfigurationErrorNoHostname', { + defaultMessage: 'error configuring slack action: unable to parse host name from webhookUrl', + }); + } + + try { + configurationUtilities.ensureWhitelistedHostname(url.hostname); } catch (whitelistError) { return i18n.translate('xpack.actions.builtin.slack.slackConfigurationError', { defaultMessage: 'error configuring slack action: {message}', diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts index 87280169c0960..5dcff8712a28d 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts @@ -94,7 +94,7 @@ export default function slackTest({ getService }: FtrProviderContext) { name: 'A slack action', actionTypeId: '.slack', secrets: { - webhookUrl: 'http://slack.mynonexistent.com', + webhookUrl: 'http://slack.mynonexistent.com/other/stuff/in/the/path', }, }) .expect(400) @@ -103,7 +103,29 @@ export default function slackTest({ getService }: FtrProviderContext) { statusCode: 400, error: 'Bad Request', message: - 'error validating action type secrets: error configuring slack action: target url "http://slack.mynonexistent.com" is not whitelisted in the Kibana config xpack.actions.whitelistedHosts', + 'error validating action type secrets: error configuring slack action: target hostname "slack.mynonexistent.com" is not whitelisted in the Kibana config xpack.actions.whitelistedHosts', + }); + }); + }); + + it('should respond with a 400 Bad Request when creating a slack action with a webhookUrl with no hostname', async () => { + await supertest + .post('/api/action') + .set('kbn-xsrf', 'foo') + .send({ + name: 'A slack action', + actionTypeId: '.slack', + secrets: { + webhookUrl: 'fee-fi-fo-fum', + }, + }) + .expect(400) + .then((resp: any) => { + expect(resp.body).to.eql({ + statusCode: 400, + error: 'Bad Request', + message: + 'error validating action type secrets: error configuring slack action: unable to parse host name from webhookUrl', }); }); }); From 95b713e69d37f70755353be15abf8ca07999ee0c Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Sat, 15 Feb 2020 00:43:32 +0100 Subject: [PATCH 16/32] update chromedriver to 80.0.1 (#57602) Co-authored-by: Elastic Machine --- package.json | 4 ++-- yarn.lock | 32 +++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 3156e87e763b2..e801f75b976f8 100644 --- a/package.json +++ b/package.json @@ -294,8 +294,8 @@ "@kbn/eslint-import-resolver-kibana": "2.0.0", "@kbn/eslint-plugin-eslint": "1.0.0", "@kbn/expect": "1.0.0", - "@kbn/plugin-generator": "1.0.0", "@kbn/optimizer": "1.0.0", + "@kbn/plugin-generator": "1.0.0", "@kbn/test": "1.0.0", "@kbn/utility-types": "1.0.0", "@microsoft/api-documenter": "7.7.2", @@ -394,7 +394,7 @@ "chai": "3.5.0", "chance": "1.0.18", "cheerio": "0.22.0", - "chromedriver": "79.0.0", + "chromedriver": "^80.0.1", "classnames": "2.2.6", "dedent": "^0.7.0", "delete-empty": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index cac39dfd4c352..33cb366e72f00 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3996,6 +3996,11 @@ "@svgr/plugin-svgo" "^4.2.0" loader-utils "^1.2.3" +"@testim/chrome-version@^1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@testim/chrome-version/-/chrome-version-1.0.7.tgz#0cd915785ec4190f08a3a6acc9b61fc38fb5f1a9" + integrity sha512-8UT/J+xqCYfn3fKtOznAibsHpiuDshCb0fwgWxRazTT19Igp9ovoXMPhXyLD6m3CKQGTMHgqoxaFfMWaL40Rnw== + "@testing-library/dom@^6.3.0": version "6.10.1" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-6.10.1.tgz#da5bf5065d3f9e484aef4cc495f4e1a5bea6df2e" @@ -7114,6 +7119,13 @@ axios@^0.19.0: follow-redirects "1.5.10" is-buffer "^2.0.2" +axios@^0.19.2: + version "0.19.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" + integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== + dependencies: + follow-redirects "1.5.10" + axobject-query@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9" @@ -9049,15 +9061,16 @@ chrome-trace-event@^1.0.2: dependencies: tslib "^1.9.0" -chromedriver@79.0.0: - version "79.0.0" - resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-79.0.0.tgz#1660ac29924dfcd847911025593d6b6746aeea35" - integrity sha512-DO29C7ntJfzu6q1vuoWwCON8E9x5xzopt7Q41A7Dr7hBKcdNpGw1l9DTt9b+l1qviOWiJLGsD+jHw21ptEHubA== +chromedriver@^80.0.1: + version "80.0.1" + resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-80.0.1.tgz#35c1642e2d864b9e8262f291003e455b0e422917" + integrity sha512-VfRtZUpBUIjeypS+xM40+VD9g4Drv7L2VibG/4+0zX3mMx4KayN6gfKETycPfO6JwQXTLSxEr58fRcrsa8r5xQ== dependencies: - del "^4.1.1" + "@testim/chrome-version" "^1.0.7" + axios "^0.19.2" + del "^5.1.0" extract-zip "^1.6.7" - mkdirp "^0.5.1" - request "^2.88.0" + mkdirp "^1.0.3" tcp-port-used "^1.0.1" ci-info@^1.0.0: @@ -20795,6 +20808,11 @@ mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdi dependencies: minimist "0.0.8" +mkdirp@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea" + integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g== + mocha-junit-reporter@^1.23.1: version "1.23.1" resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.23.1.tgz#ba11519c0b967f404e4123dd69bc4ba022ab0f12" From 0cee1a4adb0940ed911daf2ddf50ff15f40fa539 Mon Sep 17 00:00:00 2001 From: spalger Date: Fri, 14 Feb 2020 18:46:01 -0700 Subject: [PATCH 17/32] skip flaky suite (#45244) --- .../apps/visualize/feature_controls/visualize_spaces.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts b/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts index 066042896c122..b24c537d25085 100644 --- a/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts +++ b/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts @@ -20,7 +20,8 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const appsMenu = getService('appsMenu'); - describe('visualize', () => { + // FLAKY: https://github.com/elastic/kibana/issues/45244 + describe.skip('visualize', () => { before(async () => { await esArchiver.loadIfNeeded('logstash_functional'); }); From 15e4e6c6327a63e19692f372791ae6dff6d102d8 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 14 Feb 2020 18:47:32 -0700 Subject: [PATCH 18/32] Fix failed test reporter for SIEM Cypress use (#57240) * [@kbn/test] build with source-maps * [@kbn/test] the jUnit Reporter being used for SIEM Cypress tests sometimes doesn't include testcases in XML Co-authored-by: Elastic Machine --- packages/kbn-test/package.json | 2 +- packages/kbn-test/src/failed_tests_reporter/test_report.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index 0cc54fa2a64c4..a01c4ebab8ad0 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -5,7 +5,7 @@ "license": "Apache-2.0", "private": true, "scripts": { - "build": "babel src --out-dir target --delete-dir-on-start --extensions .ts,.js,.tsx --ignore *.test.js,**/__tests__/**", + "build": "babel src --out-dir target --delete-dir-on-start --extensions .ts,.js,.tsx --ignore *.test.js,**/__tests__/** --source-maps=inline", "kbn:bootstrap": "yarn build", "kbn:watch": "yarn build --watch" }, diff --git a/packages/kbn-test/src/failed_tests_reporter/test_report.ts b/packages/kbn-test/src/failed_tests_reporter/test_report.ts index 6b759ef1d4c62..43d84163462d3 100644 --- a/packages/kbn-test/src/failed_tests_reporter/test_report.ts +++ b/packages/kbn-test/src/failed_tests_reporter/test_report.ts @@ -47,7 +47,7 @@ export interface TestSuite { /* number of skipped tests as a string */ skipped: string; }; - testcase: TestCase[]; + testcase?: TestCase[]; } export interface TestCase { @@ -89,7 +89,7 @@ export function* makeTestCaseIter(report: TestReport) { const testSuites = 'testsuites' in report ? report.testsuites.testsuite : [report.testsuite]; for (const testSuite of testSuites) { - for (const testCase of testSuite.testcase) { + for (const testCase of testSuite.testcase || []) { yield testCase; } } From 6e3790537d4ad3456f053afe76f4eea8fd7ea7c3 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Fri, 14 Feb 2020 21:10:33 -0500 Subject: [PATCH 19/32] [Remote clusters] Migrate client-side code out of legacy (#57365) --- .github/CODEOWNERS | 2 +- x-pack/.i18nrc.json | 2 +- .../helpers/setup_environment.js | 35 ----- .../common/cluster_serialization.test.ts | 137 ------------------ .../common/cluster_serialization.ts | 71 --------- .../plugins/remote_clusters/common/index.ts | 14 -- .../legacy/plugins/remote_clusters/index.ts | 14 +- .../components/connection_status/_index.scss | 6 - .../public/app/services/http.ts | 39 ----- .../plugins/remote_clusters/public/index.html | 3 - .../plugins/remote_clusters/public/index.js | 12 -- .../plugins/remote_clusters/public/index.scss | 11 +- .../plugins/remote_clusters/public/plugin.js | 123 ---------------- .../plugins/remote_clusters/public/shim.ts | 42 ------ .../client_integration/helpers/constants.js | 0 .../helpers/http_requests.js | 0 .../client_integration/helpers/index.js | 2 +- .../helpers/remote_clusters_add.helpers.js | 10 +- .../helpers/remote_clusters_edit.helpers.js | 10 +- .../helpers/remote_clusters_list.helpers.js | 10 +- .../helpers/setup_environment.js | 48 ++++++ .../remote_clusters_add.test.js | 0 .../remote_clusters_edit.test.js | 4 +- .../remote_clusters_list.test.js | 12 +- .../fixtures/remote_cluster.js | 2 +- x-pack/plugins/remote_clusters/kibana.json | 12 +- .../public/application}/app.js | 0 .../public/application}/constants/index.ts | 0 .../public/application}/constants/paths.ts | 0 .../application}/constants/ui_metric.ts | 0 .../public/application/index.d.ts} | 15 +- .../public/application}/index.js | 5 +- .../configured_by_node_warning.js | 0 .../configured_by_node_warning/index.js | 0 .../application}/sections/components/index.js | 0 .../remote_cluster_form.test.js.snap | 0 .../components/remote_cluster_form/index.js | 0 .../remote_cluster_form.js | 2 +- .../remote_cluster_form.test.js | 0 .../remote_cluster_form/request_flyout.js | 2 +- .../__snapshots__/validate_name.test.js.snap | 0 .../__snapshots__/validate_seeds.test.js.snap | 0 .../remote_cluster_form/validators/index.js | 0 .../validators/validate_name.js | 0 .../validators/validate_name.test.js | 0 .../validators/validate_seed.js | 0 .../validators/validate_seed.test.js | 0 .../validators/validate_seeds.js | 0 .../validators/validate_seeds.test.js | 0 .../remote_cluster_page_title/index.js | 0 .../remote_cluster_page_title.js | 0 .../public/application}/sections/index.js | 0 .../sections/remote_cluster_add/index.js | 0 .../remote_cluster_add.container.js | 0 .../remote_cluster_add/remote_cluster_add.js | 0 .../sections/remote_cluster_edit/index.js | 0 .../remote_cluster_edit.container.js | 0 .../remote_cluster_edit.js | 0 .../connection_status/connection_status.js | 0 .../components/connection_status/index.js | 0 .../remote_cluster_list/components/index.js | 0 .../remove_cluster_button_provider/index.js | 0 ...emove_cluster_button_provider.container.js | 0 .../remove_cluster_button_provider.js | 0 .../detail_panel/detail_panel.container.js | 0 .../detail_panel/detail_panel.js | 0 .../remote_cluster_list/detail_panel/index.js | 0 .../sections/remote_cluster_list/index.js | 0 .../remote_cluster_list.container.js | 0 .../remote_cluster_list.js | 4 +- .../remote_cluster_table/index.js | 0 .../remote_cluster_table.container.js | 0 .../remote_cluster_table.js | 0 .../public/application}/services/api.js | 6 +- .../application}/services/api_errors.js | 12 +- .../application}/services/breadcrumb.ts | 23 ++- .../application}/services/documentation.ts | 7 +- .../public/application/services/http.ts | 55 +++++++ .../public/application}/services/index.js | 2 +- .../application/services/notification.ts | 15 ++ .../application}/services/query_params.js | 0 .../public/application/services/redirect.ts | 17 +++ .../public/application}/services/routing.js | 0 .../public/application}/services/ui_metric.ts | 15 +- .../services/validate_seed_node.js | 0 .../services/validate_seed_node.test.js | 0 .../public/application}/store/action_types.js | 0 .../application}/store/actions/add_cluster.js | 15 +- .../store/actions/detail_panel.js | 0 .../store/actions/edit_cluster.js | 14 +- .../application}/store/actions/index.js | 0 .../store/actions/load_clusters.js | 0 .../store/actions/refresh_clusters.js | 0 .../store/actions/remove_clusters.js | 6 +- .../public/application}/store/index.js | 0 .../store/middleware/detail_panel.js | 0 .../application}/store/middleware/index.js | 0 .../store/reducers/add_cluster.js | 0 .../application}/store/reducers/clusters.js | 0 .../store/reducers/detail_panel.js | 0 .../store/reducers/edit_cluster.js | 0 .../application}/store/reducers/index.js | 0 .../store/reducers/remove_cluster.js | 0 .../application}/store/selectors/index.js | 0 .../public/application}/store/store.js | 0 .../remote_clusters/public/index.ts} | 9 +- .../plugins/remote_clusters/public/plugin.ts | 55 +++++++ .../plugins/remote_clusters/public/types.ts | 19 +++ .../plugins/remote_clusters/server/config.ts | 21 +++ .../plugins/remote_clusters/server/index.ts | 2 + .../plugins/remote_clusters/server/plugin.ts | 10 +- .../server/routes/api/add_route.ts | 3 +- .../server/routes/api/update_route.ts | 3 +- 113 files changed, 362 insertions(+), 596 deletions(-) delete mode 100644 x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js delete mode 100644 x-pack/legacy/plugins/remote_clusters/common/cluster_serialization.test.ts delete mode 100644 x-pack/legacy/plugins/remote_clusters/common/cluster_serialization.ts delete mode 100644 x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/connection_status/_index.scss delete mode 100644 x-pack/legacy/plugins/remote_clusters/public/app/services/http.ts delete mode 100644 x-pack/legacy/plugins/remote_clusters/public/index.html delete mode 100644 x-pack/legacy/plugins/remote_clusters/public/index.js delete mode 100644 x-pack/legacy/plugins/remote_clusters/public/plugin.js delete mode 100644 x-pack/legacy/plugins/remote_clusters/public/shim.ts rename x-pack/{legacy => }/plugins/remote_clusters/__jest__/client_integration/helpers/constants.js (100%) rename x-pack/{legacy => }/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.js (100%) rename x-pack/{legacy => }/plugins/remote_clusters/__jest__/client_integration/helpers/index.js (96%) rename x-pack/{legacy => }/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_add.helpers.js (66%) rename x-pack/{legacy => }/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_edit.helpers.js (68%) rename x-pack/{legacy => }/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_list.helpers.js (88%) create mode 100644 x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js rename x-pack/{legacy => }/plugins/remote_clusters/__jest__/client_integration/remote_clusters_add.test.js (100%) rename x-pack/{legacy => }/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js (93%) rename x-pack/{legacy => }/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.js (96%) rename x-pack/{legacy => }/plugins/remote_clusters/fixtures/remote_cluster.js (91%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/app.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/constants/index.ts (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/constants/paths.ts (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/constants/ui_metric.ts (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app/services/redirect.js => plugins/remote_clusters/public/application/index.d.ts} (50%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/index.js (80%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/configured_by_node_warning/configured_by_node_warning.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/configured_by_node_warning/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/remote_cluster_form.js (99%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/remote_cluster_form.test.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/request_flyout.js (97%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/validators/__snapshots__/validate_name.test.js.snap (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/validators/__snapshots__/validate_seeds.test.js.snap (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/validators/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/validators/validate_name.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/validators/validate_name.test.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/validators/validate_seed.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/validators/validate_seed.test.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/validators/validate_seeds.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_form/validators/validate_seeds.test.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_page_title/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/components/remote_cluster_page_title/remote_cluster_page_title.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_add/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_add/remote_cluster_add.container.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_add/remote_cluster_add.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_edit/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_edit/remote_cluster_edit.container.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_edit/remote_cluster_edit.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/components/connection_status/connection_status.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/components/connection_status/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/components/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/components/remove_cluster_button_provider/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/components/remove_cluster_button_provider/remove_cluster_button_provider.container.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/components/remove_cluster_button_provider/remove_cluster_button_provider.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/detail_panel/detail_panel.container.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/detail_panel/detail_panel.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/detail_panel/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/remote_cluster_list.container.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/remote_cluster_list.js (98%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/remote_cluster_table/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/remote_cluster_table/remote_cluster_table.container.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/sections/remote_cluster_list/remote_cluster_table/remote_cluster_table.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/services/api.js (93%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/services/api_errors.js (77%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/services/breadcrumb.ts (68%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/services/documentation.ts (70%) create mode 100644 x-pack/plugins/remote_clusters/public/application/services/http.ts rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/services/index.js (93%) create mode 100644 x-pack/plugins/remote_clusters/public/application/services/notification.ts rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/services/query_params.js (100%) create mode 100644 x-pack/plugins/remote_clusters/public/application/services/redirect.ts rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/services/routing.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/services/ui_metric.ts (62%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/services/validate_seed_node.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/services/validate_seed_node.test.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/action_types.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/actions/add_cluster.js (88%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/actions/detail_panel.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/actions/edit_cluster.js (90%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/actions/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/actions/load_clusters.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/actions/refresh_clusters.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/actions/remove_clusters.js (95%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/middleware/detail_panel.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/middleware/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/reducers/add_cluster.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/reducers/clusters.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/reducers/detail_panel.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/reducers/edit_cluster.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/reducers/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/reducers/remove_cluster.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/selectors/index.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app => plugins/remote_clusters/public/application}/store/store.js (100%) rename x-pack/{legacy/plugins/remote_clusters/public/app/services/notification.ts => plugins/remote_clusters/public/index.ts} (59%) create mode 100644 x-pack/plugins/remote_clusters/public/plugin.ts create mode 100644 x-pack/plugins/remote_clusters/public/types.ts create mode 100644 x-pack/plugins/remote_clusters/server/config.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bf1e341c796fa..e54b7b56707e8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -170,7 +170,7 @@ /x-pack/legacy/plugins/index_lifecycle_management/ @elastic/es-ui /x-pack/legacy/plugins/index_management/ @elastic/es-ui /x-pack/legacy/plugins/license_management/ @elastic/es-ui -/x-pack/legacy/plugins/remote_clusters/ @elastic/es-ui +/x-pack/plugins/remote_clusters/ @elastic/es-ui /x-pack/legacy/plugins/rollup/ @elastic/es-ui /x-pack/plugins/searchprofiler/ @elastic/es-ui /x-pack/legacy/plugins/snapshot_restore/ @elastic/es-ui diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 27da54042594d..032efcee20afd 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -27,7 +27,7 @@ "xpack.maps": "legacy/plugins/maps", "xpack.ml": "legacy/plugins/ml", "xpack.monitoring": "legacy/plugins/monitoring", - "xpack.remoteClusters": ["plugins/remote_clusters", "legacy/plugins/remote_clusters"], + "xpack.remoteClusters": "plugins/remote_clusters", "xpack.reporting": ["plugins/reporting", "legacy/plugins/reporting"], "xpack.rollupJobs": "legacy/plugins/rollup", "xpack.searchProfiler": "plugins/searchprofiler", diff --git a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js b/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js deleted file mode 100644 index d2385dc900bb2..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js +++ /dev/null @@ -1,35 +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 axios from 'axios'; -import axiosXhrAdapter from 'axios/lib/adapters/xhr'; -import chrome from 'ui/chrome'; // eslint-disable-line import/no-unresolved -import { MANAGEMENT_BREADCRUMB } from 'ui/management'; // eslint-disable-line import/no-unresolved -import { fatalError, toastNotifications } from 'ui/notify'; // eslint-disable-line import/no-unresolved - -import { init as initBreadcrumb } from '../../../public/app/services/breadcrumb'; -import { init as initHttp } from '../../../public/app/services/http'; -import { init as initNotification } from '../../../public/app/services/notification'; -import { init as initUiMetric } from '../../../public/app/services/ui_metric'; -import { init as initHttpRequests } from './http_requests'; - -export const setupEnvironment = () => { - chrome.breadcrumbs = { - set: () => {}, - }; - // axios has a $http like interface so using it to simulate $http - initHttp(axios.create({ adapter: axiosXhrAdapter }), path => path); - initBreadcrumb(() => {}, MANAGEMENT_BREADCRUMB); - initNotification(toastNotifications, fatalError); - initUiMetric(() => () => {}); - - const { server, httpRequestsMockHelpers } = initHttpRequests(); - - return { - server, - httpRequestsMockHelpers, - }; -}; diff --git a/x-pack/legacy/plugins/remote_clusters/common/cluster_serialization.test.ts b/x-pack/legacy/plugins/remote_clusters/common/cluster_serialization.test.ts deleted file mode 100644 index 476fbee7fb6a0..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/common/cluster_serialization.test.ts +++ /dev/null @@ -1,137 +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 { deserializeCluster, serializeCluster } from './cluster_serialization'; - -describe('cluster_serialization', () => { - describe('deserializeCluster()', () => { - it('should throw an error for invalid arguments', () => { - expect(() => deserializeCluster('foo', 'bar')).toThrowError(); - }); - - it('should deserialize a complete cluster object', () => { - expect( - deserializeCluster('test_cluster', { - seeds: ['localhost:9300'], - connected: true, - num_nodes_connected: 1, - max_connections_per_cluster: 3, - initial_connect_timeout: '30s', - skip_unavailable: false, - transport: { - ping_schedule: '-1', - compress: false, - }, - }) - ).toEqual({ - name: 'test_cluster', - seeds: ['localhost:9300'], - isConnected: true, - connectedNodesCount: 1, - maxConnectionsPerCluster: 3, - initialConnectTimeout: '30s', - skipUnavailable: false, - transportPingSchedule: '-1', - transportCompress: false, - }); - }); - - it('should deserialize a cluster object without transport information', () => { - expect( - deserializeCluster('test_cluster', { - seeds: ['localhost:9300'], - connected: true, - num_nodes_connected: 1, - max_connections_per_cluster: 3, - initial_connect_timeout: '30s', - skip_unavailable: false, - }) - ).toEqual({ - name: 'test_cluster', - seeds: ['localhost:9300'], - isConnected: true, - connectedNodesCount: 1, - maxConnectionsPerCluster: 3, - initialConnectTimeout: '30s', - skipUnavailable: false, - }); - }); - - it('should deserialize a cluster object with arbitrary missing properties', () => { - expect( - deserializeCluster('test_cluster', { - seeds: ['localhost:9300'], - connected: true, - num_nodes_connected: 1, - initial_connect_timeout: '30s', - transport: { - compress: false, - }, - }) - ).toEqual({ - name: 'test_cluster', - seeds: ['localhost:9300'], - isConnected: true, - connectedNodesCount: 1, - initialConnectTimeout: '30s', - transportCompress: false, - }); - }); - }); - - describe('serializeCluster()', () => { - it('should throw an error for invalid arguments', () => { - expect(() => serializeCluster('foo')).toThrowError(); - }); - - it('should serialize a complete cluster object to only dynamic properties', () => { - expect( - serializeCluster({ - name: 'test_cluster', - seeds: ['localhost:9300'], - isConnected: true, - connectedNodesCount: 1, - maxConnectionsPerCluster: 3, - initialConnectTimeout: '30s', - skipUnavailable: false, - transportPingSchedule: '-1', - transportCompress: false, - }) - ).toEqual({ - persistent: { - cluster: { - remote: { - test_cluster: { - seeds: ['localhost:9300'], - skip_unavailable: false, - }, - }, - }, - }, - }); - }); - - it('should serialize a cluster object with missing properties', () => { - expect( - serializeCluster({ - name: 'test_cluster', - seeds: ['localhost:9300'], - }) - ).toEqual({ - persistent: { - cluster: { - remote: { - test_cluster: { - seeds: ['localhost:9300'], - skip_unavailable: null, - }, - }, - }, - }, - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/remote_clusters/common/cluster_serialization.ts b/x-pack/legacy/plugins/remote_clusters/common/cluster_serialization.ts deleted file mode 100644 index 07ea79d42b800..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/common/cluster_serialization.ts +++ /dev/null @@ -1,71 +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. - */ - -export function deserializeCluster(name: string, esClusterObject: any): any { - if (!name || !esClusterObject || typeof esClusterObject !== 'object') { - throw new Error('Unable to deserialize cluster'); - } - - const { - seeds, - connected: isConnected, - num_nodes_connected: connectedNodesCount, - max_connections_per_cluster: maxConnectionsPerCluster, - initial_connect_timeout: initialConnectTimeout, - skip_unavailable: skipUnavailable, - transport, - } = esClusterObject; - - let deserializedClusterObject: any = { - name, - seeds, - isConnected, - connectedNodesCount, - maxConnectionsPerCluster, - initialConnectTimeout, - skipUnavailable, - }; - - if (transport) { - const { ping_schedule: transportPingSchedule, compress: transportCompress } = transport; - - deserializedClusterObject = { - ...deserializedClusterObject, - transportPingSchedule, - transportCompress, - }; - } - - // It's unnecessary to send undefined values back to the client, so we can remove them. - Object.keys(deserializedClusterObject).forEach(key => { - if (deserializedClusterObject[key] === undefined) { - delete deserializedClusterObject[key]; - } - }); - - return deserializedClusterObject; -} - -export function serializeCluster(deserializedClusterObject: any): any { - if (!deserializedClusterObject || typeof deserializedClusterObject !== 'object') { - throw new Error('Unable to serialize cluster'); - } - - const { name, seeds, skipUnavailable } = deserializedClusterObject; - - return { - persistent: { - cluster: { - remote: { - [name]: { - seeds: seeds ? seeds : null, - skip_unavailable: skipUnavailable !== undefined ? skipUnavailable : null, - }, - }, - }, - }, - }; -} diff --git a/x-pack/legacy/plugins/remote_clusters/common/index.ts b/x-pack/legacy/plugins/remote_clusters/common/index.ts index 8f80b3b7dc6a3..c643f549cbfe1 100644 --- a/x-pack/legacy/plugins/remote_clusters/common/index.ts +++ b/x-pack/legacy/plugins/remote_clusters/common/index.ts @@ -4,20 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; -import { LICENSE_TYPE_BASIC, LicenseType } from '../../../common/constants'; - export const PLUGIN = { ID: 'remote_clusters', - // Remote Clusters are used in both CCS and CCR, and CCS is available for all licenses. - MINIMUM_LICENSE_REQUIRED: LICENSE_TYPE_BASIC as LicenseType, - getI18nName: (): string => { - return i18n.translate('xpack.remoteClusters.appName', { - defaultMessage: 'Remote Clusters', - }); - }, }; - -export const API_BASE_PATH = '/api/remote_clusters'; - -export { deserializeCluster, serializeCluster } from './cluster_serialization'; diff --git a/x-pack/legacy/plugins/remote_clusters/index.ts b/x-pack/legacy/plugins/remote_clusters/index.ts index 5dd823e09eb8b..37b2224f8d7c2 100644 --- a/x-pack/legacy/plugins/remote_clusters/index.ts +++ b/x-pack/legacy/plugins/remote_clusters/index.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Legacy } from 'kibana'; import { resolve } from 'path'; import { PLUGIN } from './common'; @@ -13,18 +12,11 @@ export function remoteClusters(kibana: any) { id: PLUGIN.ID, configPrefix: 'xpack.remote_clusters', publicDir: resolve(__dirname, 'public'), - // xpack_main is required for license checking. - require: ['kibana', 'elasticsearch', 'xpack_main', 'index_management'], + require: ['kibana'], uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), - managementSections: ['plugins/remote_clusters'], - injectDefaultVars(server: Legacy.Server) { - const config = server.config(); - return { - remoteClustersUiEnabled: config.get('xpack.remote_clusters.ui.enabled'), - }; - }, }, + // TODO: Remove once CCR has migrated to NP config(Joi: any) { return Joi.object({ // display menu item @@ -41,6 +33,6 @@ export function remoteClusters(kibana: any) { config.get('xpack.remote_clusters.enabled') && config.get('xpack.index_management.enabled') ); }, - init(server: any) {}, + init() {}, }); } diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/connection_status/_index.scss b/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/connection_status/_index.scss deleted file mode 100644 index c85cb36c5dc5a..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/connection_status/_index.scss +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 1. Prevent inherited flexbox layout from compressing this element on IE. - */ - .remoteClustersConnectionStatus__message { - flex-basis: auto !important; /* 1 */ -} diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/http.ts b/x-pack/legacy/plugins/remote_clusters/public/app/services/http.ts deleted file mode 100644 index 54dadf0ae3cb1..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/public/app/services/http.ts +++ /dev/null @@ -1,39 +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. - */ - -let _httpClient: any; -let _prependBasePath: any; - -export function init(httpClient: any, prependBasePath: any): void { - _httpClient = httpClient; - _prependBasePath = prependBasePath; -} - -export function getFullPath(path: string): string { - const apiPrefix = _prependBasePath('/api/remote_clusters'); - - if (path) { - return `${apiPrefix}/${path}`; - } - - return apiPrefix; -} - -export function sendPost(path: string, payload: any): any { - return _httpClient.post(getFullPath(path), payload); -} - -export function sendGet(path: string): any { - return _httpClient.get(getFullPath(path)); -} - -export function sendPut(path: string, payload: any): any { - return _httpClient.put(getFullPath(path), payload); -} - -export function sendDelete(path: string): any { - return _httpClient.delete(getFullPath(path)); -} diff --git a/x-pack/legacy/plugins/remote_clusters/public/index.html b/x-pack/legacy/plugins/remote_clusters/public/index.html deleted file mode 100644 index 4de600769fb40..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/public/index.html +++ /dev/null @@ -1,3 +0,0 @@ - -
-
diff --git a/x-pack/legacy/plugins/remote_clusters/public/index.js b/x-pack/legacy/plugins/remote_clusters/public/index.js deleted file mode 100644 index 0a08011dd71a0..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/public/index.js +++ /dev/null @@ -1,12 +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 { Plugin as RemoteClustersPlugin } from './plugin'; -import { createShim } from './shim'; - -const { coreStart, pluginsStart } = createShim(); -const remoteClustersPlugin = new RemoteClustersPlugin(); -remoteClustersPlugin.start(coreStart, pluginsStart); diff --git a/x-pack/legacy/plugins/remote_clusters/public/index.scss b/x-pack/legacy/plugins/remote_clusters/public/index.scss index 4618b005312a5..4ae11323642d8 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/index.scss +++ b/x-pack/legacy/plugins/remote_clusters/public/index.scss @@ -1,8 +1,7 @@ // Import the EUI global scope so we can use EUI constants @import 'src/legacy/ui/public/styles/_styling_constants'; -@import './app/sections/remote_cluster_list/components/connection_status/index'; -// Index management plugin styles +// Remote clusters plugin styles // Prefix all styles with "remoteClusters" to avoid conflicts. // Examples @@ -16,8 +15,14 @@ * as the 'Reset to defaults' link is added to and removed from the DOM. * 2. Fix the positioning. */ - .remoteClusterSkipIfUnavailableSwitch { justify-content: flex-start !important; /* 1 */ padding-top: $euiSizeS !important; } + +/** + * 1. Prevent inherited flexbox layout from compressing this element on IE. + */ + .remoteClustersConnectionStatus__message { + flex-basis: auto !important; /* 1 */ +} diff --git a/x-pack/legacy/plugins/remote_clusters/public/plugin.js b/x-pack/legacy/plugins/remote_clusters/public/plugin.js deleted file mode 100644 index 8dbcfb98859cd..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/public/plugin.js +++ /dev/null @@ -1,123 +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 { unmountComponentAtNode } from 'react-dom'; -import { i18n } from '@kbn/i18n'; -import routes from 'ui/routes'; - -import template from './index.html'; -import { renderReact } from './app'; -import { CRUD_APP_BASE_PATH } from './app/constants'; -import { setUserHasLeftApp, setRedirect } from './app/services'; -import { init as initBreadcrumbs } from './app/services/breadcrumb'; -import { init as initDocumentation } from './app/services/documentation'; -import { init as initHttp } from './app/services/http'; -import { init as initUiMetric } from './app/services/ui_metric'; -import { init as initNotification } from './app/services/notification'; - -const REACT_ROOT_ID = 'remoteClustersReactRoot'; - -export class Plugin { - start(coreStart, pluginsStart) { - const { - i18n: { Context }, - chrome: { setBreadcrumbs }, - notifications: { toasts }, - fatalError, - http: { - basePath: { prepend: prependBasePath }, - }, - injectedMetadata: { getInjectedVar }, - documentation: { elasticWebsiteUrl, docLinkVersion }, - } = coreStart; - - if (getInjectedVar('remoteClustersUiEnabled')) { - const { - management: { getSection, breadcrumb: managementBreadcrumb }, - uiMetric: { createUiStatsReporter }, - } = pluginsStart; - - const esSection = getSection('elasticsearch'); - esSection.register('remote_clusters', { - visible: true, - display: i18n.translate('xpack.remoteClusters.appTitle', { - defaultMessage: 'Remote Clusters', - }), - order: 5, - url: `#${CRUD_APP_BASE_PATH}/list`, - }); - - // Initialize services - initBreadcrumbs(setBreadcrumbs, managementBreadcrumb); - initDocumentation(`${elasticWebsiteUrl}guide/en/elasticsearch/reference/${docLinkVersion}/`); - initUiMetric(createUiStatsReporter); - initNotification(toasts, fatalError); - - const unmountReactApp = () => { - const appElement = document.getElementById(REACT_ROOT_ID); - if (appElement) { - unmountComponentAtNode(appElement); - } - }; - - // NOTE: The New Platform will implicitly handle much of this logic by mounting the app at - // the base route. - routes.when(`${CRUD_APP_BASE_PATH}/:view?/:id?`, { - template, - controllerAs: 'remoteClusters', - controller: class RemoteClustersController { - constructor($scope, $route, $http, kbnUrl) { - // NOTE: We depend upon Angular's $http service because it's decorated with interceptors, - // e.g. to check license status per request. - initHttp($http, prependBasePath); - - setRedirect(path => { - $scope.$evalAsync(() => { - kbnUrl.redirect(path); - }); - }); - - // If returning to the app, we'll need to reset this state. - setUserHasLeftApp(false); - - // React-router's will cause this controller to re-execute without the $destroy - // handler being called. This means the app will re-mount, so we need to unmount it first - // here. - unmountReactApp(); - - $scope.$$postDigest(() => { - const appElement = document.getElementById(REACT_ROOT_ID); - if (appElement) { - renderReact(appElement, Context); - } - - const appRoute = $route.current; - const stopListeningForLocationChange = $scope.$on('$locationChangeSuccess', () => { - const currentRoute = $route.current; - const isNavigationInApp = - currentRoute.$$route.template === appRoute.$$route.template; - - // When we navigate within the app, prevent Angular from re-matching the route and - // rebuilding the app. - if (isNavigationInApp) { - $route.current = appRoute; - } else { - // Set internal flag so we can prevent reacting to the route change internally. - setUserHasLeftApp(true); - } - }); - - $scope.$on('$destroy', () => { - stopListeningForLocationChange(); - unmountReactApp(); - }); - }); - } - }, - }); - } - } -} diff --git a/x-pack/legacy/plugins/remote_clusters/public/shim.ts b/x-pack/legacy/plugins/remote_clusters/public/shim.ts deleted file mode 100644 index 83975fa4bd0fe..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/public/shim.ts +++ /dev/null @@ -1,42 +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 { npStart } from 'ui/new_platform'; -import { management, MANAGEMENT_BREADCRUMB } from 'ui/management'; -import { fatalError } from 'ui/notify'; -import { DOC_LINK_VERSION, ELASTIC_WEBSITE_URL } from 'ui/documentation_links'; - -import { createUiStatsReporter } from '../../../../../src/legacy/core_plugins/ui_metric/public'; - -export function createShim() { - const { - core: { chrome, i18n, notifications, http, injectedMetadata }, - } = npStart; - - return { - coreStart: { - chrome, - i18n, - notifications, - fatalError, - injectedMetadata, - http, - documentation: { - elasticWebsiteUrl: ELASTIC_WEBSITE_URL, - docLinkVersion: DOC_LINK_VERSION, - }, - }, - pluginsStart: { - management: { - getSection: management.getSection.bind(management), - breadcrumb: MANAGEMENT_BREADCRUMB, - }, - uiMetric: { - createUiStatsReporter, - }, - }, - }; -} diff --git a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/constants.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/constants.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/constants.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/constants.js diff --git a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.js diff --git a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/index.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/index.js similarity index 96% rename from x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/index.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/index.js index 084a370666e45..d70ba2a21e176 100644 --- a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/index.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/index.js @@ -8,7 +8,7 @@ import { setup as remoteClustersAddSetup } from './remote_clusters_add.helpers'; import { setup as remoteClustersEditSetup } from './remote_clusters_edit.helpers'; import { setup as remoteClustersListSetup } from './remote_clusters_list.helpers'; -export { nextTick, getRandomString, findTestSubject } from '../../../../../../test_utils'; +export { nextTick, getRandomString, findTestSubject } from '../../../../../test_utils'; export { setupEnvironment } from './setup_environment'; diff --git a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_add.helpers.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_add.helpers.js similarity index 66% rename from x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_add.helpers.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_add.helpers.js index e573a4ebcef92..dd1d5d2187176 100644 --- a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_add.helpers.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_add.helpers.js @@ -4,10 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed } from '../../../../../../test_utils'; -import { RemoteClusterAdd } from '../../../public/app/sections/remote_cluster_add'; -import { createRemoteClustersStore } from '../../../public/app/store'; -import { registerRouter } from '../../../public/app/services/routing'; +import { registerTestBed } from '../../../../../test_utils'; + +/* eslint-disable @kbn/eslint/no-restricted-paths */ +import { RemoteClusterAdd } from '../../../public/application/sections/remote_cluster_add'; +import { createRemoteClustersStore } from '../../../public/application/store'; +import { registerRouter } from '../../../public/application/services/routing'; const testBedConfig = { store: createRemoteClustersStore, diff --git a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_edit.helpers.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_edit.helpers.js similarity index 68% rename from x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_edit.helpers.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_edit.helpers.js index 6a90ed6657c78..426aea90e5a99 100644 --- a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_edit.helpers.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_edit.helpers.js @@ -4,10 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed } from '../../../../../../test_utils'; -import { RemoteClusterEdit } from '../../../public/app/sections/remote_cluster_edit'; -import { createRemoteClustersStore } from '../../../public/app/store'; -import { registerRouter } from '../../../public/app/services/routing'; +import { registerTestBed } from '../../../../../test_utils'; + +/* eslint-disable @kbn/eslint/no-restricted-paths */ +import { RemoteClusterEdit } from '../../../public/application/sections/remote_cluster_edit'; +import { createRemoteClustersStore } from '../../../public/application/store'; +import { registerRouter } from '../../../public/application/services/routing'; import { REMOTE_CLUSTER_EDIT_NAME } from './constants'; diff --git a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_list.helpers.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_list.helpers.js similarity index 88% rename from x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_list.helpers.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_list.helpers.js index 0009bd84ffa6a..dc9b22b40542a 100644 --- a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_list.helpers.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_list.helpers.js @@ -4,10 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed, findTestSubject } from '../../../../../../test_utils'; -import { RemoteClusterList } from '../../../public/app/sections/remote_cluster_list'; -import { createRemoteClustersStore } from '../../../public/app/store'; -import { registerRouter } from '../../../public/app/services/routing'; +import { registerTestBed, findTestSubject } from '../../../../../test_utils'; + +/* eslint-disable @kbn/eslint/no-restricted-paths */ +import { RemoteClusterList } from '../../../public/application/sections/remote_cluster_list'; +import { createRemoteClustersStore } from '../../../public/application/store'; +import { registerRouter } from '../../../public/application/services/routing'; const testBedConfig = { store: createRemoteClustersStore, diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js new file mode 100644 index 0000000000000..c912a4ddabc9d --- /dev/null +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js @@ -0,0 +1,48 @@ +/* + * 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 { + notificationServiceMock, + fatalErrorsServiceMock, + docLinksServiceMock, + injectedMetadataServiceMock, +} from '../../../../../../src/core/public/mocks'; + +import { usageCollectionPluginMock } from '../../../../../../src/plugins/usage_collection/public/mocks'; + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { HttpService } from '../../../../../../src/core/public/http'; + +/* eslint-disable @kbn/eslint/no-restricted-paths */ +import { init as initBreadcrumb } from '../../../public/application/services/breadcrumb'; +import { init as initHttp } from '../../../public/application/services/http'; +import { init as initNotification } from '../../../public/application/services/notification'; +import { init as initUiMetric } from '../../../public/application/services/ui_metric'; +import { init as initDocumentation } from '../../../public/application/services/documentation'; +import { init as initHttpRequests } from './http_requests'; + +export const setupEnvironment = () => { + const httpServiceSetupMock = new HttpService().setup({ + injectedMetadata: injectedMetadataServiceMock.createSetupContract(), + fatalErrors: fatalErrorsServiceMock.createSetupContract(), + }); + + initBreadcrumb(() => {}); + initDocumentation(docLinksServiceMock.createStartContract()); + initUiMetric(usageCollectionPluginMock.createSetupContract()); + initNotification( + notificationServiceMock.createSetupContract().toasts, + fatalErrorsServiceMock.createSetupContract() + ); + initHttp(httpServiceSetupMock); + + const { server, httpRequestsMockHelpers } = initHttpRequests(); + + return { + server, + httpRequestsMockHelpers, + }; +}; diff --git a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/remote_clusters_add.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_add.test.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/remote_clusters_add.test.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_add.test.js diff --git a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js similarity index 93% rename from x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js index 95dc65a96e30a..cab91854a5114 100644 --- a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js @@ -5,7 +5,7 @@ */ jest.mock('ui/new_platform'); -import { RemoteClusterForm } from '../../public/app/sections/components/remote_cluster_form'; +import { RemoteClusterForm } from '../../public/application/sections/components/remote_cluster_form'; import { pageHelpers, setupEnvironment, nextTick } from './helpers'; import { REMOTE_CLUSTER_EDIT, REMOTE_CLUSTER_EDIT_NAME } from './helpers/constants'; @@ -31,7 +31,7 @@ describe('Edit Remote cluster', () => { httpRequestsMockHelpers.setLoadRemoteClustersResponse([REMOTE_CLUSTER_EDIT]); ({ component, find, exists } = setup()); - await nextTick(); + await nextTick(100); // We need to wait next tick for the mock server response to kick in component.update(); }); diff --git a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.js similarity index 96% rename from x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.js index 699c00e450a1f..1b7c600218cee 100644 --- a/x-pack/legacy/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.js @@ -12,7 +12,7 @@ import { findTestSubject, } from './helpers'; -import { getRouter } from '../../public/app/services'; +import { getRouter } from '../../public/application/services'; import { getRemoteClusterMock } from '../../fixtures/remote_cluster'; jest.mock('ui/new_platform'); @@ -39,11 +39,11 @@ describe('', () => { describe('on component mount', () => { let exists; - beforeEach(async () => { + beforeEach(() => { ({ exists } = setup()); }); - test('should show a "loading remote clusters" indicator', async () => { + test('should show a "loading remote clusters" indicator', () => { expect(exists('remoteClustersTableLoading')).toBe(true); }); }); @@ -55,7 +55,7 @@ describe('', () => { beforeEach(async () => { ({ exists, component } = setup()); - await nextTick(); // We need to wait next tick for the mock server response to kick in + await nextTick(100); // We need to wait next tick for the mock server response to kick in component.update(); }); @@ -97,7 +97,7 @@ describe('', () => { // Mount the component ({ component, find, exists, table, actions } = setup()); - await nextTick(); // Make sure that the Http request is fulfilled + await nextTick(100); // Make sure that the Http request is fulfilled component.update(); // Read the remote clusters list table @@ -206,7 +206,7 @@ describe('', () => { actions.clickBulkDeleteButton(); actions.clickConfirmModalDeleteRemoteCluster(); - await nextTick(550); // there is a 500ms timeout in the api action + await nextTick(600); // there is a 500ms timeout in the api action component.update(); ({ rows } = table.getMetaData('remoteClusterListTable')); diff --git a/x-pack/legacy/plugins/remote_clusters/fixtures/remote_cluster.js b/x-pack/plugins/remote_clusters/fixtures/remote_cluster.js similarity index 91% rename from x-pack/legacy/plugins/remote_clusters/fixtures/remote_cluster.js rename to x-pack/plugins/remote_clusters/fixtures/remote_cluster.js index 248e2b8232cad..e3e087548cf00 100644 --- a/x-pack/legacy/plugins/remote_clusters/fixtures/remote_cluster.js +++ b/x-pack/plugins/remote_clusters/fixtures/remote_cluster.js @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { getRandomString } from '../../../../test_utils'; +import { getRandomString } from '../../../test_utils'; export const getRemoteClusterMock = ({ name = getRandomString(), diff --git a/x-pack/plugins/remote_clusters/kibana.json b/x-pack/plugins/remote_clusters/kibana.json index de1e3d1e26865..27ae6802966dd 100644 --- a/x-pack/plugins/remote_clusters/kibana.json +++ b/x-pack/plugins/remote_clusters/kibana.json @@ -1,9 +1,17 @@ { "id": "remote_clusters", "version": "kibana", + "configPath": [ + "xpack", + "remote_clusters" + ], "requiredPlugins": [ - "licensing" + "licensing", + "management" + ], + "optionalPlugins": [ + "usageCollection" ], "server": true, - "ui": false + "ui": true } diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/app.js b/x-pack/plugins/remote_clusters/public/application/app.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/app.js rename to x-pack/plugins/remote_clusters/public/application/app.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/constants/index.ts b/x-pack/plugins/remote_clusters/public/application/constants/index.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/constants/index.ts rename to x-pack/plugins/remote_clusters/public/application/constants/index.ts diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/constants/paths.ts b/x-pack/plugins/remote_clusters/public/application/constants/paths.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/constants/paths.ts rename to x-pack/plugins/remote_clusters/public/application/constants/paths.ts diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/constants/ui_metric.ts b/x-pack/plugins/remote_clusters/public/application/constants/ui_metric.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/constants/ui_metric.ts rename to x-pack/plugins/remote_clusters/public/application/constants/ui_metric.ts diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/redirect.js b/x-pack/plugins/remote_clusters/public/application/index.d.ts similarity index 50% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/redirect.js rename to x-pack/plugins/remote_clusters/public/application/index.d.ts index ec77c2a2bfe99..b5c5ad5522134 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/services/redirect.js +++ b/x-pack/plugins/remote_clusters/public/application/index.d.ts @@ -4,14 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -// This depends upon Angular, which is why we use this provider pattern to access it within -// our React app. -let _redirect; +import { RegisterManagementAppArgs, I18nStart } from '../types'; -export function setRedirect(redirect) { - _redirect = redirect; -} - -export function redirect(path) { - _redirect(path); -} +export declare const renderApp: ( + elem: HTMLElement | null, + I18nContext: I18nStart['Context'] +) => ReturnType; diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/index.js b/x-pack/plugins/remote_clusters/public/application/index.js similarity index 80% rename from x-pack/legacy/plugins/remote_clusters/public/app/index.js rename to x-pack/plugins/remote_clusters/public/application/index.js index 2de59f4590553..0b8b26ace5daa 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/index.js +++ b/x-pack/plugins/remote_clusters/public/application/index.js @@ -5,14 +5,14 @@ */ import React from 'react'; -import { render } from 'react-dom'; +import { render, unmountComponentAtNode } from 'react-dom'; import { HashRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; import { App } from './app'; import { remoteClustersStore } from './store'; -export const renderReact = async (elem, I18nContext) => { +export const renderApp = (elem, I18nContext) => { render( @@ -23,4 +23,5 @@ export const renderReact = async (elem, I18nContext) => { , elem ); + return () => unmountComponentAtNode(elem); }; diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/configured_by_node_warning/configured_by_node_warning.js b/x-pack/plugins/remote_clusters/public/application/sections/components/configured_by_node_warning/configured_by_node_warning.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/configured_by_node_warning/configured_by_node_warning.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/configured_by_node_warning/configured_by_node_warning.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/configured_by_node_warning/index.js b/x-pack/plugins/remote_clusters/public/application/sections/components/configured_by_node_warning/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/configured_by_node_warning/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/configured_by_node_warning/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/index.js b/x-pack/plugins/remote_clusters/public/application/sections/components/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/index.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/remote_cluster_form.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.js similarity index 99% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/remote_cluster_form.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.js index f070bb218be42..08cd01496a8b9 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/remote_cluster_form.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.js @@ -491,7 +491,7 @@ export class RemoteClusterForm extends Component { let errorBody; - if (cause) { + if (cause && Array.isArray(cause)) { if (cause.length === 1) { errorBody =

{cause[0]}

; } else { diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/remote_cluster_form.test.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.test.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/remote_cluster_form.test.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.test.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/request_flyout.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/request_flyout.js similarity index 97% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/request_flyout.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/request_flyout.js index deec26129abe5..70e2267001e3c 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/request_flyout.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/request_flyout.js @@ -26,7 +26,7 @@ import { EuiTitle, } from '@elastic/eui'; -import { serializeCluster } from '../../../../../common'; +import { serializeCluster } from '../../../../../common/constants'; export class RequestFlyout extends PureComponent { static propTypes = { diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/__snapshots__/validate_name.test.js.snap b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/__snapshots__/validate_name.test.js.snap similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/__snapshots__/validate_name.test.js.snap rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/__snapshots__/validate_name.test.js.snap diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/__snapshots__/validate_seeds.test.js.snap b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/__snapshots__/validate_seeds.test.js.snap similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/__snapshots__/validate_seeds.test.js.snap rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/__snapshots__/validate_seeds.test.js.snap diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/index.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_name.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_name.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_name.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_name.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_name.test.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_name.test.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_name.test.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_name.test.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_seed.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_seed.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_seed.test.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.test.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_seed.test.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.test.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_seeds.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seeds.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_seeds.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seeds.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_seeds.test.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seeds.test.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/validators/validate_seeds.test.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seeds.test.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_page_title/index.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_page_title/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_page_title/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_page_title/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_page_title/remote_cluster_page_title.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_page_title/remote_cluster_page_title.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_page_title/remote_cluster_page_title.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_page_title/remote_cluster_page_title.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/index.js b/x-pack/plugins/remote_clusters/public/application/sections/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_add/index.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_add/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_add/remote_cluster_add.container.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.container.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_add/remote_cluster_add.container.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.container.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_add/remote_cluster_add.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_add/remote_cluster_add.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_edit/index.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_edit/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_edit/remote_cluster_edit.container.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.container.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_edit/remote_cluster_edit.container.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.container.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_edit/remote_cluster_edit.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_edit/remote_cluster_edit.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/connection_status/connection_status.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/connection_status.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/connection_status/connection_status.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/connection_status.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/connection_status/index.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/connection_status/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/index.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/remove_cluster_button_provider/index.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/remove_cluster_button_provider/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/remove_cluster_button_provider/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/remove_cluster_button_provider/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/remove_cluster_button_provider/remove_cluster_button_provider.container.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/remove_cluster_button_provider/remove_cluster_button_provider.container.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/remove_cluster_button_provider/remove_cluster_button_provider.container.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/remove_cluster_button_provider/remove_cluster_button_provider.container.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/remove_cluster_button_provider/remove_cluster_button_provider.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/remove_cluster_button_provider/remove_cluster_button_provider.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/components/remove_cluster_button_provider/remove_cluster_button_provider.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/remove_cluster_button_provider/remove_cluster_button_provider.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/detail_panel/detail_panel.container.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.container.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/detail_panel/detail_panel.container.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.container.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/detail_panel/detail_panel.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/detail_panel/detail_panel.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/detail_panel/index.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/detail_panel/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/index.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_list.container.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.container.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_list.container.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.container.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_list.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js similarity index 98% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_list.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js index dea6bc7627cc1..207aa8045c011 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_list.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js @@ -145,9 +145,9 @@ export class RemoteClusterList extends Component { } renderError(error) { - // We can safely depend upon the shape of this error coming from Angular $http, because we + // We can safely depend upon the shape of this error coming from http service, because we // handle unexpected error shapes in the API action. - const { statusCode, error: errorString } = error.data; + const { statusCode, error: errorString } = error.body; const title = i18n.translate('xpack.remoteClusters.remoteClusterList.loadingErrorTitle', { defaultMessage: 'Error loading remote clusters', diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_table/index.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_table/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_table/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_table/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_table/remote_cluster_table.container.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_table/remote_cluster_table.container.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_table/remote_cluster_table.container.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_table/remote_cluster_table.container.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_table/remote_cluster_table.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_table/remote_cluster_table.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/sections/remote_cluster_list/remote_cluster_table/remote_cluster_table.js rename to x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_table/remote_cluster_table.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/api.js b/x-pack/plugins/remote_clusters/public/application/services/api.js similarity index 93% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/api.js rename to x-pack/plugins/remote_clusters/public/application/services/api.js index 8631bc5af12a8..72d5e3f9c3f9e 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/services/api.js +++ b/x-pack/plugins/remote_clusters/public/application/services/api.js @@ -9,19 +9,19 @@ import { trackUserRequest } from './ui_metric'; import { sendGet, sendPost, sendPut, sendDelete } from './http'; export async function loadClusters() { - const response = await sendGet(); - return response.data; + return await sendGet(); } export async function addCluster(cluster) { const request = sendPost('', cluster); + return await trackUserRequest(request, UIM_CLUSTER_ADD); } export async function editCluster(cluster) { const { name, ...rest } = cluster; - const request = sendPut(name, rest); + return await trackUserRequest(request, UIM_CLUSTER_UPDATE); } diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/api_errors.js b/x-pack/plugins/remote_clusters/public/application/services/api_errors.js similarity index 77% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/api_errors.js rename to x-pack/plugins/remote_clusters/public/application/services/api_errors.js index c50ad92532071..8376f37f36f49 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/services/api_errors.js +++ b/x-pack/plugins/remote_clusters/public/application/services/api_errors.js @@ -4,12 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { fatalError, toasts } from './notification'; +import { toasts, fatalError } from './notification'; function createToastConfig(error, errorTitle) { - // Expect an error in the shape provided by Angular's $http service. - if (error && error.data) { - const { error: errorString, statusCode, message } = error.data; + // Expect an error in the shape provided by http service. + if (error && error.body) { + const { error: errorString, statusCode, message } = error.body; return { title: errorTitle, text: `${statusCode}: ${errorString}. ${message}`, @@ -26,7 +26,7 @@ export function showApiWarning(error, errorTitle) { // This error isn't an HTTP error, so let the fatal error screen tell the user something // unexpected happened. - return fatalError(error, errorTitle); + return fatalError.add(error, errorTitle); } export function showApiError(error, errorTitle) { @@ -38,5 +38,5 @@ export function showApiError(error, errorTitle) { // This error isn't an HTTP error, so let the fatal error screen tell the user something // unexpected happened. - fatalError(error, errorTitle); + fatalError.add(error, errorTitle); } diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/breadcrumb.ts b/x-pack/plugins/remote_clusters/public/application/services/breadcrumb.ts similarity index 68% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/breadcrumb.ts rename to x-pack/plugins/remote_clusters/public/application/services/breadcrumb.ts index 68d34cc2a17d4..f90a0d3456166 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/services/breadcrumb.ts +++ b/x-pack/plugins/remote_clusters/public/application/services/breadcrumb.ts @@ -8,13 +8,22 @@ import { i18n } from '@kbn/i18n'; import { CRUD_APP_BASE_PATH } from '../constants'; -let _setBreadcrumbs: any; -let _breadcrumbs: any; +interface Breadcrumb { + text: string; + href?: string; +} +interface Breadcrumbs { + home: Breadcrumb; + add: Breadcrumb; + edit: Breadcrumb; +} + +let _setBreadcrumbs: (breadcrumbs: Breadcrumb[]) => void; +let _breadcrumbs: Breadcrumbs; -export function init(setGlobalBreadcrumbs: any, managementBreadcrumb: any): void { +export function init(setGlobalBreadcrumbs: (breadcrumbs: Breadcrumb[]) => void): void { _setBreadcrumbs = setGlobalBreadcrumbs; _breadcrumbs = { - management: managementBreadcrumb, home: { text: i18n.translate('xpack.remoteClusters.listBreadcrumbTitle', { defaultMessage: 'Remote Clusters', @@ -34,13 +43,13 @@ export function init(setGlobalBreadcrumbs: any, managementBreadcrumb: any): void }; } -export function setBreadcrumbs(type: string, queryParams?: string): void { +export function setBreadcrumbs(type: 'home' | 'add' | 'edit', queryParams?: string): void { if (!_breadcrumbs[type]) { return; } if (type === 'home') { - _setBreadcrumbs([_breadcrumbs.management, _breadcrumbs.home]); + _setBreadcrumbs([_breadcrumbs.home]); } else { // Support deep-linking back to a remote cluster in the detail panel. const homeBreadcrumb = { @@ -48,6 +57,6 @@ export function setBreadcrumbs(type: string, queryParams?: string): void { href: `${_breadcrumbs.home.href}${queryParams}`, }; - _setBreadcrumbs([_breadcrumbs.management, homeBreadcrumb, _breadcrumbs[type]]); + _setBreadcrumbs([homeBreadcrumb, _breadcrumbs[type]]); } } diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/documentation.ts b/x-pack/plugins/remote_clusters/public/application/services/documentation.ts similarity index 70% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/documentation.ts rename to x-pack/plugins/remote_clusters/public/application/services/documentation.ts index 4d04aa6fad74d..38cf2223a313b 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/services/documentation.ts +++ b/x-pack/plugins/remote_clusters/public/application/services/documentation.ts @@ -4,11 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ +import { DocLinksStart } from 'kibana/public'; + export let skippingDisconnectedClustersUrl: string; export let remoteClustersUrl: string; export let transportPortUrl: string; -export function init(esDocBasePath: string): void { +export function init(docLinks: DocLinksStart): void { + const { DOC_LINK_VERSION, ELASTIC_WEBSITE_URL } = docLinks; + const esDocBasePath = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}`; + skippingDisconnectedClustersUrl = `${esDocBasePath}/modules-cross-cluster-search.html#_skipping_disconnected_clusters`; remoteClustersUrl = `${esDocBasePath}/modules-remote-clusters.html`; transportPortUrl = `${esDocBasePath}/modules-transport.html`; diff --git a/x-pack/plugins/remote_clusters/public/application/services/http.ts b/x-pack/plugins/remote_clusters/public/application/services/http.ts new file mode 100644 index 0000000000000..b49e95f3a5c65 --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/services/http.ts @@ -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 { HttpSetup, HttpResponse } from 'kibana/public'; +import { API_BASE_PATH } from '../../../common/constants'; + +let _httpClient: HttpSetup; + +export function init(httpClient: HttpSetup): void { + _httpClient = httpClient; +} + +export function getFullPath(path: string): string { + if (path) { + return `${API_BASE_PATH}/${path}`; + } + + return API_BASE_PATH; +} + +export function sendPost( + path: string, + payload: { + name: string; + seeds: string[]; + skipUnavailable: boolean; + } +): Promise { + return _httpClient.post(getFullPath(path), { + body: JSON.stringify(payload), + }); +} + +export function sendGet(path: string): Promise { + return _httpClient.get(getFullPath(path)); +} + +export function sendPut( + path: string, + payload: { + seeds: string[]; + skipUnavailable: boolean; + } +): Promise { + return _httpClient.put(getFullPath(path), { + body: JSON.stringify(payload), + }); +} + +export function sendDelete(path: string): Promise { + return _httpClient.delete(getFullPath(path)); +} diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/index.js b/x-pack/plugins/remote_clusters/public/application/services/index.js similarity index 93% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/index.js rename to x-pack/plugins/remote_clusters/public/application/services/index.js index 69679e55dfef5..031770d9500ed 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/services/index.js +++ b/x-pack/plugins/remote_clusters/public/application/services/index.js @@ -8,7 +8,7 @@ export { loadClusters, addCluster, editCluster, removeClusterRequest } from './a export { showApiError, showApiWarning } from './api_errors'; -export { setRedirect, redirect } from './redirect'; +export { initRedirect, redirect } from './redirect'; export { isSeedNodeValid, isSeedNodePortValid } from './validate_seed_node'; diff --git a/x-pack/plugins/remote_clusters/public/application/services/notification.ts b/x-pack/plugins/remote_clusters/public/application/services/notification.ts new file mode 100644 index 0000000000000..1c9173e519b48 --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/services/notification.ts @@ -0,0 +1,15 @@ +/* + * 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 { NotificationsSetup, FatalErrorsSetup } from 'src/core/public'; + +export let toasts: NotificationsSetup['toasts']; +export let fatalError: FatalErrorsSetup; + +export function init(_toasts: NotificationsSetup['toasts'], _fatalError: FatalErrorsSetup): void { + toasts = _toasts; + fatalError = _fatalError; +} diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/query_params.js b/x-pack/plugins/remote_clusters/public/application/services/query_params.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/query_params.js rename to x-pack/plugins/remote_clusters/public/application/services/query_params.js diff --git a/x-pack/plugins/remote_clusters/public/application/services/redirect.ts b/x-pack/plugins/remote_clusters/public/application/services/redirect.ts new file mode 100644 index 0000000000000..00a97fa74c5ce --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/services/redirect.ts @@ -0,0 +1,17 @@ +/* + * 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 { CoreStart } from 'kibana/public'; + +let navigateToApp: CoreStart['application']['navigateToApp']; + +export function init(_navigateToApp: CoreStart['application']['navigateToApp']) { + navigateToApp = _navigateToApp; +} + +export function redirect(path: string) { + navigateToApp('kibana', { path: `#${path}` }); +} diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/routing.js b/x-pack/plugins/remote_clusters/public/application/services/routing.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/routing.js rename to x-pack/plugins/remote_clusters/public/application/services/routing.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/ui_metric.ts b/x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts similarity index 62% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/ui_metric.ts rename to x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts index 36a23476c1873..91354155cacb0 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/services/ui_metric.ts +++ b/x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts @@ -4,17 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ +import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; +import { UiStatsMetricType } from '@kbn/analytics'; import { UIM_APP_NAME } from '../constants'; -import { - createUiStatsReporter, - METRIC_TYPE, -} from '../../../../../../../src/legacy/core_plugins/ui_metric/public'; -export let trackUiMetric: ReturnType; -export { METRIC_TYPE }; +export let trackUiMetric: (metricType: UiStatsMetricType, eventName: string) => void; +export let METRIC_TYPE: UsageCollectionSetup['METRIC_TYPE']; -export function init(getReporter: typeof createUiStatsReporter): void { - trackUiMetric = getReporter(UIM_APP_NAME); +export function init(usageCollection: UsageCollectionSetup): void { + trackUiMetric = usageCollection.reportUiStats.bind(usageCollection, UIM_APP_NAME); + METRIC_TYPE = usageCollection.METRIC_TYPE; } /** diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/validate_seed_node.js b/x-pack/plugins/remote_clusters/public/application/services/validate_seed_node.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/validate_seed_node.js rename to x-pack/plugins/remote_clusters/public/application/services/validate_seed_node.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/validate_seed_node.test.js b/x-pack/plugins/remote_clusters/public/application/services/validate_seed_node.test.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/validate_seed_node.test.js rename to x-pack/plugins/remote_clusters/public/application/services/validate_seed_node.test.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/action_types.js b/x-pack/plugins/remote_clusters/public/application/store/action_types.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/action_types.js rename to x-pack/plugins/remote_clusters/public/application/store/action_types.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/add_cluster.js b/x-pack/plugins/remote_clusters/public/application/store/actions/add_cluster.js similarity index 88% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/actions/add_cluster.js rename to x-pack/plugins/remote_clusters/public/application/store/actions/add_cluster.js index 726bc56b08f12..0b7838f48b137 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/add_cluster.js +++ b/x-pack/plugins/remote_clusters/public/application/store/actions/add_cluster.js @@ -35,12 +35,12 @@ export const addCluster = cluster => async dispatch => { ]); } catch (error) { if (error) { - const { statusCode, data } = error; + const { body } = error; - // Expect an error in the shape provided by Angular's $http service. - if (data) { - // Some errors have statusCode directly available but some are under a data property. - if ((statusCode || (data && data.statusCode)) === 409) { + // Expect an error in the shape provided by http service. + if (body) { + const { statusCode, message } = body; + if (statusCode && statusCode === 409) { return dispatch({ type: ADD_CLUSTER_FAILURE, payload: { @@ -63,9 +63,8 @@ export const addCluster = cluster => async dispatch => { error: { message: i18n.translate('xpack.remoteClusters.addAction.failedDefaultErrorMessage', { defaultMessage: 'Request failed with a {statusCode} error. {message}', - values: { statusCode, message: data.message }, + values: { statusCode, message }, }), - cause: data.cause, }, }, }); @@ -74,7 +73,7 @@ export const addCluster = cluster => async dispatch => { // This error isn't an HTTP error, so let the fatal error screen tell the user something // unexpected happened. - return fatalError( + return fatalError.add( error, i18n.translate('xpack.remoteClusters.addAction.errorTitle', { defaultMessage: 'Error adding cluster', diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/detail_panel.js b/x-pack/plugins/remote_clusters/public/application/store/actions/detail_panel.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/actions/detail_panel.js rename to x-pack/plugins/remote_clusters/public/application/store/actions/detail_panel.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/edit_cluster.js b/x-pack/plugins/remote_clusters/public/application/store/actions/edit_cluster.js similarity index 90% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/actions/edit_cluster.js rename to x-pack/plugins/remote_clusters/public/application/store/actions/edit_cluster.js index 3ed481aa0f8ea..062704472521e 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/edit_cluster.js +++ b/x-pack/plugins/remote_clusters/public/application/store/actions/edit_cluster.js @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; -import { fatalError, toasts } from '../../services/notification'; +import { toasts, fatalError } from '../../services/notification'; import { CRUD_APP_BASE_PATH } from '../../constants'; import { loadClusters } from './load_clusters'; @@ -39,19 +39,19 @@ export const editCluster = cluster => async dispatch => { ]); } catch (error) { if (error) { - const { statusCode, data } = error; + const { body } = error; - // Expect an error in the shape provided by Angular's $http service. - if (data) { + // Expect an error in the shape provided by http service. + if (body) { + const { statusCode, message } = body; return dispatch({ type: EDIT_CLUSTER_FAILURE, payload: { error: { message: i18n.translate('xpack.remoteClusters.editAction.failedDefaultErrorMessage', { defaultMessage: 'Request failed with a {statusCode} error. {message}', - values: { statusCode, message: data.message }, + values: { statusCode, message }, }), - cause: data.cause, }, }, }); @@ -60,7 +60,7 @@ export const editCluster = cluster => async dispatch => { // This error isn't an HTTP error, so let the fatal error screen tell the user something // unexpected happened. - return fatalError( + return fatalError.add( error, i18n.translate('xpack.remoteClusters.editAction.errorTitle', { defaultMessage: 'Error editing cluster', diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/index.js b/x-pack/plugins/remote_clusters/public/application/store/actions/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/actions/index.js rename to x-pack/plugins/remote_clusters/public/application/store/actions/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/load_clusters.js b/x-pack/plugins/remote_clusters/public/application/store/actions/load_clusters.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/actions/load_clusters.js rename to x-pack/plugins/remote_clusters/public/application/store/actions/load_clusters.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/refresh_clusters.js b/x-pack/plugins/remote_clusters/public/application/store/actions/refresh_clusters.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/actions/refresh_clusters.js rename to x-pack/plugins/remote_clusters/public/application/store/actions/refresh_clusters.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/remove_clusters.js b/x-pack/plugins/remote_clusters/public/application/store/actions/remove_clusters.js similarity index 95% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/actions/remove_clusters.js rename to x-pack/plugins/remote_clusters/public/application/store/actions/remove_clusters.js index 4086a91e29021..8e22eac8b292b 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/remove_clusters.js +++ b/x-pack/plugins/remote_clusters/public/application/store/actions/remove_clusters.js @@ -30,7 +30,7 @@ function getErrorTitle(count, name = null) { } } else { return i18n.translate('xpack.remoteClusters.removeAction.errorMultipleNotificationTitle', { - defaultMessage: `Error removing '{count}' remote clusters`, + defaultMessage: `Error removing {count} remote clusters`, values: { count }, }); } @@ -46,7 +46,7 @@ export const removeClusters = names => async (dispatch, getState) => { await Promise.all([ sendRemoveClusterRequest(names.join(',')).then(response => { - ({ itemsDeleted, errors } = response.data); + ({ itemsDeleted, errors } = response); }), // Wait at least half a second to avoid a weird flicker of the saving feedback (only visible // when requests resolve very quickly). @@ -55,7 +55,7 @@ export const removeClusters = names => async (dispatch, getState) => { const errorTitle = getErrorTitle(names.length, names[0]); toasts.addDanger({ title: errorTitle, - text: error.data.message, + text: error.body?.message, }); }); diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/index.js b/x-pack/plugins/remote_clusters/public/application/store/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/index.js rename to x-pack/plugins/remote_clusters/public/application/store/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/middleware/detail_panel.js b/x-pack/plugins/remote_clusters/public/application/store/middleware/detail_panel.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/middleware/detail_panel.js rename to x-pack/plugins/remote_clusters/public/application/store/middleware/detail_panel.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/middleware/index.js b/x-pack/plugins/remote_clusters/public/application/store/middleware/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/middleware/index.js rename to x-pack/plugins/remote_clusters/public/application/store/middleware/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/add_cluster.js b/x-pack/plugins/remote_clusters/public/application/store/reducers/add_cluster.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/add_cluster.js rename to x-pack/plugins/remote_clusters/public/application/store/reducers/add_cluster.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/clusters.js b/x-pack/plugins/remote_clusters/public/application/store/reducers/clusters.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/clusters.js rename to x-pack/plugins/remote_clusters/public/application/store/reducers/clusters.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/detail_panel.js b/x-pack/plugins/remote_clusters/public/application/store/reducers/detail_panel.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/detail_panel.js rename to x-pack/plugins/remote_clusters/public/application/store/reducers/detail_panel.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/edit_cluster.js b/x-pack/plugins/remote_clusters/public/application/store/reducers/edit_cluster.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/edit_cluster.js rename to x-pack/plugins/remote_clusters/public/application/store/reducers/edit_cluster.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/index.js b/x-pack/plugins/remote_clusters/public/application/store/reducers/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/index.js rename to x-pack/plugins/remote_clusters/public/application/store/reducers/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/remove_cluster.js b/x-pack/plugins/remote_clusters/public/application/store/reducers/remove_cluster.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/reducers/remove_cluster.js rename to x-pack/plugins/remote_clusters/public/application/store/reducers/remove_cluster.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/selectors/index.js b/x-pack/plugins/remote_clusters/public/application/store/selectors/index.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/selectors/index.js rename to x-pack/plugins/remote_clusters/public/application/store/selectors/index.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/store.js b/x-pack/plugins/remote_clusters/public/application/store/store.js similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/public/app/store/store.js rename to x-pack/plugins/remote_clusters/public/application/store/store.js diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/services/notification.ts b/x-pack/plugins/remote_clusters/public/index.ts similarity index 59% rename from x-pack/legacy/plugins/remote_clusters/public/app/services/notification.ts rename to x-pack/plugins/remote_clusters/public/index.ts index 1ac329253cddb..dbe22b71b48df 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/services/notification.ts +++ b/x-pack/plugins/remote_clusters/public/index.ts @@ -3,11 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { RemoteClustersUIPlugin } from './plugin'; -export let toasts: any; -export let fatalError: any; - -export function init(_toasts: any, _fatalError: any): void { - toasts = _toasts; - fatalError = _fatalError; -} +export const plugin = () => new RemoteClustersUIPlugin(); diff --git a/x-pack/plugins/remote_clusters/public/plugin.ts b/x-pack/plugins/remote_clusters/public/plugin.ts new file mode 100644 index 0000000000000..5b84fa1fde369 --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/plugin.ts @@ -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 { i18n } from '@kbn/i18n'; +import { CoreSetup, Plugin, CoreStart } from 'kibana/public'; +import { init as initBreadcrumbs } from './application/services/breadcrumb'; +import { init as initDocumentation } from './application/services/documentation'; +import { init as initHttp } from './application/services/http'; +import { init as initUiMetric } from './application/services/ui_metric'; +import { init as initNotification } from './application/services/notification'; +import { init as initRedirect } from './application/services/redirect'; +import { Dependencies } from './types'; + +export class RemoteClustersUIPlugin implements Plugin { + setup( + { notifications: { toasts }, http, getStartServices }: CoreSetup, + { management, usageCollection }: Dependencies + ) { + const esSection = management.sections.getSection('elasticsearch'); + + esSection!.registerApp({ + id: 'remote_clusters', + title: i18n.translate('xpack.remoteClusters.appTitle', { + defaultMessage: 'Remote Clusters', + }), + mount: async ({ element, setBreadcrumbs }) => { + const [core] = await getStartServices(); + const { + i18n: { Context: i18nContext }, + docLinks, + fatalErrors, + } = core; + + // Initialize services + initBreadcrumbs(setBreadcrumbs); + initDocumentation(docLinks); + initUiMetric(usageCollection); + initNotification(toasts, fatalErrors); + initHttp(http); + + const { renderApp } = await import('./application'); + return renderApp(element, i18nContext); + }, + }); + } + + start({ application }: CoreStart) { + initRedirect(application.navigateToApp); + } + + stop() {} +} diff --git a/x-pack/plugins/remote_clusters/public/types.ts b/x-pack/plugins/remote_clusters/public/types.ts new file mode 100644 index 0000000000000..45ae90f91587a --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/types.ts @@ -0,0 +1,19 @@ +/* + * 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 { ManagementSetup } from 'src/plugins/management/public'; +import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; +import { RegisterManagementAppArgs } from 'src/plugins/management/public'; +import { I18nStart } from 'kibana/public'; + +export interface Dependencies { + management: ManagementSetup; + usageCollection: UsageCollectionSetup; +} + +export { RegisterManagementAppArgs }; + +export { I18nStart }; diff --git a/x-pack/plugins/remote_clusters/server/config.ts b/x-pack/plugins/remote_clusters/server/config.ts new file mode 100644 index 0000000000000..9525fe1e2a0db --- /dev/null +++ b/x-pack/plugins/remote_clusters/server/config.ts @@ -0,0 +1,21 @@ +/* + * 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 { schema, TypeOf } from '@kbn/config-schema'; +import { PluginConfigDescriptor } from 'kibana/server'; + +export const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), +}); + +export type ConfigType = TypeOf; + +export const config: PluginConfigDescriptor = { + schema: configSchema, + exposeToBrowser: { + enabled: true, + }, +}; diff --git a/x-pack/plugins/remote_clusters/server/index.ts b/x-pack/plugins/remote_clusters/server/index.ts index 896161d82919b..927fa768fc9fd 100644 --- a/x-pack/plugins/remote_clusters/server/index.ts +++ b/x-pack/plugins/remote_clusters/server/index.ts @@ -6,4 +6,6 @@ import { PluginInitializerContext } from 'kibana/server'; import { RemoteClustersServerPlugin } from './plugin'; +export { config } from './config'; + export const plugin = (ctx: PluginInitializerContext) => new RemoteClustersServerPlugin(ctx); diff --git a/x-pack/plugins/remote_clusters/server/plugin.ts b/x-pack/plugins/remote_clusters/server/plugin.ts index dd0bb536d2695..d15ae44c8d5db 100644 --- a/x-pack/plugins/remote_clusters/server/plugin.ts +++ b/x-pack/plugins/remote_clusters/server/plugin.ts @@ -6,10 +6,12 @@ import { i18n } from '@kbn/i18n'; import { CoreSetup, Logger, Plugin, PluginInitializerContext } from 'src/core/server'; -import { PLUGIN } from '../common/constants'; +import { Observable } from 'rxjs'; import { LICENSE_CHECK_STATE } from '../../licensing/common/types'; -import { Dependencies, LicenseStatus, RouteDependencies } from './types'; +import { PLUGIN } from '../common/constants'; +import { Dependencies, LicenseStatus, RouteDependencies } from './types'; +import { ConfigType } from './config'; import { registerGetRoute, registerAddRoute, @@ -20,9 +22,11 @@ import { export class RemoteClustersServerPlugin implements Plugin { licenseStatus: LicenseStatus; log: Logger; + config: Observable; - constructor({ logger }: PluginInitializerContext) { + constructor({ logger, config }: PluginInitializerContext) { this.log = logger.get(); + this.config = config.create(); this.licenseStatus = { valid: false }; } diff --git a/x-pack/plugins/remote_clusters/server/routes/api/add_route.ts b/x-pack/plugins/remote_clusters/server/routes/api/add_route.ts index aa09b6bf45667..e4ede01ca23ea 100644 --- a/x-pack/plugins/remote_clusters/server/routes/api/add_route.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/add_route.ts @@ -38,8 +38,7 @@ export const register = (deps: RouteDependencies): void => { // Check if cluster already exists. const existingCluster = await doesClusterExist(callAsCurrentUser, name); if (existingCluster) { - return response.customError({ - statusCode: 409, + return response.conflict({ body: { message: i18n.translate( 'xpack.remoteClusters.addRemoteCluster.existingRemoteClusterErrorMessage', diff --git a/x-pack/plugins/remote_clusters/server/routes/api/update_route.ts b/x-pack/plugins/remote_clusters/server/routes/api/update_route.ts index fd707f15ad11e..ed584307d84c1 100644 --- a/x-pack/plugins/remote_clusters/server/routes/api/update_route.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/update_route.ts @@ -44,8 +44,7 @@ export const register = (deps: RouteDependencies): void => { // Check if cluster does exist. const existingCluster = await doesClusterExist(callAsCurrentUser, name); if (!existingCluster) { - return response.customError({ - statusCode: 404, + return response.notFound({ body: { message: i18n.translate( 'xpack.remoteClusters.updateRemoteCluster.noRemoteClusterErrorMessage', From 94c856dd428fbf4638b3dca1e2cbf0cfa0c7bf1c Mon Sep 17 00:00:00 2001 From: Frank Hassanabad Date: Fri, 14 Feb 2020 20:14:59 -0700 Subject: [PATCH 20/32] [SIEM][Detection Engine] Fixes queries to ignore errors when signals index is not present ## Summary Fixes a bug where if you try to query the signals index and it is not present you would get an error that would bubble up to the UI. Before: Screen Shot 2020-02-13 at 12 57 55 PM After: Screen Shot 2020-02-13 at 8 43 28 PM Screen Shot 2020-02-13 at 8 43 34 PM Also fixes a regression bug with error toasters showing up when they shouldn't because of a signals index not existing. This only effects 7.6.x and master and is _not_ part of 7.6.0 at the moment. * https://github.com/elastic/kibana/issues/57641 ### Checklist Delete any items that are not applicable to this PR. ~~- [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/master/packages/kbn-i18n/README.md)~~ ~~- [ ] [Documentation](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#writing-documentation) was added for features that require explanation or tutorials~~ ~~- [ ] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios~~ ~~- [ ] This was checked for [keyboard-only and screenreader accessibility](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Accessibility_testing_checklist)~~ ~~- [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)~~ ~~- [ ] This was checked for cross-browser compatibility, [including a check against IE11](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility)~~ ### For maintainers ~~- [ ] This was checked for breaking API changes and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process)~~ --- .../signals/errors_types/get_index_error.ts | 4 +- .../signals/use_signal_index.tsx | 2 +- .../signals/open_close_signals_route.ts | 1 + .../routes/signals/query_signals_route.ts | 1 + .../security_and_spaces/tests/index.ts | 2 + .../tests/open_close_signals.ts | 54 +++++++++++++++++ .../tests/query_signals.ts | 60 +++++++++++++++++++ .../security_and_spaces/tests/utils.ts | 30 ++++++++++ 8 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/tests/query_signals.ts diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/errors_types/get_index_error.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/errors_types/get_index_error.ts index e4f2a658b7362..4f45b480772f2 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/errors_types/get_index_error.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/errors_types/get_index_error.ts @@ -8,13 +8,13 @@ import { MessageBody } from '../../../../components/ml/api/throw_if_not_ok'; export class SignalIndexError extends Error { message: string = ''; - statusCode: number = -1; + status_code: number = -1; error: string = ''; constructor(errObj: MessageBody) { super(errObj.message); this.message = errObj.message ?? ''; - this.statusCode = errObj.statusCode ?? -1; + this.status_code = errObj.status_code ?? -1; this.error = errObj.error ?? ''; this.name = 'SignalIndexError'; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_signal_index.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_signal_index.tsx index 2635d6e5540f1..813bd2483689c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_signal_index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_signal_index.tsx @@ -60,7 +60,7 @@ export const useSignalIndex = (): Return => { signalIndexName: null, createDeSignalIndex: createIndex, }); - if (error instanceof SignalIndexError && error.statusCode !== 404) { + if (error instanceof SignalIndexError && error.status_code !== 404) { errorToToaster({ title: i18n.SIGNAL_GET_NAME_FAILURE, error, dispatchToaster }); } } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals_route.ts index b2b938625180e..dd3b8d3c99e0c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals_route.ts @@ -54,6 +54,7 @@ export const setSignalsStatusRouteDef = ( }, query: queryObject, }, + ignoreUnavailable: true, }); } catch (exc) { // error while getting or updating signal with id: id in signal index .siem-signals diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.ts index a3602ffbded41..adb6e5f32921a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.ts @@ -38,6 +38,7 @@ export const querySignalsRouteDef = ( return clusterClient.callAsCurrentUser('search', { index, body: { query, aggs, _source, track_total_hits, size }, + ignoreUnavailable: true, }); } catch (exc) { // error while getting or updating signal with id: id in signal index .siem-signals diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts index ca6ef5b6cede9..b8034fd92e988 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts @@ -25,5 +25,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./update_rules_bulk')); loadTestFile(require.resolve('./patch_rules_bulk')); loadTestFile(require.resolve('./patch_rules')); + loadTestFile(require.resolve('./query_signals')); + loadTestFile(require.resolve('./open_close_signals')); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts new file mode 100644 index 0000000000000..e9e3e4299d108 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts @@ -0,0 +1,54 @@ +/* + * 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 expect from '@kbn/expect'; + +import { DETECTION_ENGINE_SIGNALS_STATUS_URL } from '../../../../legacy/plugins/siem/common/constants'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { + createSignalsIndex, + deleteSignalsIndex, + setSignalStatus, + getSignalStatusEmptyResponse, +} from './utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + + describe('open_close_signals', () => { + describe('validation checks', () => { + it('should not give errors when querying and the signals index does not exist yet', async () => { + const { body } = await supertest + .post(DETECTION_ENGINE_SIGNALS_STATUS_URL) + .set('kbn-xsrf', 'true') + .send(setSignalStatus({ signalIds: ['123'], status: 'open' })) + .expect(200); + + // remove any server generated items that are indeterministic + delete body.took; + + expect(body).to.eql(getSignalStatusEmptyResponse()); + }); + + it('should not give errors when querying and the signals index does exist and is empty', async () => { + await createSignalsIndex(supertest); + const { body } = await supertest + .post(DETECTION_ENGINE_SIGNALS_STATUS_URL) + .set('kbn-xsrf', 'true') + .send(setSignalStatus({ signalIds: ['123'], status: 'open' })) + .expect(200); + + // remove any server generated items that are indeterministic + delete body.took; + + expect(body).to.eql(getSignalStatusEmptyResponse()); + + await deleteSignalsIndex(supertest); + }); + }); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/query_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/query_signals.ts new file mode 100644 index 0000000000000..6fa62412ed467 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/query_signals.ts @@ -0,0 +1,60 @@ +/* + * 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 expect from '@kbn/expect'; + +import { DETECTION_ENGINE_QUERY_SIGNALS_URL } from '../../../../legacy/plugins/siem/common/constants'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { getSignalStatus, createSignalsIndex, deleteSignalsIndex } from './utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + + describe('query_signals_route', () => { + describe('validation checks', () => { + it('should not give errors when querying and the signals index does not exist yet', async () => { + const { body } = await supertest + .post(DETECTION_ENGINE_QUERY_SIGNALS_URL) + .set('kbn-xsrf', 'true') + .send(getSignalStatus()) + .expect(200); + + // remove any server generated items that are indeterministic + delete body.took; + + expect(body).to.eql({ + timed_out: false, + _shards: { total: 0, successful: 0, skipped: 0, failed: 0 }, + hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] }, + }); + }); + + it('should not give errors when querying and the signals index does exist and is empty', async () => { + await createSignalsIndex(supertest); + const { body } = await supertest + .post(DETECTION_ENGINE_QUERY_SIGNALS_URL) + .set('kbn-xsrf', 'true') + .send(getSignalStatus()) + .expect(200); + + // remove any server generated items that are indeterministic + delete body.took; + + expect(body).to.eql({ + timed_out: false, + _shards: { total: 1, successful: 1, skipped: 0, failed: 0 }, + hits: { total: { value: 0, relation: 'eq' }, max_score: null, hits: [] }, + aggregations: { + statuses: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); + + await deleteSignalsIndex(supertest); + }); + }); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/utils.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/utils.ts index b78073c0e737b..bef700d0409a5 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/utils.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/utils.ts @@ -53,6 +53,36 @@ export const getSimpleRule = (ruleId = 'rule-1'): Partial = query: 'user.name: root or user.name: admin', }); +export const getSignalStatus = () => ({ + aggs: { statuses: { terms: { field: 'signal.status', size: 10 } } }, +}); + +export const setSignalStatus = ({ + signalIds, + status, +}: { + signalIds: string[]; + status: 'open' | 'closed'; +}) => ({ + signal_ids: signalIds, + status, +}); + +export const getSignalStatusEmptyResponse = () => ({ + timed_out: false, + total: 0, + updated: 0, + deleted: 0, + batches: 0, + version_conflicts: 0, + noops: 0, + retries: { bulk: 0, search: 0 }, + throttled_millis: 0, + requests_per_second: -1, + throttled_until_millis: 0, + failures: [], +}); + /** * This is a typical simple rule for testing that is easy for most basic testing */ From e370df2e5f3fc3e40ac238e1f8cc15cd2c1978f2 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Sat, 15 Feb 2020 12:46:04 +0100 Subject: [PATCH 21/32] Expose Vis on the contract as it requires visTypes (#56968) Co-authored-by: Elastic Machine --- .../buckets/_terms_other_bucket_helper.js | 4 +- .../kibana/public/discover/build_services.ts | 3 ++ .../kibana/public/discover/legacy.ts | 10 ++++- .../discover/np_ready/angular/discover.js | 7 ++- .../kibana/public/discover/plugin.ts | 6 +++ .../__tests__/region_map_visualization.js | 8 ++-- .../coordinate_maps_visualization.js | 8 ++-- .../public/metric_vis_type.test.ts | 2 +- .../public/agg_table/__tests__/agg_table.js | 13 +++--- .../agg_table/__tests__/agg_table_group.js | 6 +-- .../__tests__/tag_cloud_visualization.js | 4 +- .../public/__tests__/vega_visualization.js | 8 ++-- .../__tests__/visualizations/pie_chart.js | 6 +-- .../np_ready/public/legacy/__tests__/_vis.js | 7 ++- .../public/np_ready/public/mocks.ts | 1 + .../public/np_ready/public/plugin.ts | 3 ++ .../np_ready/public/{vis.d.ts => vis.ts} | 9 ++-- .../public/np_ready/public/vis_impl.d.ts | 44 +++++++++++++++++++ .../np_ready/public/{vis.js => vis_impl.js} | 6 +-- .../public/saved_visualizations/_saved_vis.ts | 9 ++-- .../tabify/__tests__/_get_columns.js | 12 ++--- .../tabify/__tests__/_integration.js | 6 +-- .../tabify/__tests__/_response_writer.js | 8 ++-- .../ui/public/vis/__tests__/_agg_config.js | 42 +++++++++--------- .../ui/public/vis/__tests__/_agg_configs.js | 26 +++++------ 25 files changed, 165 insertions(+), 93 deletions(-) rename src/legacy/core_plugins/visualizations/public/np_ready/public/{vis.d.ts => vis.ts} (84%) create mode 100644 src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.d.ts rename src/legacy/core_plugins/visualizations/public/np_ready/public/{vis.js => vis_impl.js} (98%) diff --git a/src/legacy/core_plugins/data/public/search/aggs/__tests__/buckets/_terms_other_bucket_helper.js b/src/legacy/core_plugins/data/public/search/aggs/__tests__/buckets/_terms_other_bucket_helper.js index 247290731df57..749dad377f2e2 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/__tests__/buckets/_terms_other_bucket_helper.js +++ b/src/legacy/core_plugins/data/public/search/aggs/__tests__/buckets/_terms_other_bucket_helper.js @@ -24,7 +24,7 @@ import { mergeOtherBucketAggResponse, updateMissingBucket, } from '../../buckets/_terms_other_bucket_helper'; -import { Vis } from '../../../../../../../core_plugins/visualizations/public'; +import { start as visualizationsStart } from '../../../../../../../core_plugins/visualizations/public/np_ready/public/legacy'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; const visConfigSingleTerm = { @@ -191,7 +191,7 @@ describe('Terms Agg Other bucket helper', () => { ngMock.inject(Private => { const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - vis = new Vis(indexPattern, aggConfig); + vis = new visualizationsStart.Vis(indexPattern, aggConfig); }); } diff --git a/src/legacy/core_plugins/kibana/public/discover/build_services.ts b/src/legacy/core_plugins/kibana/public/discover/build_services.ts index f9265323b2dcb..81f1c911f1cc9 100644 --- a/src/legacy/core_plugins/kibana/public/discover/build_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/build_services.ts @@ -36,6 +36,7 @@ import { SharePluginStart } from '../../../../../plugins/share/public'; import { SavedSearch } from './np_ready/types'; import { DocViewsRegistry } from './np_ready/doc_views/doc_views_registry'; import { ChartsPluginStart } from '../../../../../plugins/charts/public'; +import { VisualizationsStart } from '../../../visualizations/public'; export interface DiscoverServices { addBasePath: (path: string) => string; @@ -56,6 +57,7 @@ export interface DiscoverServices { getSavedSearchById: (id: string) => Promise; getSavedSearchUrlById: (id: string) => Promise; uiSettings: IUiSettingsClient; + visualizations: VisualizationsStart; } export async function buildServices( core: CoreStart, @@ -89,5 +91,6 @@ export async function buildServices( timefilter: plugins.data.query.timefilter.timefilter, toastNotifications: core.notifications.toasts, uiSettings: core.uiSettings, + visualizations: plugins.visualizations, }; } diff --git a/src/legacy/core_plugins/kibana/public/discover/legacy.ts b/src/legacy/core_plugins/kibana/public/discover/legacy.ts index ff44fbbe115d5..a1ef646f4fe85 100644 --- a/src/legacy/core_plugins/kibana/public/discover/legacy.ts +++ b/src/legacy/core_plugins/kibana/public/discover/legacy.ts @@ -20,10 +20,18 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; import { plugin } from './index'; +import { + setup as visualizationsSetup, + start as visualizationsStart, +} from '../../../../core_plugins/visualizations/public/np_ready/public/legacy'; // Legacy compatibility part - to be removed at cutover, replaced by a kibana.json file export const pluginInstance = plugin({} as PluginInitializerContext); export const setup = pluginInstance.setup(npSetup.core, { ...npSetup.plugins, + visualizations: visualizationsSetup, +}); +export const start = pluginInstance.start(npStart.core, { + ...npStart.plugins, + visualizations: visualizationsStart, }); -export const start = pluginInstance.start(npStart.core, npStart.plugins); diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js index 39a9ca6641fd1..bf5049cd976a3 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js @@ -60,7 +60,6 @@ import { ensureDefaultIndexPattern, registerTimefilterWithGlobalStateFactory, } from '../../kibana_services'; -import { Vis } from '../../../../../visualizations/public'; const { core, @@ -71,6 +70,7 @@ const { timefilter, toastNotifications, uiSettings, + visualizations, } = getServices(); import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../helpers/breadcrumbs'; @@ -990,7 +990,10 @@ function discoverController( }, }; - $scope.vis = new Vis($scope.searchSource.getField('index'), visSavedObject.visState); + $scope.vis = new visualizations.Vis( + $scope.searchSource.getField('index'), + visSavedObject.visState + ); visSavedObject.vis = $scope.vis; $scope.searchSource.onRequestStart((searchSource, options) => { diff --git a/src/legacy/core_plugins/kibana/public/discover/plugin.ts b/src/legacy/core_plugins/kibana/public/discover/plugin.ts index a495b56d5e9ea..565382313e369 100644 --- a/src/legacy/core_plugins/kibana/public/discover/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/discover/plugin.ts @@ -36,6 +36,10 @@ import { DocViewInput, DocViewInputFn } from './np_ready/doc_views/doc_views_typ import { DocViewTable } from './np_ready/components/table/table'; import { JsonCodeBlock } from './np_ready/components/json_code_block/json_code_block'; import { HomePublicPluginSetup } from '../../../../../plugins/home/public'; +import { + VisualizationsStart, + VisualizationsSetup, +} from '../../../visualizations/public/np_ready/public'; /** * These are the interfaces with your public contracts. You should export these @@ -51,6 +55,7 @@ export interface DiscoverSetupPlugins { embeddable: IEmbeddableSetup; kibanaLegacy: KibanaLegacySetup; home: HomePublicPluginSetup; + visualizations: VisualizationsSetup; } export interface DiscoverStartPlugins { uiActions: UiActionsStart; @@ -60,6 +65,7 @@ export interface DiscoverStartPlugins { data: DataPublicPluginStart; share: SharePluginStart; inspector: any; + visualizations: VisualizationsStart; } const innerAngularName = 'app/discover'; const embeddableAngularName = 'app/discoverEmbeddable'; diff --git a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js index 55447905e6421..f11aab9b9db88 100644 --- a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js +++ b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js @@ -38,8 +38,10 @@ import afterdatachangePng from './afterdatachange.png'; import afterdatachangeandresizePng from './afterdatachangeandresize.png'; import aftercolorchangePng from './aftercolorchange.png'; import changestartupPng from './changestartup.png'; -import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; -import { Vis } from '../../../visualizations/public/np_ready/public/vis'; +import { + setup as visualizationsSetup, + start as visualizationsStart, +} from '../../../visualizations/public/np_ready/public/legacy'; import { createRegionMapVisualization } from '../region_map_visualization'; import { createRegionMapTypeDefinition } from '../region_map_type'; @@ -158,7 +160,7 @@ describe('RegionMapsVisualizationTests', function() { imageComparator = new ImageComparator(); - vis = new Vis(indexPattern, { + vis = new visualizationsStart.Vis(indexPattern, { type: 'region_map', }); diff --git a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js index ef2ea831e84fd..27e9459c7e06c 100644 --- a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js @@ -32,8 +32,10 @@ import EMS_TILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_ import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_bright'; import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated'; import EMS_STYLE_DARK_MAP from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_dark'; -import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; -import { Vis } from '../../../visualizations/public/np_ready/public/vis'; +import { + setup as visualizationsSetup, + start as visualizationsStart, +} from '../../../visualizations/public/np_ready/public/legacy'; import { createTileMapVisualization } from '../tile_map_visualization'; import { createTileMapTypeDefinition } from '../tile_map_type'; @@ -124,7 +126,7 @@ describe('CoordinateMapsVisualizationTest', function() { setupDOM('512px', '512px'); imageComparator = new ImageComparator(); - vis = new Vis(indexPattern, { + vis = new visualizationsStart.Vis(indexPattern, { type: 'tile_map', }); vis.params = { diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts index 15cd920b79e4a..67b5d018f4638 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts @@ -59,7 +59,7 @@ describe('metric_vis - createMetricVisTypeDefinition', () => { // TODO: remove when Vis is converted to typescript. Only importing Vis as type // @ts-ignore - vis = new Vis(stubIndexPattern, { + vis = new visualizationsStart.Vis(stubIndexPattern, { type: 'metric', aggs: [{ id: '1', type: 'top_hits', schema: 'metric', params: { field: 'ip' } }], }); diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js index fc5a24a66dab3..0dbff60613cb0 100644 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js @@ -26,10 +26,11 @@ import sinon from 'sinon'; import { tabifyAggResponse, npStart } from '../../legacy_imports'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { round } from 'lodash'; - -import { Vis } from '../../../../visualizations/public'; import { tableVisTypeDefinition } from '../../table_vis_type'; -import { setup as visualizationsSetup } from '../../../../visualizations/public/np_ready/public/legacy'; +import { + setup as visualizationsSetup, + start as visualizationsStart, +} from '../../../../visualizations/public/np_ready/public/legacy'; import { getAngularModule } from '../../get_inner_angular'; import { initTableVisLegacyModule } from '../../table_vis_legacy_module'; import { tableVisResponseHandler } from '../../table_vis_response_handler'; @@ -42,10 +43,10 @@ describe('Table Vis - AggTable Directive', function() { const tabifiedData = {}; const init = () => { - const vis1 = new Vis(indexPattern, 'table'); + const vis1 = new visualizationsStart.Vis(indexPattern, 'table'); tabifiedData.metricOnly = tabifyAggResponse(vis1.aggs, fixtures.metricOnly); - const vis2 = new Vis(indexPattern, { + const vis2 = new visualizationsStart.Vis(indexPattern, { type: 'table', params: { showMetricsAtAllLevels: true, @@ -64,7 +65,7 @@ describe('Table Vis - AggTable Directive', function() { metricsAtAllLevels: true, }); - const vis3 = new Vis(indexPattern, { + const vis3 = new visualizationsStart.Vis(indexPattern, { type: 'table', aggs: [ { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js index 3c633f21cbabb..f6ae41b024b7d 100644 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js @@ -23,10 +23,10 @@ import expect from '@kbn/expect'; import fixtures from 'fixtures/fake_hierarchical_data'; import { tabifyAggResponse, npStart } from '../../legacy_imports'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { Vis } from '../../../../visualizations/public'; import { getAngularModule } from '../../get_inner_angular'; import { initTableVisLegacyModule } from '../../table_vis_legacy_module'; import { tableVisResponseHandler } from '../../table_vis_response_handler'; +import { start as visualizationsStart } from '../../../../visualizations/public/np_ready/public/legacy'; describe('Table Vis - AggTableGroup Directive', function() { let $rootScope; @@ -35,10 +35,10 @@ describe('Table Vis - AggTableGroup Directive', function() { const tabifiedData = {}; const init = () => { - const vis1 = new Vis(indexPattern, 'table'); + const vis1 = new visualizationsStart.Vis(indexPattern, 'table'); tabifiedData.metricOnly = tabifyAggResponse(vis1.aggs, fixtures.metricOnly); - const vis2 = new Vis(indexPattern, { + const vis2 = new visualizationsStart.Vis(indexPattern, { type: 'pie', aggs: [ { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/components/__tests__/tag_cloud_visualization.js b/src/legacy/core_plugins/vis_type_tagcloud/public/components/__tests__/tag_cloud_visualization.js index 5f7d1ad90ecf8..55ecf98f994d2 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/components/__tests__/tag_cloud_visualization.js +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/components/__tests__/tag_cloud_visualization.js @@ -20,7 +20,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import LogstashIndexPatternStubProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { Vis } from '../../../../visualizations/public/np_ready/public/vis'; +import { start as visualizationsStart } from '../../../../../core_plugins/visualizations/public/np_ready/public/legacy'; import { ImageComparator } from 'test_utils/image_comparator'; import { createTagCloudVisualization } from '../tag_cloud_visualization'; import basicdrawPng from './basicdraw.png'; @@ -76,7 +76,7 @@ describe('TagCloudVisualizationTest', function() { beforeEach(async function() { setupDOM('512px', '512px'); imageComparator = new ImageComparator(); - vis = new Vis(indexPattern, { + vis = new visualizationsStart.Vis(indexPattern, { type: 'tagcloud', params: { bucket: { accessor: 0, format: {} }, diff --git a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js index 868e5729bd494..378590af29d3a 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js +++ b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js @@ -23,7 +23,6 @@ import ngMock from 'ng_mock'; import $ from 'jquery'; import { createVegaVisualization } from '../vega_visualization'; import LogstashIndexPatternStubProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { Vis } from '../../../visualizations/public/np_ready/public/vis'; import { ImageComparator } from 'test_utils/image_comparator'; import vegaliteGraph from '!!raw-loader!./vegalite_graph.hjson'; @@ -41,7 +40,10 @@ import vegaMapImage256 from './vega_map_image_256.png'; import { VegaParser } from '../data_model/vega_parser'; import { SearchCache } from '../data_model/search_cache'; -import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; +import { + setup as visualizationsSetup, + start as visualizationsStart, +} from '../../../visualizations/public/np_ready/public/legacy'; import { createVegaTypeDefinition } from '../vega_type'; // TODO This is an integration test and thus requires a running platform. When moving to the new platform, // this test has to be migrated to the newly created integration test environment. @@ -106,7 +108,7 @@ describe('VegaVisualizations', () => { setupDOM('512px', '512px'); imageComparator = new ImageComparator(); - vis = new Vis(indexPattern, { type: 'vega' }); + vis = new visualizationsStart.Vis(indexPattern, { type: 'vega' }); }); afterEach(function() { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js index e4da572259b69..534a523103774 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js @@ -25,7 +25,7 @@ import expect from '@kbn/expect'; import fixtures from 'fixtures/fake_hierarchical_data'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { Vis } from '../../../../../visualizations/public'; +import { start as visualizationsStart } from '../../../../../visualizations/public/np_ready/public/legacy'; import { getVis, getMockUiState } from '../lib/fixtures/_vis_fixture'; import { tabifyAggResponse } from '../../../legacy_imports'; import { vislibSlicesResponseHandler } from '../../response_handler'; @@ -133,7 +133,7 @@ describe('No global chart settings', function() { responseHandler = vislibSlicesResponseHandler; let id1 = 1; - stubVis1 = new Vis(indexPattern, { + stubVis1 = new visualizationsStart.Vis(indexPattern, { type: 'pie', aggs: rowAgg, }); @@ -222,7 +222,7 @@ describe('Vislib PieChart Class Test Suite', function() { responseHandler = vislibSlicesResponseHandler; let id = 1; - stubVis = new Vis(indexPattern, { + stubVis = new visualizationsStart.Vis(indexPattern, { type: 'pie', aggs: dataAgg, }); diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/_vis.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/_vis.js index d963315ef79db..8c75ba24051b0 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/_vis.js +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/_vis.js @@ -20,7 +20,6 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; -import { Vis } from '../..'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { start as visualizations } from '../../legacy'; @@ -49,7 +48,7 @@ describe('Vis Class', function() { ); beforeEach(function() { - vis = new Vis(indexPattern, stateFixture); + vis = new visualizations.Vis(indexPattern, stateFixture); }); const verifyVis = function(vis) { @@ -85,7 +84,7 @@ describe('Vis Class', function() { describe('setState()', function() { it('should set the state to defaults', function() { - const vis = new Vis(indexPattern); + const vis = new visualizations.Vis(indexPattern); expect(vis).to.have.property('type'); expect(vis.type).to.eql(visTypes.get('histogram')); expect(vis).to.have.property('aggs'); @@ -101,7 +100,7 @@ describe('Vis Class', function() { expect(vis.isHierarchical()).to.be(true); }); it('should return false for non-hierarchical vis (like histogram)', function() { - const vis = new Vis(indexPattern); + const vis = new visualizations.Vis(indexPattern); expect(vis.isHierarchical()).to.be(false); }); }); diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts index 1063b1718b851..a948757d7bd83 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts @@ -49,6 +49,7 @@ const createStartContract = (): VisualizationsStart => ({ }, getSavedVisualizationsLoader: jest.fn(), showNewVisModal: jest.fn(), + Vis: jest.fn(), }); const createInstance = async () => { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts index cbbeb7ff980a6..36c04923e3fd0 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts @@ -43,6 +43,7 @@ import { SavedObjectKibanaServicesWithVisualizations, } from '../../saved_visualizations'; import { SavedVisualizations } from '../../../../kibana/public/visualize/np_ready/types'; +import { VisImpl, VisImplConstructor } from './vis_impl'; import { showNewVisModal } from './wizard'; /** * Interface for this plugin's returned setup/start contracts. @@ -57,6 +58,7 @@ export interface VisualizationsStart { types: TypesStart; getSavedVisualizationsLoader: () => SavedVisualizations; showNewVisModal: typeof showNewVisModal; + Vis: VisImplConstructor; } export interface VisualizationsSetupDeps { @@ -131,6 +133,7 @@ export class VisualizationsPlugin types, getSavedVisualizationsLoader: () => this.getSavedVisualizationsLoader(), showNewVisModal, + Vis: VisImpl, }; } diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.d.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts similarity index 84% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/vis.d.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts index 71bf9bcf983ff..59a8013523ef6 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.d.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts @@ -42,9 +42,8 @@ export interface VisState { aggs: IAggConfigs; } -export declare class VisualizationController { - constructor(element: HTMLElement, vis: Vis); - public render(visData: any, visParams: any, update: { [key in Status]: boolean }): Promise; - public destroy(): void; - public isLoaded?(): Promise | void; +export interface VisualizationController { + render(visData: any, visParams: any, update: { [key in Status]: boolean }): Promise; + destroy(): void; + isLoaded?(): Promise | void; } diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.d.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.d.ts new file mode 100644 index 0000000000000..45d65efb5dcdf --- /dev/null +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.d.ts @@ -0,0 +1,44 @@ +/* + * 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 { Vis, VisState } from './vis'; +import { VisType } from './types'; +import { IIndexPattern } from '../../../../../../plugins/data/common'; + +type InitVisStateType = + | Partial + | Partial & { type: string }> + | string; + +export type VisImplConstructor = new ( + indexPattern: IIndexPattern, + visState?: InitVisStateType +) => VisImpl; + +export declare class VisImpl implements Vis { + constructor(indexPattern: IIndexPattern, visState?: InitVisStateType); + + type: VisType; + + // Since we haven't typed everything here yet, we basically "any" the rest + // of that interface. This should be removed as soon as this type definition + // has been completed. But that way we at least have typing for a couple of + // properties on that type. + [key: string]: any; +} diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js similarity index 98% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/vis.js rename to src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js index 0c2e5012df439..6f4ab6d708184 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.js +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js @@ -33,7 +33,7 @@ import { AggConfigs, PersistedState } from '../../legacy_imports'; import { updateVisualizationConfig } from './legacy/vis_update'; import { getTypes } from './services'; -class Vis extends EventEmitter { +class VisImpl extends EventEmitter { constructor(indexPattern, visState) { super(); visState = visState || {}; @@ -203,6 +203,6 @@ class Vis extends EventEmitter { } } -Vis.prototype.type = 'histogram'; +VisImpl.prototype.type = 'histogram'; -export { Vis }; +export { VisImpl }; diff --git a/src/legacy/core_plugins/visualizations/public/saved_visualizations/_saved_vis.ts b/src/legacy/core_plugins/visualizations/public/saved_visualizations/_saved_vis.ts index ca2305a9cc91c..8b8c5fe94cc95 100644 --- a/src/legacy/core_plugins/visualizations/public/saved_visualizations/_saved_vis.ts +++ b/src/legacy/core_plugins/visualizations/public/saved_visualizations/_saved_vis.ts @@ -26,14 +26,14 @@ */ import { SavedObject, SavedObjectKibanaServices } from 'ui/saved_objects/types'; import { createSavedObjectClass } from 'ui/saved_objects/saved_object'; -// @ts-ignore -import { updateOldState, Vis } from '../index'; +import { updateOldState } from '../index'; import { extractReferences, injectReferences } from './saved_visualization_references'; import { IIndexPattern } from '../../../../../plugins/data/public'; import { VisSavedObject } from '../embeddable/visualize_embeddable'; import { createSavedSearchesLoader } from '../../../kibana/public/discover'; import { VisualizeConstants } from '../../../kibana/public/visualize'; +import { VisImpl } from '../np_ready/public/vis_impl'; async function _afterEsResp(savedVis: VisSavedObject, services: any) { await _getLinkedSavedSearch(savedVis, services); @@ -72,9 +72,8 @@ async function _createVis(savedVis: VisSavedObject) { if (savedVis.visState) { savedVis.visState.title = savedVis.title; } - // the typescript compiler is wrong here, will be right when vis.js -> vis.ts - // @ts-ignore - savedVis.vis = new Vis(savedVis.searchSource!.getField('index'), savedVis.visState); + + savedVis.vis = new VisImpl(savedVis.searchSource!.getField('index')!, savedVis.visState); savedVis.vis!.savedSearchId = savedVis.savedSearchId; diff --git a/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js b/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js index 56536a2e5b536..3eb41c03050d0 100644 --- a/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js +++ b/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js @@ -20,7 +20,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { tabifyGetColumns } from '../_get_columns'; -import { Vis } from '../../../../../core_plugins/visualizations/public'; +import { start as visualizationsStart } from '../../../../../core_plugins/visualizations/public/np_ready/public/legacy'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; describe('get columns', function() { let indexPattern; @@ -33,7 +33,7 @@ describe('get columns', function() { ); it('should inject a count metric if no aggs exist', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'pie', }); while (vis.aggs.length) vis.aggs.pop(); @@ -49,7 +49,7 @@ describe('get columns', function() { }); it('should inject a count metric if only buckets exist', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'pie', aggs: [ { @@ -68,7 +68,7 @@ describe('get columns', function() { }); it('should inject the metric after each bucket if the vis is hierarchical', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'pie', aggs: [ { @@ -104,7 +104,7 @@ describe('get columns', function() { }); it('should inject the multiple metrics after each bucket if the vis is hierarchical', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'pie', aggs: [ { @@ -156,7 +156,7 @@ describe('get columns', function() { }); it('should put all metrics at the end of the columns if the vis is not hierarchical', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { diff --git a/src/legacy/ui/public/agg_response/tabify/__tests__/_integration.js b/src/legacy/ui/public/agg_response/tabify/__tests__/_integration.js index c7c328000772b..f3f2e20149acf 100644 --- a/src/legacy/ui/public/agg_response/tabify/__tests__/_integration.js +++ b/src/legacy/ui/public/agg_response/tabify/__tests__/_integration.js @@ -22,7 +22,7 @@ import fixtures from 'fixtures/fake_hierarchical_data'; import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { tabifyAggResponse } from '../tabify'; -import { Vis } from '../../../../../core_plugins/visualizations/public'; +import { start as visualizationsStart } from '../../../../../core_plugins/visualizations/public/np_ready/public/legacy'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; describe('tabifyAggResponse Integration', function() { @@ -42,7 +42,7 @@ describe('tabifyAggResponse Integration', function() { } it('transforms a simple response properly', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [], }); @@ -73,7 +73,7 @@ describe('tabifyAggResponse Integration', function() { let esResp; beforeEach(function() { - vis = new Vis(indexPattern, { + vis = new visualizationsStart.Vis(indexPattern, { type: 'pie', aggs: [ { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, diff --git a/src/legacy/ui/public/agg_response/tabify/__tests__/_response_writer.js b/src/legacy/ui/public/agg_response/tabify/__tests__/_response_writer.js index ced495ef23c36..b0c0f2f3d9100 100644 --- a/src/legacy/ui/public/agg_response/tabify/__tests__/_response_writer.js +++ b/src/legacy/ui/public/agg_response/tabify/__tests__/_response_writer.js @@ -20,7 +20,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { TabbedAggResponseWriter } from '../_response_writer'; -import { Vis } from '../../../../../core_plugins/visualizations/public'; +import { start as visualizationsStart } from '../../../../../core_plugins/visualizations/public/np_ready/public/legacy'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; describe('TabbedAggResponseWriter class', function() { @@ -61,7 +61,7 @@ describe('TabbedAggResponseWriter class', function() { ]; const createResponseWritter = (aggs = [], opts = {}) => { - const vis = new Vis(indexPattern, { type: 'histogram', aggs: aggs }); + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: aggs }); return new TabbedAggResponseWriter(vis.getAggConfig(), opts); }; @@ -88,7 +88,7 @@ describe('TabbedAggResponseWriter class', function() { describe('sets timeRange', function() { it("to the first nested object's range", function() { - const vis = new Vis(indexPattern, { type: 'histogram', aggs: [] }); + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [] }); const range = { gte: 0, lte: 100, @@ -106,7 +106,7 @@ describe('TabbedAggResponseWriter class', function() { }); it('to undefined if no nested object', function() { - const vis = new Vis(indexPattern, { type: 'histogram', aggs: [] }); + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [] }); const writer = new TabbedAggResponseWriter(vis.getAggConfig(), { timeRange: {}, diff --git a/src/legacy/ui/public/vis/__tests__/_agg_config.js b/src/legacy/ui/public/vis/__tests__/_agg_config.js index 7dccf3eec18aa..9e53044f681ba 100644 --- a/src/legacy/ui/public/vis/__tests__/_agg_config.js +++ b/src/legacy/ui/public/vis/__tests__/_agg_config.js @@ -20,8 +20,8 @@ import sinon from 'sinon'; import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { Vis } from '../../../../core_plugins/visualizations/public'; import { AggType, AggConfig } from '../../agg_types'; +import { start as visualizationsStart } from '../../../../core_plugins/visualizations/public/np_ready/public/legacy'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; @@ -37,7 +37,7 @@ describe('AggConfig', function() { describe('#toDsl', function() { it('calls #write()', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { @@ -55,7 +55,7 @@ describe('AggConfig', function() { }); it('uses the type name as the agg name', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { @@ -73,7 +73,7 @@ describe('AggConfig', function() { }); it('uses the params from #write() output as the agg params', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { @@ -93,7 +93,7 @@ describe('AggConfig', function() { }); it('includes subAggs from #write() output', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { @@ -219,8 +219,8 @@ describe('AggConfig', function() { testsIdentical.forEach((visConfig, index) => { it(`identical aggregations (${index})`, function() { - const vis1 = new Vis(indexPattern, visConfig); - const vis2 = new Vis(indexPattern, visConfig); + const vis1 = new visualizationsStart.Vis(indexPattern, visConfig); + const vis2 = new visualizationsStart.Vis(indexPattern, visConfig); expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(true); }); }); @@ -258,8 +258,8 @@ describe('AggConfig', function() { testsIdenticalDifferentOrder.forEach((test, index) => { it(`identical aggregations (${index}) - init json is in different order`, function() { - const vis1 = new Vis(indexPattern, test.config1); - const vis2 = new Vis(indexPattern, test.config2); + const vis1 = new visualizationsStart.Vis(indexPattern, test.config1); + const vis2 = new visualizationsStart.Vis(indexPattern, test.config2); expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(true); }); }); @@ -323,8 +323,8 @@ describe('AggConfig', function() { testsDifferent.forEach((test, index) => { it(`different aggregations (${index})`, function() { - const vis1 = new Vis(indexPattern, test.config1); - const vis2 = new Vis(indexPattern, test.config2); + const vis1 = new visualizationsStart.Vis(indexPattern, test.config1); + const vis2 = new visualizationsStart.Vis(indexPattern, test.config2); expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(false); }); }); @@ -332,7 +332,7 @@ describe('AggConfig', function() { describe('#toJSON', function() { it('includes the aggs id, params, type and schema', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { @@ -360,7 +360,7 @@ describe('AggConfig', function() { }); it('test serialization order is identical (for visual consistency)', function() { - const vis1 = new Vis(indexPattern, { + const vis1 = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { @@ -369,7 +369,7 @@ describe('AggConfig', function() { }, ], }); - const vis2 = new Vis(indexPattern, { + const vis2 = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { @@ -387,26 +387,26 @@ describe('AggConfig', function() { describe('#makeLabel', function() { it('uses the custom label if it is defined', function() { - const vis = new Vis(indexPattern, {}); + const vis = new visualizationsStart.Vis(indexPattern, {}); const aggConfig = vis.aggs.aggs[0]; aggConfig.params.customLabel = 'Custom label'; const label = aggConfig.makeLabel(); expect(label).to.be(aggConfig.params.customLabel); }); it('default label should be "Count"', function() { - const vis = new Vis(indexPattern, {}); + const vis = new visualizationsStart.Vis(indexPattern, {}); const aggConfig = vis.aggs.aggs[0]; const label = aggConfig.makeLabel(); expect(label).to.be('Count'); }); it('default label should be "Percentage of Count" when percentageMode is set to true', function() { - const vis = new Vis(indexPattern, {}); + const vis = new visualizationsStart.Vis(indexPattern, {}); const aggConfig = vis.aggs.aggs[0]; const label = aggConfig.makeLabel(true); expect(label).to.be('Percentage of Count'); }); - it('empty label if the Vis type is not defined', function() { - const vis = new Vis(indexPattern, {}); + it('empty label if the visualizationsStart.Vis type is not defined', function() { + const vis = new visualizationsStart.Vis(indexPattern, {}); const aggConfig = vis.aggs.aggs[0]; aggConfig.type = undefined; const label = aggConfig.makeLabel(); @@ -416,7 +416,7 @@ describe('AggConfig', function() { describe('#fieldFormatter - custom getFormat handler', function() { it('returns formatter from getFormat handler', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'metric', aggs: [ { @@ -447,7 +447,7 @@ describe('AggConfig', function() { let vis; beforeEach(function() { - vis = new Vis(indexPattern, visStateAggWithoutCustomGetFormat); + vis = new visualizationsStart.Vis(indexPattern, visStateAggWithoutCustomGetFormat); }); it("returns the field's formatter", function() { diff --git a/src/legacy/ui/public/vis/__tests__/_agg_configs.js b/src/legacy/ui/public/vis/__tests__/_agg_configs.js index 62ad9a40ad058..172523ec50c8b 100644 --- a/src/legacy/ui/public/vis/__tests__/_agg_configs.js +++ b/src/legacy/ui/public/vis/__tests__/_agg_configs.js @@ -22,7 +22,7 @@ import sinon from 'sinon'; import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { AggConfig, AggConfigs, AggGroupNames, Schemas } from '../../agg_types'; -import { Vis } from '../../../../core_plugins/visualizations/public'; +import { start as visualizationsStart } from '../../../../core_plugins/visualizations/public/np_ready/public/legacy'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; describe('AggConfigs', function() { @@ -38,7 +38,7 @@ describe('AggConfigs', function() { describe('constructor', function() { it('handles passing just a vis', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [], }); @@ -48,7 +48,7 @@ describe('AggConfigs', function() { }); it('converts configStates into AggConfig objects if they are not already', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [], }); @@ -72,7 +72,7 @@ describe('AggConfigs', function() { }); it('attempts to ensure that all states have an id', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [], }); @@ -154,7 +154,7 @@ describe('AggConfigs', function() { describe('#getRequestAggs', function() { it('performs a stable sort, but moves metrics to the bottom', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { type: 'avg', schema: 'metric' }, @@ -185,7 +185,7 @@ describe('AggConfigs', function() { describe('#getResponseAggs', function() { it('returns all request aggs for basic aggs', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { type: 'terms', schema: 'split' }, @@ -206,7 +206,7 @@ describe('AggConfigs', function() { }); it('expands aggs that have multiple responses', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { type: 'terms', schema: 'split' }, @@ -231,14 +231,14 @@ describe('AggConfigs', function() { describe('#toDsl', function() { it('uses the sorted aggs', function() { - const vis = new Vis(indexPattern, { type: 'histogram' }); + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram' }); sinon.spy(vis.aggs, 'getRequestAggs'); vis.aggs.toDsl(); expect(vis.aggs.getRequestAggs).to.have.property('callCount', 1); }); it('calls aggConfig#toDsl() on each aggConfig and compiles the nested output', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { type: 'date_histogram', schema: 'segment' }, @@ -272,7 +272,7 @@ describe('AggConfigs', function() { }); it("skips aggs that don't have a dsl representation", function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { @@ -295,7 +295,7 @@ describe('AggConfigs', function() { }); it('writes multiple metric aggregations at the same level', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { @@ -326,7 +326,7 @@ describe('AggConfigs', function() { }); it('writes multiple metric aggregations at every level if the vis is hierarchical', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { type: 'terms', schema: 'segment', params: { field: 'ip', orderBy: 1 } }, @@ -362,7 +362,7 @@ describe('AggConfigs', function() { }); it('adds the parent aggs of nested metrics at every level if the vis is hierarchical', function() { - const vis = new Vis(indexPattern, { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram', aggs: [ { From 3b232ae73577d2067c820d8b22d57a07cba21334 Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Sat, 15 Feb 2020 19:32:16 -0500 Subject: [PATCH 22/32] Fix login redirect for expired sessions (#57157) --- .../security/public/services/auto_logout.js | 22 ++++- x-pack/plugins/security/public/plugin.tsx | 7 +- .../public/session/session_expired.test.ts | 91 +++++++------------ .../public/session/session_expired.ts | 30 +++--- ...thorized_response_http_interceptor.test.ts | 8 +- 5 files changed, 76 insertions(+), 82 deletions(-) diff --git a/x-pack/legacy/plugins/security/public/services/auto_logout.js b/x-pack/legacy/plugins/security/public/services/auto_logout.js index eb00d62d0266c..fa4d149d1f2e6 100644 --- a/x-pack/legacy/plugins/security/public/services/auto_logout.js +++ b/x-pack/legacy/plugins/security/public/services/auto_logout.js @@ -8,12 +8,26 @@ import { uiModules } from 'ui/modules'; import chrome from 'ui/chrome'; const module = uiModules.get('security'); + +const getNextParameter = () => { + const { location } = window; + const next = encodeURIComponent(`${location.pathname}${location.search}${location.hash}`); + return `&next=${next}`; +}; + +const getProviderParameter = tenant => { + const key = `${tenant}/session_provider`; + const providerName = sessionStorage.getItem(key); + return providerName ? `&provider=${encodeURIComponent(providerName)}` : ''; +}; + module.service('autoLogout', ($window, Promise) => { return () => { - const next = chrome.removeBasePath(`${window.location.pathname}${window.location.hash}`); - $window.location.href = chrome.addBasePath( - `/logout?next=${encodeURIComponent(next)}&msg=SESSION_EXPIRED` - ); + const logoutUrl = chrome.getInjected('logoutUrl'); + const tenant = `${chrome.getInjected('session.tenant', '')}`; + const next = getNextParameter(); + const provider = getProviderParameter(tenant); + $window.location.href = `${logoutUrl}?msg=SESSION_EXPIRED${next}${provider}`; return Promise.halt(); }; }); diff --git a/x-pack/plugins/security/public/plugin.tsx b/x-pack/plugins/security/public/plugin.tsx index f1ac2e2ecc3e2..467f86bd1ac69 100644 --- a/x-pack/plugins/security/public/plugin.tsx +++ b/x-pack/plugins/security/public/plugin.tsx @@ -57,13 +57,14 @@ export class SecurityPlugin { home, licensing, management }: PluginSetupDependencies ) { const { http, notifications, injectedMetadata } = core; - const { basePath, anonymousPaths } = http; + const { anonymousPaths } = http; anonymousPaths.register('/login'); anonymousPaths.register('/logout'); anonymousPaths.register('/logged_out'); - const tenant = `${injectedMetadata.getInjectedVar('session.tenant', '')}`; - const sessionExpired = new SessionExpired(basePath, tenant); + const tenant = injectedMetadata.getInjectedVar('session.tenant', '') as string; + const logoutUrl = injectedMetadata.getInjectedVar('logoutUrl') as string; + const sessionExpired = new SessionExpired(logoutUrl, tenant); http.intercept(new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths)); this.sessionTimeout = new SessionTimeout(notifications, sessionExpired, http, tenant); http.intercept(new SessionTimeoutHttpInterceptor(this.sessionTimeout, anonymousPaths)); diff --git a/x-pack/plugins/security/public/session/session_expired.test.ts b/x-pack/plugins/security/public/session/session_expired.test.ts index 678c397dfbc64..f5ad9cb464e3e 100644 --- a/x-pack/plugins/security/public/session/session_expired.test.ts +++ b/x-pack/plugins/security/public/session/session_expired.test.ts @@ -4,11 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { coreMock } from 'src/core/public/mocks'; import { SessionExpired } from './session_expired'; -describe('Session Expiration', () => { +describe('#logout', () => { const mockGetItem = jest.fn().mockReturnValue(null); + const CURRENT_URL = '/foo/bar?baz=quz#quuz'; + const LOGOUT_URL = '/logout'; + const TENANT = '/some-basepath'; + + let newUrlPromise: Promise; beforeAll(() => { Object.defineProperty(window, 'sessionStorage', { @@ -19,69 +23,42 @@ describe('Session Expiration', () => { }); }); + beforeEach(() => { + window.history.pushState({}, '', CURRENT_URL); + mockGetItem.mockReset(); + newUrlPromise = new Promise(resolve => { + jest.spyOn(window.location, 'assign').mockImplementation(url => { + resolve(url); + }); + }); + }); + afterAll(() => { delete (window as any).sessionStorage; }); - describe('logout', () => { - const mockCurrentUrl = (url: string) => window.history.pushState({}, '', url); - const tenant = ''; - - it('redirects user to "/logout" when there is no basePath', async () => { - const { basePath } = coreMock.createSetup().http; - mockCurrentUrl('/foo/bar?baz=quz#quuz'); - const sessionExpired = new SessionExpired(basePath, tenant); - const newUrlPromise = new Promise(resolve => { - jest.spyOn(window.location, 'assign').mockImplementation(url => { - resolve(url); - }); - }); - - sessionExpired.logout(); + it(`redirects user to the logout URL with 'msg' and 'next' parameters`, async () => { + const sessionExpired = new SessionExpired(LOGOUT_URL, TENANT); + sessionExpired.logout(); - const url = await newUrlPromise; - expect(url).toBe( - `/logout?next=${encodeURIComponent('/foo/bar?baz=quz#quuz')}&msg=SESSION_EXPIRED` - ); - }); - - it('adds a provider parameter when an auth provider is saved in sessionStorage', async () => { - const { basePath } = coreMock.createSetup().http; - mockCurrentUrl('/foo/bar?baz=quz#quuz'); - const sessionExpired = new SessionExpired(basePath, tenant); - const newUrlPromise = new Promise(resolve => { - jest.spyOn(window.location, 'assign').mockImplementation(url => { - resolve(url); - }); - }); - mockGetItem.mockReturnValueOnce('basic'); - - sessionExpired.logout(); + const next = `&next=${encodeURIComponent(CURRENT_URL)}`; + await expect(newUrlPromise).resolves.toBe(`${LOGOUT_URL}?msg=SESSION_EXPIRED${next}`); + }); - const url = await newUrlPromise; - expect(url).toBe( - `/logout?next=${encodeURIComponent( - '/foo/bar?baz=quz#quuz' - )}&msg=SESSION_EXPIRED&provider=basic` - ); - }); + it(`adds 'provider' parameter when sessionStorage contains the provider name for this tenant`, async () => { + const providerName = 'basic'; + mockGetItem.mockReturnValueOnce(providerName); - it('redirects user to "/${basePath}/logout" and removes basePath from next parameter when there is a basePath', async () => { - const { basePath } = coreMock.createSetup({ basePath: '/foo' }).http; - mockCurrentUrl('/foo/bar?baz=quz#quuz'); - const sessionExpired = new SessionExpired(basePath, tenant); - const newUrlPromise = new Promise(resolve => { - jest.spyOn(window.location, 'assign').mockImplementation(url => { - resolve(url); - }); - }); + const sessionExpired = new SessionExpired(LOGOUT_URL, TENANT); + sessionExpired.logout(); - sessionExpired.logout(); + expect(mockGetItem).toHaveBeenCalledTimes(1); + expect(mockGetItem).toHaveBeenCalledWith(`${TENANT}/session_provider`); - const url = await newUrlPromise; - expect(url).toBe( - `/foo/logout?next=${encodeURIComponent('/bar?baz=quz#quuz')}&msg=SESSION_EXPIRED` - ); - }); + const next = `&next=${encodeURIComponent(CURRENT_URL)}`; + const provider = `&provider=${providerName}`; + await expect(newUrlPromise).resolves.toBe( + `${LOGOUT_URL}?msg=SESSION_EXPIRED${next}${provider}` + ); }); }); diff --git a/x-pack/plugins/security/public/session/session_expired.ts b/x-pack/plugins/security/public/session/session_expired.ts index a43da85526757..5866526b8851e 100644 --- a/x-pack/plugins/security/public/session/session_expired.ts +++ b/x-pack/plugins/security/public/session/session_expired.ts @@ -4,26 +4,28 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HttpSetup } from 'src/core/public'; - export interface ISessionExpired { logout(): void; } +const getNextParameter = () => { + const { location } = window; + const next = encodeURIComponent(`${location.pathname}${location.search}${location.hash}`); + return `&next=${next}`; +}; + +const getProviderParameter = (tenant: string) => { + const key = `${tenant}/session_provider`; + const providerName = sessionStorage.getItem(key); + return providerName ? `&provider=${encodeURIComponent(providerName)}` : ''; +}; + export class SessionExpired { - constructor(private basePath: HttpSetup['basePath'], private tenant: string) {} + constructor(private logoutUrl: string, private tenant: string) {} logout() { - const next = this.basePath.remove( - `${window.location.pathname}${window.location.search}${window.location.hash}` - ); - const key = `${this.tenant}/session_provider`; - const providerName = sessionStorage.getItem(key); - const provider = providerName ? `&provider=${encodeURIComponent(providerName)}` : ''; - window.location.assign( - this.basePath.prepend( - `/logout?next=${encodeURIComponent(next)}&msg=SESSION_EXPIRED${provider}` - ) - ); + const next = getNextParameter(); + const provider = getProviderParameter(this.tenant); + window.location.assign(`${this.logoutUrl}?msg=SESSION_EXPIRED${next}${provider}`); } } diff --git a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts index ff2db01cb6c58..fba2a2ec98146 100644 --- a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts +++ b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts @@ -33,7 +33,7 @@ afterEach(() => { it(`logs out 401 responses`, async () => { const http = setupHttp('/foo'); - const sessionExpired = new SessionExpired(http.basePath, tenant); + const sessionExpired = new SessionExpired(`${http.basePath}/logout`, tenant); const logoutPromise = new Promise(resolve => { jest.spyOn(sessionExpired, 'logout').mockImplementation(() => resolve()); }); @@ -59,7 +59,7 @@ it(`ignores anonymous paths`, async () => { const http = setupHttp('/foo'); const { anonymousPaths } = http; anonymousPaths.register('/bar'); - const sessionExpired = new SessionExpired(http.basePath, tenant); + const sessionExpired = new SessionExpired(`${http.basePath}/logout`, tenant); const interceptor = new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths); http.intercept(interceptor); fetchMock.mock('*', 401); @@ -70,7 +70,7 @@ it(`ignores anonymous paths`, async () => { it(`ignores errors which don't have a response, for example network connectivity issues`, async () => { const http = setupHttp('/foo'); - const sessionExpired = new SessionExpired(http.basePath, tenant); + const sessionExpired = new SessionExpired(`${http.basePath}/logout`, tenant); const interceptor = new UnauthorizedResponseHttpInterceptor(sessionExpired, http.anonymousPaths); http.intercept(interceptor); fetchMock.mock('*', new Promise((resolve, reject) => reject(new Error('Network is down')))); @@ -81,7 +81,7 @@ it(`ignores errors which don't have a response, for example network connectivity it(`ignores requests which omit credentials`, async () => { const http = setupHttp('/foo'); - const sessionExpired = new SessionExpired(http.basePath, tenant); + const sessionExpired = new SessionExpired(`${http.basePath}/logout`, tenant); const interceptor = new UnauthorizedResponseHttpInterceptor(sessionExpired, http.anonymousPaths); http.intercept(interceptor); fetchMock.mock('*', 401); From 67087e34d1406b00b2e0ca5ce286bb90dc8b65da Mon Sep 17 00:00:00 2001 From: Ben Skelker <54019610+benskelker@users.noreply.github.com> Date: Sun, 16 Feb 2020 10:39:58 +0200 Subject: [PATCH 23/32] fixes ui titles (#57535) Co-authored-by: Elastic Machine --- .../siem/public/components/alerts_viewer/translations.ts | 2 +- .../components/signals_histogram_panel/translations.ts | 2 +- .../plugins/siem/public/pages/overview/translations.ts | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts index b0bc38bd3ebdc..79466251fc57b 100644 --- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts +++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts @@ -19,7 +19,7 @@ export const ALERTS_TABLE_TITLE = i18n.translate('xpack.siem.alertsView.alertsTa }); export const ALERTS_GRAPH_TITLE = i18n.translate('xpack.siem.alertsView.alertsGraphTitle', { - defaultMessage: 'External alerts count', + defaultMessage: 'External alert count', }); export const ALERTS_STACK_BY_MODULE = i18n.translate( diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts index 4cecf7376ca41..8c88fa4a5dae6 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts @@ -86,7 +86,7 @@ export const STACK_BY_USERS = i18n.translate( export const HISTOGRAM_HEADER = i18n.translate( 'xpack.siem.detectionEngine.signals.histogram.headerTitle', { - defaultMessage: 'Signals count', + defaultMessage: 'Signal count', } ); diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/translations.ts b/x-pack/legacy/plugins/siem/public/pages/overview/translations.ts index e20083bf51772..5ccd25984bc40 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/overview/translations.ts @@ -7,11 +7,11 @@ import { i18n } from '@kbn/i18n'; export const ALERTS_GRAPH_TITLE = i18n.translate('xpack.siem.overview.alertsGraphTitle', { - defaultMessage: 'External alerts count', + defaultMessage: 'External alert count', }); export const EVENTS = i18n.translate('xpack.siem.overview.eventsTitle', { - defaultMessage: 'Events count', + defaultMessage: 'Event count', }); export const NEWS_FEED_TITLE = i18n.translate('xpack.siem.overview.newsFeedSidebarTitle', { @@ -31,7 +31,7 @@ export const RECENT_TIMELINES = i18n.translate('xpack.siem.overview.recentTimeli }); export const SIGNAL_COUNT = i18n.translate('xpack.siem.overview.signalCountTitle', { - defaultMessage: 'Signals count', + defaultMessage: 'Signal count', }); export const VIEW_ALERTS = i18n.translate('xpack.siem.overview.viewAlertsButtonLabel', { From 335c7129924d25dc200d69c9b29c0b734634701b Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 16 Feb 2020 18:13:22 +0200 Subject: [PATCH 24/32] allow using any path to generate --- packages/kbn-plugin-generator/index.js | 4 +- .../kbn-plugin-generator/sao_template/sao.js | 81 +++++++++++++++---- 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/packages/kbn-plugin-generator/index.js b/packages/kbn-plugin-generator/index.js index 15adce7f01c8e..5417649db1a39 100644 --- a/packages/kbn-plugin-generator/index.js +++ b/packages/kbn-plugin-generator/index.js @@ -54,9 +54,8 @@ exports.run = function run(argv) { } const name = options._[0]; - const isKibanaPlugin = options.internal; const template = resolve(__dirname, './sao_template'); - const kibanaPlugins = resolve(__dirname, isKibanaPlugin ? '../../src/plugins' : '../../plugins'); + const kibanaPlugins = resolve(process.cwd(), 'plugins'); const targetPath = resolve(kibanaPlugins, snakeCase(name)); sao({ @@ -64,7 +63,6 @@ exports.run = function run(argv) { targetPath: targetPath, configOptions: { name, - isKibanaPlugin, targetPath, }, }).catch(error => { diff --git a/packages/kbn-plugin-generator/sao_template/sao.js b/packages/kbn-plugin-generator/sao_template/sao.js index aed4b9a02838f..f8d13b1229b7b 100755 --- a/packages/kbn-plugin-generator/sao_template/sao.js +++ b/packages/kbn-plugin-generator/sao_template/sao.js @@ -17,7 +17,8 @@ * under the License. */ -const { relative } = require('path'); +const { relative, resolve } = require('path'); +const fs = require('fs'); const startCase = require('lodash.startcase'); const camelCase = require('lodash.camelcase'); @@ -29,9 +30,54 @@ const pkg = require('../package.json'); const kibanaPkgPath = require.resolve('../../../package.json'); const kibanaPkg = require(kibanaPkgPath); // eslint-disable-line import/no-dynamic-require -module.exports = function({ name, targetPath, isKibanaPlugin }) { +async function gitInit(dir) { + // Only plugins in /plugins get git init + try { + await execa('git', ['init', dir]); + console.log(`Git repo initialized in ${dir}`); + } catch (error) { + console.error(error); + throw new Error(`Failure to git init ${dir}: ${error.all || error}`); + } +} + +async function moveToCustomFolder(from, to) { + try { + await execa('mv', [from, to]); + } catch (error) { + console.error(error); + throw new Error(`Failure to move plugin to ${to}: ${error.all || error}`); + } +} + +async function eslintPlugin(dir) { + try { + await execa('yarn', ['lint:es', `./${dir}/**/*.ts*`, '--no-ignore', '--fix']); + } catch (error) { + console.error(error); + throw new Error(`Failure when running prettier on the generated output: ${error.all || error}`); + } +} + +module.exports = function({ name, targetPath }) { return { prompts: { + customPath: { + message: 'Would you like to create the plugin in a different folder?', + default: '/plugins', + filter(value) { + // Keep default value empty + if (value === '/plugins') return ''; + return value; + }, + validate(customPath) { + const p = resolve(process.cwd(), customPath); + const exists = fs.existsSync(p); + if (!exists) + return `Folder should exist relative to the kibana root folder. Consider /src/plugins or /x-pack/plugins.`; + return true; + }, + }, description: { message: 'Provide a short description', default: 'An awesome Kibana plugin', @@ -64,7 +110,9 @@ module.exports = function({ name, targetPath, isKibanaPlugin }) { generateEslint: { type: 'confirm', message: 'Would you like to use a custom eslint file?', - default: !isKibanaPlugin, + default({ customPath }) { + return !customPath; + }, }, }, filters: { @@ -86,31 +134,32 @@ module.exports = function({ name, targetPath, isKibanaPlugin }) { camelCase, snakeCase, name, - isKibanaPlugin, + // kibana plugins are placed in a the non default path + isKibanaPlugin: !answers.customPath, kbnVersion: answers.kbnVersion, upperCamelCaseName: name.charAt(0).toUpperCase() + camelCase(name).slice(1), hasUi: !!answers.generateApp, hasServer: !!answers.generateApi, hasScss: !!answers.generateScss, - relRoot: isKibanaPlugin ? '../../../..' : '../../..', + relRoot: relative(resolve(answers.customPath || targetPath, 'public'), process.cwd()), }, answers ), enforceNewFolder: true, installDependencies: false, - gitInit: !isKibanaPlugin, - async post({ log }) { - const dir = relative(process.cwd(), targetPath); + async post({ log, answers }) { + let dir = relative(process.cwd(), targetPath); + if (answers.customPath) { + // Move to custom path + moveToCustomFolder(targetPath, answers.customPath); + dir = relative(process.cwd(), resolve(answers.customPath, snakeCase(name))); + } else { + // Init git only in the default path + await gitInit(dir); + } // Apply eslint to the generated plugin - try { - await execa('yarn', ['lint:es', `./${dir}/**/*.ts*`, '--no-ignore', '--fix']); - } catch (error) { - console.error(error); - throw new Error( - `Failure when running prettier on the generated output: ${error.all || error}` - ); - } + eslintPlugin(dir); log.success(chalk`🎉 From 36599fdfac18ddf6ecd475f0de461e4d5e87900f Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 16 Feb 2020 18:19:37 +0200 Subject: [PATCH 25/32] revert --- packages/kbn-plugin-generator/index.js | 4 +- .../kbn-plugin-generator/sao_template/sao.js | 81 ++++--------------- 2 files changed, 19 insertions(+), 66 deletions(-) diff --git a/packages/kbn-plugin-generator/index.js b/packages/kbn-plugin-generator/index.js index 5417649db1a39..15adce7f01c8e 100644 --- a/packages/kbn-plugin-generator/index.js +++ b/packages/kbn-plugin-generator/index.js @@ -54,8 +54,9 @@ exports.run = function run(argv) { } const name = options._[0]; + const isKibanaPlugin = options.internal; const template = resolve(__dirname, './sao_template'); - const kibanaPlugins = resolve(process.cwd(), 'plugins'); + const kibanaPlugins = resolve(__dirname, isKibanaPlugin ? '../../src/plugins' : '../../plugins'); const targetPath = resolve(kibanaPlugins, snakeCase(name)); sao({ @@ -63,6 +64,7 @@ exports.run = function run(argv) { targetPath: targetPath, configOptions: { name, + isKibanaPlugin, targetPath, }, }).catch(error => { diff --git a/packages/kbn-plugin-generator/sao_template/sao.js b/packages/kbn-plugin-generator/sao_template/sao.js index f8d13b1229b7b..aed4b9a02838f 100755 --- a/packages/kbn-plugin-generator/sao_template/sao.js +++ b/packages/kbn-plugin-generator/sao_template/sao.js @@ -17,8 +17,7 @@ * under the License. */ -const { relative, resolve } = require('path'); -const fs = require('fs'); +const { relative } = require('path'); const startCase = require('lodash.startcase'); const camelCase = require('lodash.camelcase'); @@ -30,54 +29,9 @@ const pkg = require('../package.json'); const kibanaPkgPath = require.resolve('../../../package.json'); const kibanaPkg = require(kibanaPkgPath); // eslint-disable-line import/no-dynamic-require -async function gitInit(dir) { - // Only plugins in /plugins get git init - try { - await execa('git', ['init', dir]); - console.log(`Git repo initialized in ${dir}`); - } catch (error) { - console.error(error); - throw new Error(`Failure to git init ${dir}: ${error.all || error}`); - } -} - -async function moveToCustomFolder(from, to) { - try { - await execa('mv', [from, to]); - } catch (error) { - console.error(error); - throw new Error(`Failure to move plugin to ${to}: ${error.all || error}`); - } -} - -async function eslintPlugin(dir) { - try { - await execa('yarn', ['lint:es', `./${dir}/**/*.ts*`, '--no-ignore', '--fix']); - } catch (error) { - console.error(error); - throw new Error(`Failure when running prettier on the generated output: ${error.all || error}`); - } -} - -module.exports = function({ name, targetPath }) { +module.exports = function({ name, targetPath, isKibanaPlugin }) { return { prompts: { - customPath: { - message: 'Would you like to create the plugin in a different folder?', - default: '/plugins', - filter(value) { - // Keep default value empty - if (value === '/plugins') return ''; - return value; - }, - validate(customPath) { - const p = resolve(process.cwd(), customPath); - const exists = fs.existsSync(p); - if (!exists) - return `Folder should exist relative to the kibana root folder. Consider /src/plugins or /x-pack/plugins.`; - return true; - }, - }, description: { message: 'Provide a short description', default: 'An awesome Kibana plugin', @@ -110,9 +64,7 @@ module.exports = function({ name, targetPath }) { generateEslint: { type: 'confirm', message: 'Would you like to use a custom eslint file?', - default({ customPath }) { - return !customPath; - }, + default: !isKibanaPlugin, }, }, filters: { @@ -134,32 +86,31 @@ module.exports = function({ name, targetPath }) { camelCase, snakeCase, name, - // kibana plugins are placed in a the non default path - isKibanaPlugin: !answers.customPath, + isKibanaPlugin, kbnVersion: answers.kbnVersion, upperCamelCaseName: name.charAt(0).toUpperCase() + camelCase(name).slice(1), hasUi: !!answers.generateApp, hasServer: !!answers.generateApi, hasScss: !!answers.generateScss, - relRoot: relative(resolve(answers.customPath || targetPath, 'public'), process.cwd()), + relRoot: isKibanaPlugin ? '../../../..' : '../../..', }, answers ), enforceNewFolder: true, installDependencies: false, - async post({ log, answers }) { - let dir = relative(process.cwd(), targetPath); - if (answers.customPath) { - // Move to custom path - moveToCustomFolder(targetPath, answers.customPath); - dir = relative(process.cwd(), resolve(answers.customPath, snakeCase(name))); - } else { - // Init git only in the default path - await gitInit(dir); - } + gitInit: !isKibanaPlugin, + async post({ log }) { + const dir = relative(process.cwd(), targetPath); // Apply eslint to the generated plugin - eslintPlugin(dir); + try { + await execa('yarn', ['lint:es', `./${dir}/**/*.ts*`, '--no-ignore', '--fix']); + } catch (error) { + console.error(error); + throw new Error( + `Failure when running prettier on the generated output: ${error.all || error}` + ); + } log.success(chalk`🎉 From f998174898eb68f8fe3996dc7186079c336a0e34 Mon Sep 17 00:00:00 2001 From: Patrick Mueller Date: Sun, 16 Feb 2020 17:55:52 -0500 Subject: [PATCH 26/32] [eventLog] get kibana.index name from config instead of hard-coding it (#57607) fixes https://github.com/elastic/kibana/issues/55629 --- x-pack/plugins/event_log/server/plugin.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/event_log/server/plugin.ts b/x-pack/plugins/event_log/server/plugin.ts index e32d4ff6f7acc..653e753446bb1 100644 --- a/x-pack/plugins/event_log/server/plugin.ts +++ b/x-pack/plugins/event_log/server/plugin.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import { CoreSetup, @@ -12,6 +13,7 @@ import { Plugin as CorePlugin, PluginInitializerContext, ClusterClient, + SharedGlobalConfig, } from 'src/core/server'; import { IEventLogConfig, IEventLogService, IEventLogger, IEventLogConfig$ } from './types'; @@ -20,9 +22,6 @@ import { createEsContext, EsContext } from './es'; export type PluginClusterClient = Pick; -// TODO - figure out how to get ${kibana.index} for `.kibana` -const KIBANA_INDEX = '.kibana'; - const PROVIDER = 'event_log'; const ACTIONS = { starting: 'starting', @@ -35,13 +34,18 @@ export class Plugin implements CorePlugin { private eventLogService?: IEventLogService; private esContext?: EsContext; private eventLogger?: IEventLogger; + private globalConfig$: Observable; constructor(private readonly context: PluginInitializerContext) { this.systemLogger = this.context.logger.get(); this.config$ = this.context.config.create(); + this.globalConfig$ = this.context.config.legacy.globalConfig$; } async setup(core: CoreSetup): Promise { + const globalConfig = await this.globalConfig$.pipe(first()).toPromise(); + const kibanaIndex = globalConfig.kibana.index; + this.systemLogger.debug('setting up plugin'); const config = await this.config$.pipe(first()).toPromise(); @@ -49,7 +53,7 @@ export class Plugin implements CorePlugin { this.esContext = createEsContext({ logger: this.systemLogger, // TODO: get index prefix from config.get(kibana.index) - indexNameRoot: KIBANA_INDEX, + indexNameRoot: kibanaIndex, clusterClient: core.elasticsearch.adminClient, }); From 5d3797ee0ba75faa120e1093ffe5db24f2d69f19 Mon Sep 17 00:00:00 2001 From: Patrick Mueller Date: Sun, 16 Feb 2020 20:10:35 -0500 Subject: [PATCH 27/32] change id of x-pack event_log plugin to eventLog (#57612) change id of x-pack event_log plugin to eventLog --- x-pack/plugins/actions/kibana.json | 2 +- x-pack/plugins/actions/server/plugin.test.ts | 4 ++-- x-pack/plugins/actions/server/plugin.ts | 6 +++--- x-pack/plugins/event_log/README.md | 16 ++++++++-------- x-pack/plugins/event_log/kibana.json | 4 ++-- x-pack/plugins/event_log/server/plugin.ts | 7 ++++--- .../alerting_api_integration/common/config.ts | 2 +- .../common/config.ts | 2 +- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/actions/kibana.json b/x-pack/plugins/actions/kibana.json index ff7f22af6261d..0c40dec46a6ee 100644 --- a/x-pack/plugins/actions/kibana.json +++ b/x-pack/plugins/actions/kibana.json @@ -4,7 +4,7 @@ "version": "8.0.0", "kibanaVersion": "kibana", "configPath": ["xpack", "actions"], - "requiredPlugins": ["licensing", "taskManager", "encryptedSavedObjects", "event_log"], + "requiredPlugins": ["licensing", "taskManager", "encryptedSavedObjects", "eventLog"], "optionalPlugins": ["spaces"], "ui": false } diff --git a/x-pack/plugins/actions/server/plugin.test.ts b/x-pack/plugins/actions/server/plugin.test.ts index ba6fbcd32daee..91944dfa8f3ad 100644 --- a/x-pack/plugins/actions/server/plugin.test.ts +++ b/x-pack/plugins/actions/server/plugin.test.ts @@ -27,7 +27,7 @@ describe('Actions Plugin', () => { taskManager: taskManagerMock.createSetup(), encryptedSavedObjects: encryptedSavedObjectsMock.createSetup(), licensing: licensingMock.createSetup(), - event_log: eventLogMock.createSetup(), + eventLog: eventLogMock.createSetup(), }; }); @@ -107,7 +107,7 @@ describe('Actions Plugin', () => { taskManager: taskManagerMock.createSetup(), encryptedSavedObjects: encryptedSavedObjectsMock.createSetup(), licensing: licensingMock.createSetup(), - event_log: eventLogMock.createSetup(), + eventLog: eventLogMock.createSetup(), }; pluginsStart = { taskManager: taskManagerMock.createStart(), diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 1714666882b05..b0555921f395f 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -70,7 +70,7 @@ export interface ActionsPluginsSetup { encryptedSavedObjects: EncryptedSavedObjectsPluginSetup; licensing: LicensingPluginSetup; spaces?: SpacesPluginSetup; - event_log: IEventLogService; + eventLog: IEventLogService; } export interface ActionsPluginsStart { encryptedSavedObjects: EncryptedSavedObjectsPluginStart; @@ -132,8 +132,8 @@ export class ActionsPlugin implements Plugin, Plugi attributesToEncrypt: new Set(['apiKey']), }); - plugins.event_log.registerProviderActions(EVENT_LOG_PROVIDER, Object.values(EVENT_LOG_ACTIONS)); - this.eventLogger = plugins.event_log.getLogger({ + plugins.eventLog.registerProviderActions(EVENT_LOG_PROVIDER, Object.values(EVENT_LOG_ACTIONS)); + this.eventLogger = plugins.eventLog.getLogger({ event: { provider: EVENT_LOG_PROVIDER }, }); diff --git a/x-pack/plugins/event_log/README.md b/x-pack/plugins/event_log/README.md index d2d67ffc27d94..027bbc694801f 100644 --- a/x-pack/plugins/event_log/README.md +++ b/x-pack/plugins/event_log/README.md @@ -9,14 +9,14 @@ and actions. ## Basic Usage - Logging Events -Follow these steps to use `event_log` in your plugin: +Follow these steps to use `eventLog` in your plugin: -1. Declare `event_log` as a dependency in `kibana.json`: +1. Declare `eventLog` as a dependency in `kibana.json`: ```json { ... - "requiredPlugins": ["event_log"], + "requiredPlugins": ["eventLog"], ... } ``` @@ -28,13 +28,13 @@ API provided in the `setup` stage: ... import { IEventLogger, IEventLogService } from '../../event_log/server'; interface PluginSetupDependencies { - event_log: IEventLogService; + eventLog: IEventLogService; } ... -public setup(core: CoreSetup, { event_log }: PluginSetupDependencies) { +public setup(core: CoreSetup, { eventLog }: PluginSetupDependencies) { ... - event_log.registerProviderActions('my-plugin', ['action-1, action-2']); - const eventLogger: IEventLogger = event_log.getLogger({ event: { provider: 'my-plugin' } }); + eventLog.registerProviderActions('my-plugin', ['action-1, action-2']); + const eventLogger: IEventLogger = eventLog.getLogger({ event: { provider: 'my-plugin' } }); ... } ... @@ -73,7 +73,7 @@ a new elasticsearch index referred to as the "event log". Example events are actions firing, alerts running their scheduled functions, alerts scheduling actions to run, etc. -This functionality will be provided in a new NP plugin `event_log`, and will +This functionality will be provided in a new NP plugin `eventLog`, and will provide server-side plugin APIs to write to the event log, and run limited queries against it. For now, access via HTTP will not be available, due to security concerns and lack of use cases. diff --git a/x-pack/plugins/event_log/kibana.json b/x-pack/plugins/event_log/kibana.json index 52b68deeffce5..7231d967b4c8d 100644 --- a/x-pack/plugins/event_log/kibana.json +++ b/x-pack/plugins/event_log/kibana.json @@ -1,8 +1,8 @@ { - "id": "event_log", + "id": "eventLog", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["xpack", "event_log"], + "configPath": ["xpack", "eventLog"], "server": true, "ui": false } diff --git a/x-pack/plugins/event_log/server/plugin.ts b/x-pack/plugins/event_log/server/plugin.ts index 653e753446bb1..fdb08b2d090a6 100644 --- a/x-pack/plugins/event_log/server/plugin.ts +++ b/x-pack/plugins/event_log/server/plugin.ts @@ -22,7 +22,8 @@ import { createEsContext, EsContext } from './es'; export type PluginClusterClient = Pick; -const PROVIDER = 'event_log'; +const PROVIDER = 'eventLog'; + const ACTIONS = { starting: 'starting', stopping: 'stopping', @@ -88,7 +89,7 @@ export class Plugin implements CorePlugin { // will log the event after initialization this.eventLogger.logEvent({ event: { action: ACTIONS.starting }, - message: 'event_log starting', + message: 'eventLog starting', }); } @@ -101,7 +102,7 @@ export class Plugin implements CorePlugin { // when Kibana is actuaelly stopping, as it's written asynchronously this.eventLogger.logEvent({ event: { action: ACTIONS.stopping }, - message: 'event_log stopping', + message: 'eventLog stopping', }); } } diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index d23bd2ac4646d..eb03aafc03d08 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -75,7 +75,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ])}`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, '--xpack.alerting.enabled=true', - '--xpack.event_log.logEntries=true', + '--xpack.eventLog.logEntries=true', ...disabledPlugins.map(key => `--xpack.${key}.enabled=false`), `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'alerts')}`, `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'actions')}`, diff --git a/x-pack/test/detection_engine_api_integration/common/config.ts b/x-pack/test/detection_engine_api_integration/common/config.ts index bf8e6982b545d..d2bfeeb6433d3 100644 --- a/x-pack/test/detection_engine_api_integration/common/config.ts +++ b/x-pack/test/detection_engine_api_integration/common/config.ts @@ -74,7 +74,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ])}`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, '--xpack.alerting.enabled=true', - '--xpack.event_log.logEntries=true', + '--xpack.eventLog.logEntries=true', ...disabledPlugins.map(key => `--xpack.${key}.enabled=false`), `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'alerts')}`, `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'actions')}`, From 8e17fdabd4954ee49ab6d2e327351cb20abc6e77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Mon, 17 Feb 2020 14:22:07 +0530 Subject: [PATCH 28/32] [Index management] Client-side NP ready (#57295) --- src/plugins/management/public/index.ts | 1 + src/plugins/management/public/types.ts | 2 +- .../components/detail_panel/detail_panel.js | 2 +- .../components/detail_panel/detail_panel.js | 2 +- .../public/extend_index_management/index.js | 4 +- .../__jest__/extend_index_management.test.js | 5 + .../components/policy_table/policy_table.js | 2 +- .../np_ready/extend_index_management/index.js | 28 +- .../helpers/home.helpers.ts | 9 +- .../helpers/setup_environment.ts | 39 --- .../helpers/setup_environment.tsx | 56 ++++ .../helpers/template_clone.helpers.ts | 5 +- .../helpers/template_create.helpers.ts | 8 +- .../helpers/template_edit.helpers.ts | 5 +- .../__jest__/components/index_table.test.js | 49 ++- .../__jest__/lib/flatten_object.test.js | 2 +- .../index_management/public/app/index.tsx | 36 -- .../index_list/detail_panel/detail_panel.js | 164 --------- .../public/app/services/ui_metric.ts | 25 -- .../public/app/store/reducers/detail_panel.js | 89 ----- .../public/{app => application}/app.tsx | 4 +- .../public/application/app_context.tsx | 52 +++ .../{app => application}/components/index.ts | 0 .../client_integration/helpers/index.ts | 0 .../helpers/mappings_editor.helpers.ts | 0 .../mappings_editor.test.tsx | 0 .../components/mappings_editor/_index.scss | 0 .../mappings_editor/components/_index.scss | 0 .../mappings_editor/components/code_block.tsx | 0 .../configuration_form/configuration_form.tsx | 0 .../configuration_form_schema.tsx | 0 .../dynamic_mapping_section.tsx | 0 .../dynamic_mapping_section/index.ts | 0 .../components/configuration_form/index.ts | 0 .../meta_field_section/index.ts | 0 .../meta_field_section/meta_field_section.tsx | 0 .../configuration_form/routing_section.tsx | 0 .../source_field_section/index.ts | 0 .../source_field_section.tsx | 0 .../components/document_fields/_index.scss | 0 .../document_fields/document_fields.tsx | 0 .../document_fields_header.tsx | 0 .../editor_toggle_controls.tsx | 0 .../field_parameters/analyzer_parameter.tsx | 0 .../analyzer_parameter_selects.tsx | 0 .../field_parameters/analyzers_parameter.tsx | 0 .../field_parameters/boost_parameter.tsx | 0 .../coerce_number_parameter.tsx | 0 .../coerce_shape_parameter.tsx | 0 .../field_parameters/copy_to_parameter.tsx | 0 .../field_parameters/doc_values_parameter.tsx | 0 .../field_parameters/dynamic_parameter.tsx | 0 .../eager_global_ordinals_parameter.tsx | 0 .../field_parameters/enabled_parameter.tsx | 0 .../fielddata_frequency_filter_absolute.tsx | 0 .../fielddata_frequency_filter_percentage.tsx | 0 .../field_parameters/fielddata_parameter.tsx | 0 .../field_parameters/format_parameter.tsx | 0 .../field_parameters/ignore_malformed.tsx | 0 .../ignore_z_value_parameter.tsx | 0 .../document_fields/field_parameters/index.ts | 0 .../field_parameters/index_parameter.tsx | 0 .../field_parameters/locale_parameter.tsx | 0 .../max_shingle_size_parameter.tsx | 0 .../field_parameters/name_parameter.tsx | 0 .../field_parameters/norms_parameter.tsx | 0 .../field_parameters/null_value_parameter.tsx | 0 .../orientation_parameter.tsx | 0 .../field_parameters/path_parameter.tsx | 0 .../field_parameters/relations_parameter.tsx | 0 .../field_parameters/similarity_parameter.tsx | 0 .../split_queries_on_whitespace_parameter.tsx | 0 .../field_parameters/store_parameter.tsx | 0 .../term_vector_parameter.tsx | 0 .../field_parameters/type_parameter.tsx | 0 .../fields/_field_list_item.scss | 0 .../document_fields/fields/_index.scss | 0 .../fields/create_field/create_field.tsx | 0 .../fields/create_field/index.ts | 0 .../required_parameters_forms/alias_type.tsx | 0 .../dense_vector_type.tsx | 0 .../required_parameters_forms/index.ts | 0 .../scaled_float_type.tsx | 0 .../token_count_type.tsx | 0 .../fields/delete_field_provider.tsx | 0 .../edit_field/_edit_field_form_row.scss | 0 .../fields/edit_field/_index.scss | 0 .../advanced_parameters_section.tsx | 0 .../edit_field/basic_parameters_section.tsx | 0 .../fields/edit_field/edit_field.tsx | 0 .../edit_field/edit_field_container.tsx | 0 .../fields/edit_field/edit_field_form_row.tsx | 0 .../edit_field/edit_field_header_form.tsx | 0 .../edit_field/field_description_section.tsx | 0 .../fields/edit_field/index.ts | 0 .../edit_field/update_field_provider.tsx | 0 .../fields/field_types/alias_type.tsx | 0 .../fields/field_types/binary_type.tsx | 0 .../fields/field_types/boolean_type.tsx | 0 .../fields/field_types/completion_type.tsx | 0 .../fields/field_types/date_type.tsx | 0 .../fields/field_types/dense_vector_type.tsx | 0 .../fields/field_types/flattened_type.tsx | 0 .../fields/field_types/geo_point_type.tsx | 0 .../fields/field_types/geo_shape_type.tsx | 0 .../fields/field_types/index.ts | 0 .../fields/field_types/ip_type.tsx | 0 .../fields/field_types/join_type.tsx | 0 .../fields/field_types/keyword_type.tsx | 0 .../fields/field_types/nested_type.tsx | 0 .../fields/field_types/numeric_type.tsx | 0 .../fields/field_types/object_type.tsx | 0 .../fields/field_types/range_type.tsx | 0 .../fields/field_types/search_as_you_type.tsx | 0 .../fields/field_types/shape_type.tsx | 0 .../fields/field_types/text_type.tsx | 0 .../fields/field_types/token_count_type.tsx | 0 .../document_fields/fields/fields_list.tsx | 0 .../fields/fields_list_item.tsx | 0 .../fields/fields_list_item_container.tsx | 0 .../document_fields/fields/index.ts | 0 .../modal_confirmation_delete_fields.tsx | 0 .../document_fields/fields_json_editor.tsx | 0 .../document_fields/fields_tree_editor.tsx | 0 .../components/document_fields/index.ts | 0 .../document_fields/search_fields/index.ts | 0 .../search_fields/search_result.tsx | 0 .../search_fields/search_result_item.tsx | 0 .../components/fields_tree.tsx | 0 .../mappings_editor/components/index.ts | 0 .../components/load_mappings/index.ts | 0 .../load_mappings/load_from_json_button.tsx | 0 .../load_mappings_provider.test.tsx | 0 .../load_mappings/load_mappings_provider.tsx | 0 .../components/multiple_mappings_warning.tsx | 0 .../components/templates_form/index.ts | 0 .../templates_form/templates_form.tsx | 0 .../templates_form/templates_form_schema.ts | 0 .../mappings_editor/components/tree/index.ts | 0 .../mappings_editor/components/tree/tree.tsx | 0 .../components/tree/tree_item.tsx | 0 .../constants/data_types_definition.tsx | 0 .../constants/default_values.ts | 0 .../constants/field_options.tsx | 0 .../constants/field_options_i18n.ts | 0 .../mappings_editor/constants/index.ts | 0 .../constants/mappings_editor.ts | 0 .../constants/parameters_definition.tsx | 0 .../components/mappings_editor/index.ts | 0 .../index_settings_context.tsx | 0 .../mappings_editor/lib/error_reporter.ts | 0 .../lib/extract_mappings_definition.test.ts | 0 .../lib/extract_mappings_definition.ts | 0 .../components/mappings_editor/lib/index.ts | 0 .../lib/mappings_validator.test.ts | 0 .../mappings_editor/lib/mappings_validator.ts | 0 .../mappings_editor/lib/search_fields.test.ts | 0 .../mappings_editor/lib/search_fields.tsx | 0 .../mappings_editor/lib/serializers.ts | 0 .../mappings_editor/lib/utils.test.ts | 0 .../components/mappings_editor/lib/utils.ts | 0 .../mappings_editor/lib/validators.ts | 0 .../mappings_editor/mappings_editor.tsx | 0 .../mappings_editor/mappings_state.tsx | 0 .../components/mappings_editor/reducer.ts | 0 .../mappings_editor/shared_imports.ts | 0 .../components/mappings_editor/types.ts | 0 .../components/no_match/index.ts | 0 .../components/no_match/no_match.tsx | 0 .../components/page_error/index.ts | 0 .../page_error/page_error_forbidden.tsx | 0 .../components/section_error.tsx | 0 .../components/section_loading.tsx | 0 .../components/template_delete_modal.tsx | 0 .../components/template_form/index.ts | 0 .../components/template_form/steps/index.ts | 0 .../template_form/steps/step_aliases.tsx | 0 .../template_form/steps/step_logistics.tsx | 0 .../template_form/steps/step_mappings.tsx | 0 .../template_form/steps/step_review.tsx | 0 .../template_form/steps/step_settings.tsx | 0 .../template_form/steps/use_json_step.ts | 0 .../template_form/template_form.tsx | 0 .../template_form/template_form_schemas.tsx | 0 .../template_form/template_steps.tsx | 0 .../components/template_form/types.ts | 0 .../constants/detail_panel_tabs.ts | 0 .../{app => application}/constants/index.ts | 0 .../constants/refresh_intervals.ts | 0 .../public/application/index.tsx | 45 +++ .../public/{app => application}/lib/ace.js | 0 .../{app => application}/lib/edit_settings.js | 0 .../lib/flatten_object.js | 0 .../lib/flatten_panel_tree.js | 0 .../lib/index_status_labels.js | 0 .../lib/manage_angular_lifecycle.ts | 0 .../{app => application}/lib/render_badges.js | 6 +- .../sections/home/home.tsx | 0 .../sections/home/index.ts | 0 .../detail_panel/detail_panel.container.js | 0 .../index_list/detail_panel/detail_panel.js | 167 ++++++++++ .../edit_settings_json.container.js | 0 .../edit_settings_json/edit_settings_json.js | 0 .../detail_panel/edit_settings_json/index.js | 0 .../home/index_list/detail_panel/index.js | 0 .../detail_panel/show_json/index.js | 0 .../show_json/show_json.container.js | 0 .../detail_panel/show_json/show_json.js | 0 .../index_list/detail_panel/summary/index.js | 0 .../detail_panel/summary/summary.container.js | 0 .../detail_panel/summary/summary.js | 58 ++-- .../sections/home/index_list/index.ts | 0 .../index_actions_context_menu/index.js | 0 .../index_actions_context_menu.container.js | 0 .../index_actions_context_menu.js | 126 +++---- .../sections/home/index_list/index_list.d.ts | 0 .../sections/home/index_list/index_list.js | 0 .../home/index_list/index_table/index.js | 0 .../index_table/index_table.container.js | 0 .../index_list/index_table/index_table.js | 314 +++++++++--------- .../sections/home/template_list/index.ts | 0 .../template_list/template_details/index.ts | 0 .../template_details/tabs/index.ts | 0 .../template_details/tabs/tab_aliases.tsx | 0 .../template_details/tabs/tab_mappings.tsx | 0 .../template_details/tabs/tab_settings.tsx | 0 .../template_details/tabs/tab_summary.tsx | 0 .../template_details/template_details.tsx | 3 +- .../home/template_list/template_list.tsx | 3 +- .../template_list/template_table/index.ts | 0 .../template_table/template_table.tsx | 3 +- .../sections/template_clone/index.ts | 0 .../template_clone/template_clone.tsx | 0 .../sections/template_create/index.ts | 0 .../template_create/template_create.tsx | 0 .../sections/template_edit/index.ts | 0 .../sections/template_edit/template_edit.tsx | 0 .../{app => application}/services/api.ts | 11 +- .../services/breadcrumbs.ts | 21 +- .../services/documentation.ts | 2 +- .../services/health_to_color.ts | 0 .../{app => application}/services/http.ts | 4 +- .../{app => application}/services/index.ts | 4 + .../services/navigation.ts | 0 .../services/notification.ts | 4 +- .../{app => application}/services/routing.ts | 0 .../services/sort_table.ts | 0 .../public/application/services/ui_metric.ts | 49 +++ .../services/use_request.ts | 0 .../store/actions/clear_cache_indices.js | 0 .../store/actions/clear_row_status.js | 0 .../store/actions/close_indices.js | 0 .../store/actions/delete_indices.js | 0 .../store/actions/detail_panel.js | 0 .../store/actions/edit_index_settings.js | 0 .../store/actions/extension_action.js | 0 .../store/actions/flush_indices.js | 0 .../store/actions/forcemerge_indices.js | 0 .../store/actions/freeze_indices.js | 0 .../store/actions/index.js | 0 .../store/actions/load_index_data.js | 0 .../store/actions/load_indices.js | 0 .../store/actions/open_indices.js | 0 .../store/actions/refresh_indices.js | 0 .../store/actions/reload_indices.js | 0 .../store/actions/table_state.js | 0 .../store/actions/unfreeze_indices.js | 0 .../store/actions/update_index_settings.js | 0 .../{app => application}/store/index.ts | 0 .../store/reducers/detail_panel.js | 89 +++++ .../store/reducers/index.js} | 2 +- .../store/reducers/index_management.js | 15 +- .../store/reducers/indices.js | 0 .../store/reducers/row_status.js | 0 .../store/reducers/table_state.js | 0 .../application/store/selectors/index.d.ts | 8 + .../store/selectors/index.js | 12 +- .../public/application/store/store.d.ts | 9 + .../{app => application}/store/store.js | 9 +- .../index_management/public/index.scss | 2 +- .../plugins/index_management/public/index.ts | 44 +-- .../public/index_management_extensions.ts | 72 ---- .../plugins/index_management/public/legacy.ts | 31 -- .../plugins/index_management/public/mocks.ts | 21 ++ .../plugins/index_management/public/plugin.ts | 112 +++++-- .../public/register_management_section.ts | 19 -- .../public/register_routes.ts | 34 -- .../services/extensions_service.mock.ts | 31 ++ .../public/services/extensions_service.ts | 97 ++++++ .../index_management/public/services/index.ts | 7 + .../{app/store/reducers/index.js => types.ts} | 2 +- x-pack/legacy/plugins/rollup/public/legacy.ts | 5 +- x-pack/legacy/plugins/rollup/public/plugin.ts | 11 +- 293 files changed, 1138 insertions(+), 903 deletions(-) delete mode 100644 x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.ts create mode 100644 x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx delete mode 100644 x-pack/legacy/plugins/index_management/public/app/index.tsx delete mode 100644 x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.js delete mode 100644 x-pack/legacy/plugins/index_management/public/app/services/ui_metric.ts delete mode 100644 x-pack/legacy/plugins/index_management/public/app/store/reducers/detail_panel.js rename x-pack/legacy/plugins/index_management/public/{app => application}/app.tsx (93%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/app_context.tsx rename x-pack/legacy/plugins/index_management/public/{app => application}/components/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/__jest__/client_integration/helpers/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/_index.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/_index.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/code_block.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/configuration_form.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/dynamic_mapping_section/dynamic_mapping_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/dynamic_mapping_section/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/meta_field_section/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/meta_field_section/meta_field_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/routing_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/source_field_section/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/source_field_section/source_field_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/_index.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/document_fields.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/document_fields_header.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/editor_toggle_controls.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/boost_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/coerce_number_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/coerce_shape_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/copy_to_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/doc_values_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_absolute.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_percentage.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/fielddata_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/format_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/ignore_malformed.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/index_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/locale_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/name_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/norms_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/null_value_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/orientation_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/path_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/similarity_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/split_queries_on_whitespace_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/store_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/term_vector_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/type_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/_field_list_item.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/_index.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/alias_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/dense_vector_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/scaled_float_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/token_count_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/delete_field_provider.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/_edit_field_form_row.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/_index.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/advanced_parameters_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/basic_parameters_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/edit_field.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_container.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_form_row.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/update_field_provider.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/alias_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/binary_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/boolean_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/completion_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/dense_vector_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/flattened_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/geo_point_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/geo_shape_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/ip_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/keyword_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/search_as_you_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/shape_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/text_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/fields_list.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/fields_list_item_container.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/modal_confirmation_delete_fields.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields_json_editor.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields_tree_editor.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/search_fields/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/search_fields/search_result.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/fields_tree.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/load_mappings/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/load_mappings/load_from_json_button.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/load_mappings/load_mappings_provider.test.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/multiple_mappings_warning.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/templates_form/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/templates_form/templates_form.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/templates_form/templates_form_schema.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/tree/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/tree/tree.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/tree/tree_item.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/data_types_definition.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/default_values.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/field_options.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/field_options_i18n.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/mappings_editor.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/parameters_definition.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/index_settings_context.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/error_reporter.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/extract_mappings_definition.test.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/extract_mappings_definition.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/mappings_validator.test.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/mappings_validator.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/search_fields.test.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/search_fields.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/serializers.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/utils.test.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/utils.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/validators.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/mappings_editor.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/mappings_state.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/reducer.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/shared_imports.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/types.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/no_match/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/no_match/no_match.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/page_error/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/page_error/page_error_forbidden.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/section_error.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/section_loading.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_delete_modal.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/step_aliases.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/step_logistics.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/step_mappings.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/step_review.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/step_settings.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/use_json_step.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/template_form.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/template_form_schemas.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/template_steps.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/types.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/constants/detail_panel_tabs.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/constants/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/constants/refresh_intervals.ts (100%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/index.tsx rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/ace.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/edit_settings.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/flatten_object.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/flatten_panel_tree.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/index_status_labels.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/manage_angular_lifecycle.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/render_badges.js (83%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/home.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/detail_panel.container.js (100%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.js rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.container.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/edit_settings_json/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/show_json/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/show_json/show_json.container.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/show_json/show_json.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/summary/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/summary/summary.container.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/summary/summary.js (72%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_actions_context_menu/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js (91%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_list.d.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_list.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_table/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_table/index_table.container.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_table/index_table.js (62%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/tabs/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/tabs/tab_aliases.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/tabs/tab_mappings.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/tabs/tab_settings.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/tabs/tab_summary.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/template_details.tsx (99%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_list.tsx (98%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_table/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_table/template_table.tsx (98%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_clone/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_clone/template_clone.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_create/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_create/template_create.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_edit/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_edit/template_edit.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/api.ts (94%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/breadcrumbs.ts (81%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/documentation.ts (99%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/health_to_color.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/http.ts (86%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/index.ts (82%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/navigation.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/notification.ts (91%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/routing.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/sort_table.ts (100%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/services/ui_metric.ts rename x-pack/legacy/plugins/index_management/public/{app => application}/services/use_request.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/clear_cache_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/clear_row_status.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/close_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/delete_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/detail_panel.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/edit_index_settings.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/extension_action.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/flush_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/forcemerge_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/freeze_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/load_index_data.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/load_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/open_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/refresh_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/reload_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/table_state.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/unfreeze_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/update_index_settings.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/index.ts (100%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/store/reducers/detail_panel.js rename x-pack/legacy/plugins/index_management/public/{app/store/store.d.ts => application/store/reducers/index.js} (82%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/reducers/index_management.js (63%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/reducers/indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/reducers/row_status.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/reducers/table_state.js (100%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/store/selectors/index.d.ts rename x-pack/legacy/plugins/index_management/public/{app => application}/store/selectors/index.js (93%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/store/store.d.ts rename x-pack/legacy/plugins/index_management/public/{app => application}/store/store.js (71%) delete mode 100644 x-pack/legacy/plugins/index_management/public/index_management_extensions.ts delete mode 100644 x-pack/legacy/plugins/index_management/public/legacy.ts create mode 100644 x-pack/legacy/plugins/index_management/public/mocks.ts delete mode 100644 x-pack/legacy/plugins/index_management/public/register_management_section.ts delete mode 100644 x-pack/legacy/plugins/index_management/public/register_routes.ts create mode 100644 x-pack/legacy/plugins/index_management/public/services/extensions_service.mock.ts create mode 100644 x-pack/legacy/plugins/index_management/public/services/extensions_service.ts create mode 100644 x-pack/legacy/plugins/index_management/public/services/index.ts rename x-pack/legacy/plugins/index_management/public/{app/store/reducers/index.js => types.ts} (78%) diff --git a/src/plugins/management/public/index.ts b/src/plugins/management/public/index.ts index 4ece75bbf36da..9e59834303546 100644 --- a/src/plugins/management/public/index.ts +++ b/src/plugins/management/public/index.ts @@ -29,6 +29,7 @@ export { ManagementStart, RegisterManagementApp, RegisterManagementAppArgs, + ManagementAppMountParams, } from './types'; export { ManagementApp } from './management_app'; export { ManagementSection } from './management_section'; diff --git a/src/plugins/management/public/types.ts b/src/plugins/management/public/types.ts index 4dbea30ff062d..a8bdd5cca24a3 100644 --- a/src/plugins/management/public/types.ts +++ b/src/plugins/management/public/types.ts @@ -64,7 +64,7 @@ export type RegisterManagementApp = (managementApp: RegisterManagementAppArgs) = export type Unmount = () => Promise | void; -interface ManagementAppMountParams { +export interface ManagementAppMountParams { basePath: string; // base path for setting up your router element: HTMLElement; // element the section should render into setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js b/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js index cd107be408727..16ed0a7d695ad 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js +++ b/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js @@ -7,7 +7,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from '@kbn/i18n/react'; -import { getIndexListUri } from '../../../../../../../../index_management/public/app/services/navigation'; +import { getIndexListUri } from '../../../../../../../../index_management/public/application/services/navigation'; import { EuiButtonEmpty, diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js b/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js index d4e43a1bd1840..e3bda2e67097d 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js +++ b/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js @@ -7,7 +7,7 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from '@kbn/i18n/react'; -import { getIndexListUri } from '../../../../../../../../index_management/public/app/services/navigation'; +import { getIndexListUri } from '../../../../../../../../index_management/public/application/services/navigation'; import { EuiButton, diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/extend_index_management/index.js b/x-pack/legacy/plugins/cross_cluster_replication/public/extend_index_management/index.js index 549c71748e1be..809a7c3e87b75 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/public/extend_index_management/index.js +++ b/x-pack/legacy/plugins/cross_cluster_replication/public/extend_index_management/index.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; -import { addBadgeExtension } from '../../../index_management/public/index_management_extensions'; +import { extensionsService } from '../../../index_management/public'; import { get } from 'lodash'; const propertyPath = 'isFollowerIndex'; @@ -19,4 +19,4 @@ export const followerBadgeExtension = { filterExpression: 'isFollowerIndex:true', }; -addBadgeExtension(followerBadgeExtension); +extensionsService.addBadge(followerBadgeExtension); diff --git a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js b/x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js index cfae072b57a26..bcbae7e093f46 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js @@ -7,6 +7,7 @@ import moment from 'moment-timezone'; import axios from 'axios'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; + import { mountWithIntl } from '../../../../test_utils/enzyme_helpers'; import { retryLifecycleActionExtension, @@ -26,6 +27,10 @@ initHttp(axios.create({ adapter: axiosXhrAdapter }), path => path); initUiMetric(() => () => {}); jest.mock('ui/new_platform'); +jest.mock('../../index_management/public', async () => { + const { indexManagementMock } = await import('../../index_management/public/mocks.ts'); + return indexManagementMock.createSetup(); +}); const indexWithoutLifecyclePolicy = { health: 'yellow', diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js index eba7f75aa9baf..83d32eae1097d 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js @@ -37,7 +37,7 @@ import { import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; -import { getIndexListUri } from '../../../../../../../../index_management/public/app/services/navigation'; +import { getIndexListUri } from '../../../../../../../../index_management/public/application/services/navigation'; import { BASE_PATH } from '../../../../../../../common/constants'; import { UIM_EDIT_CLICK } from '../../../../constants'; import { getPolicyPath } from '../../../../services/navigation'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js index 422a7986aa057..6958c4ecce0cc 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js @@ -9,13 +9,7 @@ import { get, every, any } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiSearchBar } from '@elastic/eui'; -import { - addSummaryExtension, - addBannerExtension, - addActionExtension, - addFilterExtension, -} from '../../../../index_management/public/index_management_extensions'; - +import { extensionsService } from '../../../../index_management/public'; import { init as initUiMetric } from '../application/services/ui_metric'; import { init as initNotification } from '../application/services/notification'; import { retryLifecycleForIndex } from '../application/services/api'; @@ -27,13 +21,17 @@ const stepPath = 'ilm.step'; export const retryLifecycleActionExtension = ({ indices, - createUiStatsReporter, + usageCollection, toasts, fatalErrors, }) => { // These are hacks that we can remove once the New Platform migration is done. They're needed here // because API requests and API errors require them. - initUiMetric(createUiStatsReporter); + const getLegacyReporter = appName => (type, name) => { + usageCollection.reportUiStats(appName, type, name); + }; + + initUiMetric(getLegacyReporter); initNotification(toasts, fatalErrors); const allHaveErrors = every(indices, index => { @@ -207,11 +205,11 @@ export const ilmFilterExtension = indices => { }; export const addAllExtensions = () => { - addActionExtension(retryLifecycleActionExtension); - addActionExtension(removeLifecyclePolicyActionExtension); - addActionExtension(addLifecyclePolicyActionExtension); + extensionsService.addAction(retryLifecycleActionExtension); + extensionsService.addAction(removeLifecyclePolicyActionExtension); + extensionsService.addAction(addLifecyclePolicyActionExtension); - addBannerExtension(ilmBannerExtension); - addSummaryExtension(ilmSummaryExtension); - addFilterExtension(ilmFilterExtension); + extensionsService.addBanner(ilmBannerExtension); + extensionsService.addSummary(ilmSummaryExtension); + extensionsService.addFilter(ilmFilterExtension); }; diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts index 4a4896347333c..e5f0b25d89c3e 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts @@ -13,13 +13,14 @@ import { findTestSubject, nextTick, } from '../../../../../../test_utils'; -import { IndexManagementHome } from '../../../public/app/sections/home'; +import { IndexManagementHome } from '../../../public/application/sections/home'; import { BASE_PATH } from '../../../common/constants'; -import { indexManagementStore } from '../../../public/app/store'; +import { indexManagementStore } from '../../../public/application/store'; import { Template } from '../../../common/types'; +import { WithAppDependencies, services } from './setup_environment'; const testBedConfig: TestBedConfig = { - store: indexManagementStore, + store: () => indexManagementStore(services as any), memoryRouter: { initialEntries: [`${BASE_PATH}indices`], componentRoutePath: `${BASE_PATH}:section(indices|templates)`, @@ -27,7 +28,7 @@ const testBedConfig: TestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(IndexManagementHome, testBedConfig); +const initTestBed = registerTestBed(WithAppDependencies(IndexManagementHome), testBedConfig); export interface IdxMgmtHomeTestBed extends TestBed { findAction: (action: 'edit' | 'clone' | 'delete') => ReactWrapper; diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.ts deleted file mode 100644 index d5ac185a63ccd..0000000000000 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.ts +++ /dev/null @@ -1,39 +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 axios from 'axios'; -import axiosXhrAdapter from 'axios/lib/adapters/xhr'; -import { init as initHttpRequests } from './http_requests'; -import { httpService } from '../../../public/app/services/http'; -import { breadcrumbService } from '../../../public/app/services/breadcrumbs'; -import { documentationService } from '../../../public/app/services/documentation'; -import { notificationService } from '../../../public/app/services/notification'; -import { uiMetricService } from '../../../public/app/services/ui_metric'; -import { createUiStatsReporter } from '../../../../../../../src/legacy/core_plugins/ui_metric/public'; - -/* eslint-disable @kbn/eslint/no-restricted-paths */ -import { notificationServiceMock } from '../../../../../../../src/core/public/notifications/notifications_service.mock'; -import { chromeServiceMock } from '../../../../../../../src/core/public/chrome/chrome_service.mock'; -import { docLinksServiceMock } from '../../../../../../../src/core/public/doc_links/doc_links_service.mock'; - -const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); - -export const setupEnvironment = () => { - // Mock initialization of services - // @ts-ignore - httpService.init(mockHttpClient); - breadcrumbService.init(chromeServiceMock.createStartContract(), ''); - documentationService.init(docLinksServiceMock.createStartContract()); - notificationService.init(notificationServiceMock.createStartContract()); - uiMetricService.init(createUiStatsReporter); - - const { server, httpRequestsMockHelpers } = initHttpRequests(); - - return { - server, - httpRequestsMockHelpers, - }; -}; diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx new file mode 100644 index 0000000000000..0212efe1f322d --- /dev/null +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.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 axios from 'axios'; +import axiosXhrAdapter from 'axios/lib/adapters/xhr'; + +import { + notificationServiceMock, + docLinksServiceMock, +} from '../../../../../../../src/core/public/mocks'; +import { AppContextProvider } from '../../../public/application/app_context'; +import { httpService } from '../../../public/application/services/http'; +import { breadcrumbService } from '../../../public/application/services/breadcrumbs'; +import { documentationService } from '../../../public/application/services/documentation'; +import { notificationService } from '../../../public/application/services/notification'; +import { ExtensionsService } from '../../../public/services'; +import { UiMetricService } from '../../../public/application/services/ui_metric'; +import { setUiMetricService } from '../../../public/application/services/api'; +import { setExtensionsService } from '../../../public/application/store/selectors'; +import { init as initHttpRequests } from './http_requests'; + +const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); + +export const services = { + extensionsService: new ExtensionsService(), + uiMetricService: new UiMetricService('index_management'), +}; +services.uiMetricService.setup({ reportUiStats() {} } as any); +setExtensionsService(services.extensionsService); +setUiMetricService(services.uiMetricService); +const appDependencies = { services, core: {}, plugins: {} } as any; + +export const setupEnvironment = () => { + // Mock initialization of services + // @ts-ignore + httpService.setup(mockHttpClient); + breadcrumbService.setup(() => undefined); + documentationService.setup(docLinksServiceMock.createStartContract()); + notificationService.setup(notificationServiceMock.createSetupContract()); + + const { server, httpRequestsMockHelpers } = initHttpRequests(); + + return { + server, + httpRequestsMockHelpers, + }; +}; + +export const WithAppDependencies = (Comp: any) => (props: any) => ( + + + +); diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_clone.helpers.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_clone.helpers.ts index 286e56b4349e4..cd1b67c08d934 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_clone.helpers.ts +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_clone.helpers.ts @@ -6,9 +6,10 @@ import { registerTestBed, TestBedConfig } from '../../../../../../test_utils'; import { BASE_PATH } from '../../../common/constants'; -import { TemplateClone } from '../../../public/app/sections/template_clone'; +import { TemplateClone } from '../../../public/application/sections/template_clone'; import { formSetup } from './template_form.helpers'; import { TEMPLATE_NAME } from './constants'; +import { WithAppDependencies } from './setup_environment'; const testBedConfig: TestBedConfig = { memoryRouter: { @@ -18,6 +19,6 @@ const testBedConfig: TestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(TemplateClone, testBedConfig); +const initTestBed = registerTestBed(WithAppDependencies(TemplateClone), testBedConfig); export const setup = formSetup.bind(null, initTestBed); diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_create.helpers.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_create.helpers.ts index b1b5d51ef6a9d..8e62bc25d6bd1 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_create.helpers.ts +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_create.helpers.ts @@ -6,8 +6,9 @@ import { registerTestBed, TestBedConfig } from '../../../../../../test_utils'; import { BASE_PATH } from '../../../common/constants'; -import { TemplateCreate } from '../../../public/app/sections/template_create'; +import { TemplateCreate } from '../../../public/application/sections/template_create'; import { formSetup, TestSubjects } from './template_form.helpers'; +import { WithAppDependencies } from './setup_environment'; const testBedConfig: TestBedConfig = { memoryRouter: { @@ -17,6 +18,9 @@ const testBedConfig: TestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(TemplateCreate, testBedConfig); +const initTestBed = registerTestBed( + WithAppDependencies(TemplateCreate), + testBedConfig +); export const setup = formSetup.bind(null, initTestBed); diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_edit.helpers.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_edit.helpers.ts index e8e19f637854d..cb1025234b48e 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_edit.helpers.ts +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_edit.helpers.ts @@ -6,9 +6,10 @@ import { registerTestBed, TestBedConfig } from '../../../../../../test_utils'; import { BASE_PATH } from '../../../common/constants'; -import { TemplateEdit } from '../../../public/app/sections/template_edit'; +import { TemplateEdit } from '../../../public/application/sections/template_edit'; import { formSetup, TestSubjects } from './template_form.helpers'; import { TEMPLATE_NAME } from './constants'; +import { WithAppDependencies } from './setup_environment'; const testBedConfig: TestBedConfig = { memoryRouter: { @@ -18,6 +19,6 @@ const testBedConfig: TestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(TemplateEdit, testBedConfig); +const initTestBed = registerTestBed(WithAppDependencies(TemplateEdit), testBedConfig); export const setup = formSetup.bind(null, initTestBed); diff --git a/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js b/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js index fe55b93d24a91..2b4fd89436458 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js +++ b/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js @@ -8,23 +8,25 @@ import React from 'react'; import axios from 'axios'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import { MemoryRouter } from 'react-router-dom'; -import { AppWithoutRouter } from '../../public/app/app'; +import { AppWithoutRouter } from '../../public/application/app'; +import { AppContextProvider } from '../../public/application/app_context'; import { Provider } from 'react-redux'; -import { loadIndicesSuccess } from '../../public/app/store/actions'; -import { breadcrumbService } from '../../public/app/services/breadcrumbs'; -import { uiMetricService } from '../../public/app/services/ui_metric'; -import { notificationService } from '../../public/app/services/notification'; -import { httpService } from '../../public/app/services/http'; -import { createUiStatsReporter } from '../../../../../../src/legacy/core_plugins/ui_metric/public'; -import { indexManagementStore } from '../../public/app/store'; +import { loadIndicesSuccess } from '../../public/application/store/actions'; +import { breadcrumbService } from '../../public/application/services/breadcrumbs'; +import { UiMetricService } from '../../public/application/services/ui_metric'; +import { notificationService } from '../../public/application/services/notification'; +import { httpService } from '../../public/application/services/http'; +import { setUiMetricService } from '../../public/application/services/api'; +import { indexManagementStore } from '../../public/application/store'; +import { setExtensionsService } from '../../public/application/store/selectors'; import { BASE_PATH, API_BASE_PATH } from '../../common/constants'; import { mountWithIntl } from '../../../../../test_utils/enzyme_helpers'; +import { ExtensionsService } from '../../public/services'; import sinon from 'sinon'; import { findTestSubject } from '@elastic/eui/lib/test'; /* eslint-disable @kbn/eslint/no-restricted-paths */ import { notificationServiceMock } from '../../../../../../src/core/public/notifications/notifications_service.mock'; -import { chromeServiceMock } from '../../../../../../src/core/public/chrome/chrome_service.mock'; jest.mock('ui/new_platform'); @@ -107,17 +109,29 @@ const namesText = rendered => { describe('index table', () => { beforeEach(() => { // Mock initialization of services + const services = { + extensionsService: new ExtensionsService(), + uiMetricService: new UiMetricService('index_management'), + }; + services.uiMetricService.setup({ reportUiStats() {} }); + setExtensionsService(services.extensionsService); + setUiMetricService(services.uiMetricService); + // @ts-ignore - httpService.init(mockHttpClient); - breadcrumbService.init(chromeServiceMock.createStartContract(), ''); - uiMetricService.init(createUiStatsReporter); - notificationService.init(notificationServiceMock.createStartContract()); + httpService.setup(mockHttpClient); + breadcrumbService.setup(() => undefined); + notificationService.setup(notificationServiceMock.createStartContract()); + + store = indexManagementStore(services); + + const appDependencies = { services, core: {}, plugins: {} }; - store = indexManagementStore(); component = ( - + + + ); @@ -141,6 +155,9 @@ describe('index table', () => { server.respondImmediately = true; }); afterEach(() => { + if (!server) { + return; + } server.restore(); }); @@ -294,6 +311,8 @@ describe('index table', () => { confirmButton.simulate('click'); snapshot(status(rendered, rowIndex)); }); + // Commenting the following 2 tests as it works in the browser (status changes to "closed" or "open") but the + // snapshot say the contrary. Need to be investigated. test('close index button works from context menu', done => { const modifiedIndices = indices.map(index => { return { diff --git a/x-pack/legacy/plugins/index_management/__jest__/lib/flatten_object.test.js b/x-pack/legacy/plugins/index_management/__jest__/lib/flatten_object.test.js index eb21459a3cbc7..0d6d5ee796627 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/lib/flatten_object.test.js +++ b/x-pack/legacy/plugins/index_management/__jest__/lib/flatten_object.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { flattenObject } from '../../public/app/lib/flatten_object'; +import { flattenObject } from '../../public/application/lib/flatten_object'; describe('flatten_object', () => { test('it flattens an object', () => { const obj = { diff --git a/x-pack/legacy/plugins/index_management/public/app/index.tsx b/x-pack/legacy/plugins/index_management/public/app/index.tsx deleted file mode 100644 index 027839df2e20e..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/app/index.tsx +++ /dev/null @@ -1,36 +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 React from 'react'; -import { Provider } from 'react-redux'; -import { render, unmountComponentAtNode } from 'react-dom'; - -import { CoreStart } from '../../../../../../src/core/public'; - -import { App } from './app'; -import { indexManagementStore } from './store'; - -export const mountReactApp = (elem: HTMLElement | null, { core }: { core: CoreStart }): void => { - if (elem) { - const { i18n } = core; - const { Context: I18nContext } = i18n; - - render( - - - - - , - elem - ); - } -}; - -export const unmountReactApp = (elem: HTMLElement | null) => { - if (elem) { - unmountComponentAtNode(elem); - } -}; diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.js b/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.js deleted file mode 100644 index 0bfd32581ef4a..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.js +++ /dev/null @@ -1,164 +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 React, { Component, Fragment } from 'react'; -import { Route } from 'react-router-dom'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiCallOut, - EuiFlexGroup, - EuiFlexItem, - EuiFlyout, - EuiFlyoutBody, - EuiFlyoutFooter, - EuiFlyoutHeader, - EuiSpacer, - EuiTabs, - EuiTab, - EuiTitle, -} from '@elastic/eui'; -import { renderBadges } from '../../../../lib/render_badges'; -import { INDEX_OPEN } from '../../../../../../common/constants'; -import { - TAB_SUMMARY, - TAB_SETTINGS, - TAB_MAPPING, - TAB_STATS, - TAB_EDIT_SETTINGS, -} from '../../../../constants'; -import { IndexActionsContextMenu } from '../index_actions_context_menu'; -import { ShowJson } from './show_json'; -import { Summary } from './summary'; -import { EditSettingsJson } from './edit_settings_json'; - -const tabToHumanizedMap = { - [TAB_SUMMARY]: ( - - ), - [TAB_SETTINGS]: ( - - ), - [TAB_MAPPING]: ( - - ), - [TAB_STATS]: ( - - ), - [TAB_EDIT_SETTINGS]: ( - - ), -}; - -const tabs = [TAB_SUMMARY, TAB_SETTINGS, TAB_MAPPING, TAB_STATS, TAB_EDIT_SETTINGS]; - -export class DetailPanel extends Component { - renderTabs() { - const { panelType, indexName, index, openDetailPanel } = this.props; - return tabs.map((tab, i) => { - const isSelected = tab === panelType; - return ( - openDetailPanel({ panelType: tab, indexName })} - isSelected={isSelected} - data-test-subj={`detailPanelTab${isSelected ? 'Selected' : ''}`} - disabled={tab === TAB_STATS && index.status !== INDEX_OPEN} - key={i} - > - {tabToHumanizedMap[tab]} - - ); - }); - } - render() { - const { panelType, indexName, index, closeDetailPanel } = this.props; - if (!panelType) { - return null; - } - let component = null; - switch (panelType) { - case TAB_EDIT_SETTINGS: - component = ; - break; - case TAB_MAPPING: - case TAB_SETTINGS: - case TAB_STATS: - component = ; - break; - default: - component = ; - } - const content = index ? ( - - {component} - - - - ( - - } - /> - )} - /> - - - - - ) : ( - - - - } - color="danger" - iconType="cross" - > - - - - ); - return ( - - - -

- {indexName} - {renderBadges(index)} -

-
- {index ? {this.renderTabs()} : null} -
- {content} -
- ); - } -} diff --git a/x-pack/legacy/plugins/index_management/public/app/services/ui_metric.ts b/x-pack/legacy/plugins/index_management/public/app/services/ui_metric.ts deleted file mode 100644 index 4ea98fff1d70a..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/app/services/ui_metric.ts +++ /dev/null @@ -1,25 +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 { UIM_APP_NAME } from '../../../common/constants'; -import { - createUiStatsReporter, - UiStatsMetricType, -} from '../../../../../../../src/legacy/core_plugins/ui_metric/public'; - -class UiMetricService { - track?: ReturnType; - - public init = (getReporter: typeof createUiStatsReporter): void => { - this.track = getReporter(UIM_APP_NAME); - }; - - public trackMetric = (type: 'loaded' | 'click' | 'count', eventName: string): void => { - if (!this.track) throw Error('UiMetricService not initialized.'); - return this.track(type as UiStatsMetricType, eventName); - }; -} - -export const uiMetricService = new UiMetricService(); diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/detail_panel.js b/x-pack/legacy/plugins/index_management/public/app/store/reducers/detail_panel.js deleted file mode 100644 index 9ba73a1c61b03..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/app/store/reducers/detail_panel.js +++ /dev/null @@ -1,89 +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 { handleActions } from 'redux-actions'; -import { - UIM_DETAIL_PANEL_SUMMARY_TAB, - UIM_DETAIL_PANEL_SETTINGS_TAB, - UIM_DETAIL_PANEL_MAPPING_TAB, - UIM_DETAIL_PANEL_STATS_TAB, - UIM_DETAIL_PANEL_EDIT_SETTINGS_TAB, -} from '../../../../common/constants'; -import { - TAB_SUMMARY, - TAB_SETTINGS, - TAB_MAPPING, - TAB_STATS, - TAB_EDIT_SETTINGS, -} from '../../constants'; -import { uiMetricService } from '../../services/ui_metric'; -import { openDetailPanel, closeDetailPanel } from '../actions/detail_panel'; -import { loadIndexDataSuccess } from '../actions/load_index_data'; -import { - updateIndexSettingsSuccess, - updateIndexSettingsError, -} from '../actions/update_index_settings'; -import { deleteIndicesSuccess } from '../actions/delete_indices'; - -const defaultState = {}; - -export const detailPanel = handleActions( - { - [deleteIndicesSuccess](state, action) { - const { indexNames } = action.payload; - const { indexName } = state; - if (indexNames.includes(indexName)) { - return {}; - } else { - return state; - } - }, - [openDetailPanel](state, action) { - const { panelType, indexName, title } = action.payload; - - const panelTypeToUiMetricMap = { - [TAB_SUMMARY]: UIM_DETAIL_PANEL_SUMMARY_TAB, - [TAB_SETTINGS]: UIM_DETAIL_PANEL_SETTINGS_TAB, - [TAB_MAPPING]: UIM_DETAIL_PANEL_MAPPING_TAB, - [TAB_STATS]: UIM_DETAIL_PANEL_STATS_TAB, - [TAB_EDIT_SETTINGS]: UIM_DETAIL_PANEL_EDIT_SETTINGS_TAB, - }; - - if (panelTypeToUiMetricMap[panelType]) { - uiMetricService.trackMetric('count', panelTypeToUiMetricMap[panelType]); - } - - return { - panelType: panelType || state.panelType || TAB_SUMMARY, - indexName, - title, - }; - }, - [closeDetailPanel]() { - return {}; - }, - [loadIndexDataSuccess](state, action) { - const { data } = action.payload; - const newState = { - ...state, - data, - }; - return newState; - }, - [updateIndexSettingsError](state, action) { - const { error } = action.payload; - const newState = { - ...state, - error, - }; - return newState; - }, - [updateIndexSettingsSuccess]() { - return {}; - }, - }, - defaultState -); diff --git a/x-pack/legacy/plugins/index_management/public/app/app.tsx b/x-pack/legacy/plugins/index_management/public/application/app.tsx similarity index 93% rename from x-pack/legacy/plugins/index_management/public/app/app.tsx rename to x-pack/legacy/plugins/index_management/public/application/app.tsx index 9ed824e184120..3b475f3baba04 100644 --- a/x-pack/legacy/plugins/index_management/public/app/app.tsx +++ b/x-pack/legacy/plugins/index_management/public/application/app.tsx @@ -11,9 +11,11 @@ import { IndexManagementHome } from './sections/home'; import { TemplateCreate } from './sections/template_create'; import { TemplateClone } from './sections/template_clone'; import { TemplateEdit } from './sections/template_edit'; -import { uiMetricService } from './services/ui_metric'; + +import { useServices } from './app_context'; export const App = () => { + const { uiMetricService } = useServices(); useEffect(() => uiMetricService.trackMetric('loaded', UIM_APP_LOAD), []); return ( diff --git a/x-pack/legacy/plugins/index_management/public/application/app_context.tsx b/x-pack/legacy/plugins/index_management/public/application/app_context.tsx new file mode 100644 index 0000000000000..12e0d362a2930 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/app_context.tsx @@ -0,0 +1,52 @@ +/* + * 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, { createContext, useContext } from 'react'; +import { CoreStart } from '../../../../../../src/core/public'; + +import { UsageCollectionSetup } from '../../../../../../src/plugins/usage_collection/public'; +import { IndexMgmtMetricsType } from '../types'; +import { UiMetricService, NotificationService, HttpService } from './services'; +import { ExtensionsService } from '../services'; + +const AppContext = createContext(undefined); + +export interface AppDependencies { + core: { + fatalErrors: CoreStart['fatalErrors']; + }; + plugins: { + usageCollection: UsageCollectionSetup; + }; + services: { + uiMetricService: UiMetricService; + extensionsService: ExtensionsService; + httpService: HttpService; + notificationService: NotificationService; + }; +} + +export const AppContextProvider = ({ + children, + value, +}: { + value: AppDependencies; + children: React.ReactNode; +}) => { + return {children}; +}; + +export const AppContextConsumer = AppContext.Consumer; + +export const useAppContext = () => { + const ctx = useContext(AppContext); + if (!ctx) { + throw new Error('"useAppContext" can only be called inside of AppContext.Provider!'); + } + return ctx; +}; + +export const useServices = () => useAppContext().services; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/_index.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/_index.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/_index.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/_index.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/_index.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/_index.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/_index.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/_index.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/code_block.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/code_block.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/code_block.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/code_block.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/configuration_form.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/configuration_form.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/dynamic_mapping_section/dynamic_mapping_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/dynamic_mapping_section/dynamic_mapping_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/dynamic_mapping_section/dynamic_mapping_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/dynamic_mapping_section/dynamic_mapping_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/dynamic_mapping_section/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/dynamic_mapping_section/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/dynamic_mapping_section/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/dynamic_mapping_section/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/meta_field_section/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/meta_field_section/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/meta_field_section/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/meta_field_section/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/meta_field_section/meta_field_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/meta_field_section/meta_field_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/meta_field_section/meta_field_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/meta_field_section/meta_field_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/routing_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/routing_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/routing_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/routing_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/source_field_section/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/source_field_section/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/source_field_section/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/source_field_section/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/source_field_section/source_field_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/source_field_section/source_field_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/source_field_section/source_field_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/source_field_section/source_field_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/_index.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/_index.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/_index.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/_index.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/document_fields.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/document_fields.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields_header.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/document_fields_header.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields_header.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/document_fields_header.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/editor_toggle_controls.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/editor_toggle_controls.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/editor_toggle_controls.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/editor_toggle_controls.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/boost_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/boost_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/boost_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/boost_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/coerce_number_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/coerce_number_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/coerce_number_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/coerce_number_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/coerce_shape_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/coerce_shape_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/coerce_shape_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/coerce_shape_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/copy_to_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/copy_to_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/copy_to_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/copy_to_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/doc_values_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/doc_values_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/doc_values_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/doc_values_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_absolute.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_absolute.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_absolute.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_absolute.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_percentage.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_percentage.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_percentage.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_percentage.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/format_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/format_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/format_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/format_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/ignore_malformed.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/ignore_malformed.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/ignore_malformed.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/ignore_malformed.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/locale_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/locale_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/locale_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/locale_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/name_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/name_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/name_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/name_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/norms_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/norms_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/norms_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/norms_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/null_value_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/null_value_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/null_value_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/null_value_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/orientation_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/orientation_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/orientation_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/orientation_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/path_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/path_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/path_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/path_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/similarity_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/similarity_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/similarity_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/similarity_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/split_queries_on_whitespace_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/split_queries_on_whitespace_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/split_queries_on_whitespace_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/split_queries_on_whitespace_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/store_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/store_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/store_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/store_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/term_vector_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/term_vector_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/term_vector_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/term_vector_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/type_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/type_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/type_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/type_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/_field_list_item.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_field_list_item.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/_field_list_item.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_field_list_item.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/_index.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_index.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/_index.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_index.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/alias_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/alias_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/alias_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/alias_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/dense_vector_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/dense_vector_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/dense_vector_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/dense_vector_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/scaled_float_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/scaled_float_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/scaled_float_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/scaled_float_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/token_count_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/token_count_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/token_count_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/token_count_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/delete_field_provider.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/delete_field_provider.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/delete_field_provider.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/delete_field_provider.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/_edit_field_form_row.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/_edit_field_form_row.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/_edit_field_form_row.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/_edit_field_form_row.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/_index.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/_index.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/_index.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/_index.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/advanced_parameters_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/advanced_parameters_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/advanced_parameters_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/advanced_parameters_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/basic_parameters_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/basic_parameters_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/basic_parameters_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/basic_parameters_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_container.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_container.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_container.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_container.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_form_row.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_form_row.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_form_row.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_form_row.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/update_field_provider.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/update_field_provider.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/update_field_provider.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/update_field_provider.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/alias_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/alias_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/alias_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/alias_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/binary_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/binary_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/binary_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/binary_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/boolean_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/boolean_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/boolean_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/boolean_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/completion_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/completion_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/completion_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/completion_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/dense_vector_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/dense_vector_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/dense_vector_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/dense_vector_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/flattened_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/flattened_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/flattened_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/flattened_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/geo_point_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/geo_point_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/geo_point_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/geo_point_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/geo_shape_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/geo_shape_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/geo_shape_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/geo_shape_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/ip_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/ip_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/ip_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/ip_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/keyword_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/keyword_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/keyword_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/keyword_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/search_as_you_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/search_as_you_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/search_as_you_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/search_as_you_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/shape_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/shape_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/shape_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/shape_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/text_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/text_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/text_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/text_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item_container.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item_container.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item_container.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item_container.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/modal_confirmation_delete_fields.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/modal_confirmation_delete_fields.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/modal_confirmation_delete_fields.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/modal_confirmation_delete_fields.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields_json_editor.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_json_editor.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields_json_editor.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_json_editor.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields_tree_editor.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_tree_editor.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields_tree_editor.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_tree_editor.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/search_result.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/search_result.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/fields_tree.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/fields_tree.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/fields_tree.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/fields_tree.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_from_json_button.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_from_json_button.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_from_json_button.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_from_json_button.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.test.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_mappings_provider.test.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.test.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_mappings_provider.test.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/multiple_mappings_warning.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/multiple_mappings_warning.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/multiple_mappings_warning.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/multiple_mappings_warning.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/templates_form.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/templates_form.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/templates_form_schema.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form_schema.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/templates_form_schema.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form_schema.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/tree.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/tree.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/tree.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/tree.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/tree_item.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/tree_item.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/tree_item.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/tree_item.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/data_types_definition.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/data_types_definition.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/data_types_definition.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/data_types_definition.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/default_values.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/default_values.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/default_values.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/default_values.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/field_options.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/field_options.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/field_options_i18n.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/field_options_i18n.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/field_options_i18n.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/field_options_i18n.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/mappings_editor.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/mappings_editor.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/mappings_editor.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/mappings_editor.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/index_settings_context.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/index_settings_context.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/error_reporter.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/error_reporter.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.test.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.test.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.test.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.test.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.test.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/search_fields.test.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.test.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/search_fields.test.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/search_fields.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/search_fields.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/serializers.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/serializers.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/serializers.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/serializers.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.test.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/utils.test.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.test.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/utils.test.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/validators.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/validators.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/validators.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/validators.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_state.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/mappings_state.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_state.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/mappings_state.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/reducer.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/reducer.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/reducer.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/reducer.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/shared_imports.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/shared_imports.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/shared_imports.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/shared_imports.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/types.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/types.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/no_match/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/no_match/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/no_match/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/no_match/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/no_match/no_match.tsx b/x-pack/legacy/plugins/index_management/public/application/components/no_match/no_match.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/no_match/no_match.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/no_match/no_match.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/page_error/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/page_error/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/page_error/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/page_error/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/page_error/page_error_forbidden.tsx b/x-pack/legacy/plugins/index_management/public/application/components/page_error/page_error_forbidden.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/page_error/page_error_forbidden.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/page_error/page_error_forbidden.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/section_error.tsx b/x-pack/legacy/plugins/index_management/public/application/components/section_error.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/section_error.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/section_error.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/section_loading.tsx b/x-pack/legacy/plugins/index_management/public/application/components/section_loading.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/section_loading.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/section_loading.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_delete_modal.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_delete_modal.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_delete_modal.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_delete_modal.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/template_form/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_aliases.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_aliases.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_aliases.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_aliases.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_logistics.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_logistics.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_mappings.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_mappings.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_mappings.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_mappings.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_review.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_review.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_review.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_review.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_settings.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_settings.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_settings.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_settings.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/use_json_step.ts b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/use_json_step.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/use_json_step.ts rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/use_json_step.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/template_form.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/template_form.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/template_form.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/template_form.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/template_form_schemas.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/template_form_schemas.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/template_steps.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/template_steps.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/template_steps.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/template_steps.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/types.ts b/x-pack/legacy/plugins/index_management/public/application/components/template_form/types.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/types.ts rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/types.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/constants/detail_panel_tabs.ts b/x-pack/legacy/plugins/index_management/public/application/constants/detail_panel_tabs.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/constants/detail_panel_tabs.ts rename to x-pack/legacy/plugins/index_management/public/application/constants/detail_panel_tabs.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/constants/index.ts b/x-pack/legacy/plugins/index_management/public/application/constants/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/constants/index.ts rename to x-pack/legacy/plugins/index_management/public/application/constants/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/constants/refresh_intervals.ts b/x-pack/legacy/plugins/index_management/public/application/constants/refresh_intervals.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/constants/refresh_intervals.ts rename to x-pack/legacy/plugins/index_management/public/application/constants/refresh_intervals.ts diff --git a/x-pack/legacy/plugins/index_management/public/application/index.tsx b/x-pack/legacy/plugins/index_management/public/application/index.tsx new file mode 100644 index 0000000000000..b9859903f1434 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/index.tsx @@ -0,0 +1,45 @@ +/* + * 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 { Provider } from 'react-redux'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import { CoreStart } from '../../../../../../src/core/public'; + +import { AppContextProvider, AppDependencies } from './app_context'; +import { App } from './app'; +import { indexManagementStore } from './store'; + +export const renderApp = ( + elem: HTMLElement | null, + { core, dependencies }: { core: CoreStart; dependencies: AppDependencies } +) => { + if (!elem) { + return () => undefined; + } + + const { i18n } = core; + const { Context: I18nContext } = i18n; + const { services } = dependencies; + + render( + + + + + + + , + elem + ); + + return () => { + unmountComponentAtNode(elem); + }; +}; + +export { AppDependencies }; diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/ace.js b/x-pack/legacy/plugins/index_management/public/application/lib/ace.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/ace.js rename to x-pack/legacy/plugins/index_management/public/application/lib/ace.js diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/edit_settings.js b/x-pack/legacy/plugins/index_management/public/application/lib/edit_settings.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/edit_settings.js rename to x-pack/legacy/plugins/index_management/public/application/lib/edit_settings.js diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/flatten_object.js b/x-pack/legacy/plugins/index_management/public/application/lib/flatten_object.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/flatten_object.js rename to x-pack/legacy/plugins/index_management/public/application/lib/flatten_object.js diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/flatten_panel_tree.js b/x-pack/legacy/plugins/index_management/public/application/lib/flatten_panel_tree.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/flatten_panel_tree.js rename to x-pack/legacy/plugins/index_management/public/application/lib/flatten_panel_tree.js diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/index_status_labels.js b/x-pack/legacy/plugins/index_management/public/application/lib/index_status_labels.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/index_status_labels.js rename to x-pack/legacy/plugins/index_management/public/application/lib/index_status_labels.js diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/manage_angular_lifecycle.ts b/x-pack/legacy/plugins/index_management/public/application/lib/manage_angular_lifecycle.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/manage_angular_lifecycle.ts rename to x-pack/legacy/plugins/index_management/public/application/lib/manage_angular_lifecycle.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/render_badges.js b/x-pack/legacy/plugins/index_management/public/application/lib/render_badges.js similarity index 83% rename from x-pack/legacy/plugins/index_management/public/app/lib/render_badges.js rename to x-pack/legacy/plugins/index_management/public/application/lib/render_badges.js index 175b88bd31f6c..fbca65fe5dba6 100644 --- a/x-pack/legacy/plugins/index_management/public/app/lib/render_badges.js +++ b/x-pack/legacy/plugins/index_management/public/application/lib/render_badges.js @@ -7,10 +7,10 @@ import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiBadge, EuiSearchBar } from '@elastic/eui'; -import { getBadgeExtensions } from '../../index_management_extensions'; -export const renderBadges = (index, filterChanged) => { + +export const renderBadges = (index, filterChanged, extensionsService) => { const badgeLabels = []; - getBadgeExtensions().forEach(({ matchIndex, label, color, filterExpression }) => { + extensionsService.badges.forEach(({ matchIndex, label, color, filterExpression }) => { if (matchIndex(index)) { const clickHandler = () => { filterChanged && diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/home.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/home.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/home.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/home.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.container.js diff --git a/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.js new file mode 100644 index 0000000000000..e0128b1d51d02 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.js @@ -0,0 +1,167 @@ +/* + * 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, { Fragment } from 'react'; +import { Route } from 'react-router-dom'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiCallOut, + EuiFlexGroup, + EuiFlexItem, + EuiFlyout, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiSpacer, + EuiTabs, + EuiTab, + EuiTitle, +} from '@elastic/eui'; +import { renderBadges } from '../../../../lib/render_badges'; +import { INDEX_OPEN } from '../../../../../../common/constants'; +import { + TAB_SUMMARY, + TAB_SETTINGS, + TAB_MAPPING, + TAB_STATS, + TAB_EDIT_SETTINGS, +} from '../../../../constants'; +import { IndexActionsContextMenu } from '../index_actions_context_menu'; +import { ShowJson } from './show_json'; +import { Summary } from './summary'; +import { EditSettingsJson } from './edit_settings_json'; +import { useServices } from '../../../../app_context'; + +const tabToHumanizedMap = { + [TAB_SUMMARY]: ( + + ), + [TAB_SETTINGS]: ( + + ), + [TAB_MAPPING]: ( + + ), + [TAB_STATS]: ( + + ), + [TAB_EDIT_SETTINGS]: ( + + ), +}; + +const tabs = [TAB_SUMMARY, TAB_SETTINGS, TAB_MAPPING, TAB_STATS, TAB_EDIT_SETTINGS]; + +export const DetailPanel = ({ panelType, indexName, index, openDetailPanel, closeDetailPanel }) => { + const { extensionsService } = useServices(); + + const renderTabs = () => { + return tabs.map((tab, i) => { + const isSelected = tab === panelType; + return ( + openDetailPanel({ panelType: tab, indexName })} + isSelected={isSelected} + data-test-subj={`detailPanelTab${isSelected ? 'Selected' : ''}`} + disabled={tab === TAB_STATS && index.status !== INDEX_OPEN} + key={i} + > + {tabToHumanizedMap[tab]} + + ); + }); + }; + + if (!panelType) { + return null; + } + + let component = null; + switch (panelType) { + case TAB_EDIT_SETTINGS: + component = ; + break; + case TAB_MAPPING: + case TAB_SETTINGS: + case TAB_STATS: + component = ; + break; + default: + component = ; + } + + const content = index ? ( + + {component} + + + + ( + + } + /> + )} + /> + + + + + ) : ( + + + + } + color="danger" + iconType="cross" + > + + + + ); + + return ( + + + +

+ {indexName} + {renderBadges(index, undefined, extensionsService)} +

+
+ {index ? {renderTabs()} : null} +
+ {content} +
+ ); +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.container.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/show_json.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/show_json.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/show_json.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/show_json.container.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/show_json.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/show_json.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/show_json.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/show_json.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/summary.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/summary.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.container.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/summary.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.js similarity index 72% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/summary.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.js index a49dc6079e3c5..e49b3c353931e 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/summary.js +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.js @@ -6,7 +6,6 @@ import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; -import { healthToColor } from '../../../../../services'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlexGroup, @@ -19,7 +18,9 @@ import { EuiSpacer, EuiTitle, } from '@elastic/eui'; -import { getSummaryExtensions } from '../../../../../../index_management_extensions'; +import { healthToColor } from '../../../../../services'; +import { AppContextConsumer } from '../../../../../app_context'; + const getHeaders = () => { return { health: i18n.translate('xpack.idxMgmt.summary.headers.healthHeader', { @@ -53,9 +54,9 @@ const getHeaders = () => { }; export class Summary extends React.PureComponent { - getAdditionalContent() { + getAdditionalContent(extensionsService) { const { index } = this.props; - const extensions = getSummaryExtensions(); + const extensions = extensionsService.summaries; return extensions.map((summaryExtension, i) => { return ( @@ -65,6 +66,7 @@ export class Summary extends React.PureComponent { ); }); } + buildRows() { const { index } = this.props; const headers = getHeaders(); @@ -99,26 +101,36 @@ export class Summary extends React.PureComponent { } render() { - const { left, right } = this.buildRows(); - const additionalContent = this.getAdditionalContent(); return ( - - -

- -

-
- - - - {left} - - - {right} - - - {additionalContent} -
+ + {({ services }) => { + const { left, right } = this.buildRows(); + const additionalContent = this.getAdditionalContent(services.extensionsService); + + return ( + + +

+ +

+
+ + + + {left} + + + {right} + + + {additionalContent} +
+ ); + }} +
); } } diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js similarity index 91% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js index 5ed651e3125cf..8f794ce1ed612 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js @@ -23,21 +23,9 @@ import { EuiCheckbox, } from '@elastic/eui'; -// We will be able to remove these after the NP migration is complete. -import { fatalError } from 'ui/notify'; -import { createUiStatsReporter } from '../../../../../../../../../../src/legacy/core_plugins/ui_metric/public'; -import { httpService } from '../../../../services/http'; -import { notificationService } from '../../../../services/notification'; - import { flattenPanelTree } from '../../../../lib/flatten_panel_tree'; import { INDEX_OPEN } from '../../../../../../common/constants'; -import { getActionExtensions } from '../../../../../index_management_extensions'; - -// We will be able to remove this after the NP migration is complete and we can just inject the -// NP fatalErrors service.. -const getNewPlatformCompatibleFatalErrorService = () => ({ - add: fatalError.bind(fatalError), -}); +import { AppContextConsumer } from '../../../../app_context'; export class IndexActionsContextMenu extends Component { constructor(props) { @@ -58,7 +46,11 @@ export class IndexActionsContextMenu extends Component { confirmAction = isActionConfirmed => { this.setState({ isActionConfirmed }); }; - panels() { + panels({ + core: { fatalErrors }, + services: { extensionsService, httpService, notificationService }, + plugins: { usageCollection }, + }) { const { closeIndices, openIndices, @@ -222,7 +214,7 @@ export class IndexActionsContextMenu extends Component { this.setState({ renderConfirmModal: this.renderConfirmDeleteModal }); }, }); - getActionExtensions().forEach(actionExtension => { + extensionsService.actions.forEach(actionExtension => { const actionExtensionDefinition = actionExtension({ indices, reloadIndices, @@ -231,12 +223,11 @@ export class IndexActionsContextMenu extends Component { // dependencies, but they're not available unless the app's "setup" lifecycle stage occurs. // Within the old platform, "setup" only occurs once the user actually visits the app. // Once ILM and IM have been moved out of legacy this hack won't be necessary. - createUiStatsReporter, + usageCollection, toasts: notificationService.toasts, - fatalErrors: getNewPlatformCompatibleFatalErrorService(), + fatalErrors, httpClient: httpService.httpClient, }); - if (actionExtensionDefinition) { const { buttonLabel, @@ -721,52 +712,61 @@ export class IndexActionsContextMenu extends Component { }; render() { - const { indexNames } = this.props; - const selectedIndexCount = indexNames.length; - const { - iconSide = 'right', - anchorPosition = 'rightUp', - label = i18n.translate('xpack.idxMgmt.indexActionsMenu.manageButtonLabel', { - defaultMessage: 'Manage {selectedIndexCount, plural, one {index} other {indices}}', - values: { selectedIndexCount }, - }), - iconType = 'arrowDown', - } = this.props; - const panels = this.panels(); - const button = ( - - {label} - - ); - return ( -
- {this.state.renderConfirmModal - ? this.state.renderConfirmModal(this.closeConfirmModal) - : null} - - - -
+ + {appDependencies => { + const { indexNames } = this.props; + const selectedIndexCount = indexNames.length; + const { + iconSide = 'right', + anchorPosition = 'rightUp', + label = i18n.translate('xpack.idxMgmt.indexActionsMenu.manageButtonLabel', { + defaultMessage: 'Manage {selectedIndexCount, plural, one {index} other {indices}}', + values: { selectedIndexCount }, + }), + iconType = 'arrowDown', + } = this.props; + + const panels = this.panels(appDependencies); + + const button = ( + + {label} + + ); + + return ( +
+ {this.state.renderConfirmModal + ? this.state.renderConfirmModal(this.closeConfirmModal) + : null} + + + +
+ ); + }} +
); } } diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_list.d.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_list.d.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_list.d.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_list.d.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_list.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_list.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_list.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_list.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index_table.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index_table.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.container.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index_table.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js similarity index 62% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index_table.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js index e043323c5b290..b659e2ec86a9b 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index_table.js +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js @@ -38,12 +38,7 @@ import { import { UIM_SHOW_DETAILS_CLICK } from '../../../../../../common/constants'; import { REFRESH_RATE_INDEX_LIST } from '../../../../constants'; import { healthToColor } from '../../../../services'; -import { uiMetricService } from '../../../../services/ui_metric'; -import { - getBannerExtensions, - getFilterExtensions, - getToggleExtensions, -} from '../../../../../index_management_extensions'; +import { AppContextConsumer } from '../../../../app_context'; import { renderBadges } from '../../../../lib/render_badges'; import { NoMatch, PageErrorForbidden } from '../../../../components'; import { IndexActionsContextMenu } from '../index_actions_context_menu'; @@ -153,9 +148,9 @@ export class IndexTable extends Component { this.setState({ filterError: null }); } }; - getFilters = () => { + getFilters = extensionsService => { const { allIndices } = this.props; - return getFilterExtensions().reduce((accum, filterExtension) => { + return extensionsService.filters.reduce((accum, filterExtension) => { const filtersToAdd = filterExtension(allIndices); return [...accum, ...filtersToAdd]; }, []); @@ -218,7 +213,7 @@ export class IndexTable extends Component { }); } - buildRowCell(fieldName, value, index) { + buildRowCell(fieldName, value, index, appServices) { const { openDetailPanel, filterChanged } = this.props; if (fieldName === 'health') { return {value}; @@ -228,20 +223,20 @@ export class IndexTable extends Component { { - uiMetricService.trackMetric('click', UIM_SHOW_DETAILS_CLICK); + appServices.uiMetricService.trackMetric('click', UIM_SHOW_DETAILS_CLICK); openDetailPanel(value); }} > {value} - {renderBadges(index, filterChanged)} + {renderBadges(index, filterChanged, appServices.extensionsService)}
); } return value; } - buildRowCells(index) { + buildRowCells(index, appServices) { return Object.keys(HEADERS).map(fieldName => { const { name } = index; const value = index[fieldName]; @@ -255,7 +250,9 @@ export class IndexTable extends Component { data-test-subj={`indexTableCell-${fieldName}`} >
- {this.buildRowCell(fieldName, value, index)} + + {this.buildRowCell(fieldName, value, index, appServices)} +
); @@ -268,7 +265,7 @@ export class IndexTable extends Component { className={'indTable__cell--' + fieldName} header={fieldName} > - {this.buildRowCell(fieldName, value, index)} + {this.buildRowCell(fieldName, value, index, appServices)} ); }); @@ -310,9 +307,9 @@ export class IndexTable extends Component { ); } - renderBanners() { + renderBanners(extensionsService) { const { allIndices = [], filterChanged } = this.props; - return getBannerExtensions().map((bannerExtension, i) => { + return extensionsService.banners.map((bannerExtension, i) => { const bannerData = bannerExtension(allIndices); if (!bannerData) { return null; @@ -335,7 +332,8 @@ export class IndexTable extends Component { ); }); } - buildRows() { + + buildRows(appServices) { const { indices = [], detailPanelIndexName } = this.props; return indices.map(index => { const { name } = index; @@ -360,7 +358,7 @@ export class IndexTable extends Component { })} /> - {this.buildRowCells(index)} + {this.buildRowCells(index, appServices)} ); }); @@ -383,6 +381,7 @@ export class IndexTable extends Component { onItemSelectionChanged = selectedIndices => { this.setState({ selectedIndices }); }; + renderToggleControl({ name, label }) { const { toggleNameToVisibleMap, toggleChanged } = this.props; return ( @@ -397,6 +396,7 @@ export class IndexTable extends Component { ); } + render() { const { filter, @@ -434,145 +434,157 @@ export class IndexTable extends Component { } return ( - - - - - - - - - - - {(indicesLoading && allIndices.length === 0) || indicesError ? null : ( - - {getToggleExtensions().map(toggle => { - return this.renderToggleControl(toggle); - })} - - showSystemIndicesChanged(event.target.checked)} - label={ + + {({ services }) => { + const { extensionsService } = services; + + return ( + + + + + - } - /> + + + + + {(indicesLoading && allIndices.length === 0) || indicesError ? null : ( + + {extensionsService.toggles.map(toggle => { + return this.renderToggleControl(toggle); + })} + + showSystemIndicesChanged(event.target.checked)} + label={ + + } + /> + + + )} - )} - - - - {this.renderBanners()} - {indicesError && this.renderError()} - - {atLeastOneItemSelected ? ( - - ( - { - this.setState({ selectedIndicesMap: {} }); - }} - /> + + {this.renderBanners(extensionsService)} + {indicesError && this.renderError()} + + {atLeastOneItemSelected ? ( + + ( + { + this.setState({ selectedIndicesMap: {} }); + }} + /> + )} + /> + + ) : null} + {(indicesLoading && allIndices.length === 0) || indicesError ? null : ( + + + 0 + ? this.getFilters(extensionsService) + : null + } + defaultQuery={filter} + query={filter} + box={{ + incremental: true, + placeholder: i18n.translate( + 'xpack.idxMgmt.indexTable.systemIndicesSearchInputPlaceholder', + { + defaultMessage: 'Search', + } + ), + }} + aria-label={i18n.translate( + 'xpack.idxMgmt.indexTable.systemIndicesSearchIndicesAriaLabel', + { + defaultMessage: 'Search indices', + } + )} + data-test-subj="indexTableFilterInput" + onChange={this.onFilterChanged} + /> + + + { + loadIndices(); + }} + iconType="refresh" + data-test-subj="reloadIndicesButton" + > + + + + )} - /> - - ) : null} - {(indicesLoading && allIndices.length === 0) || indicesError ? null : ( - - - 0 ? this.getFilters() : null} - defaultQuery={filter} - query={filter} - box={{ - incremental: true, - placeholder: i18n.translate( - 'xpack.idxMgmt.indexTable.systemIndicesSearchInputPlaceholder', - { - defaultMessage: 'Search', - } - ), - }} - aria-label={i18n.translate( - 'xpack.idxMgmt.indexTable.systemIndicesSearchIndicesAriaLabel', - { - defaultMessage: 'Search indices', - } - )} - data-test-subj="indexTableFilterInput" - onChange={this.onFilterChanged} - /> - - - { - loadIndices(); - }} - iconType="refresh" - data-test-subj="reloadIndicesButton" - > - - - + + {this.renderFilterError()} + + {indices.length > 0 ? ( +
+ + + + + + + + + + + {this.buildHeader()} + + {this.buildRows(services)} + +
+ ) : ( + emptyState + )} + + {indices.length > 0 ? this.renderPager() : null}
- )} - - {this.renderFilterError()} - - {indices.length > 0 ? ( -
- - - - - - - - - - - {this.buildHeader()} - - {this.buildRows()} - -
- ) : ( - emptyState - )} - - {indices.length > 0 ? this.renderPager() : null} - + ); + }} + ); } } diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_aliases.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_aliases.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_aliases.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_aliases.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_mappings.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_mappings.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_mappings.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_mappings.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_settings.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_settings.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_settings.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_settings.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_summary.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_summary.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/template_details.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/template_details.tsx similarity index 99% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/template_details.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/template_details.tsx index eaa0a331afcef..ced8bd97e744b 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/template_details.tsx +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/template_details.tsx @@ -34,8 +34,8 @@ import { Template } from '../../../../../../common/types'; import { TemplateDeleteModal, SectionLoading, SectionError, Error } from '../../../../components'; import { loadIndexTemplate } from '../../../../services/api'; import { decodePath } from '../../../../services/routing'; -import { uiMetricService } from '../../../../services/ui_metric'; import { SendRequestResponse } from '../../../../../shared_imports'; +import { useServices } from '../../../../app_context'; import { TabSummary, TabMappings, TabSettings, TabAliases } from './tabs'; interface Props { @@ -101,6 +101,7 @@ export const TemplateDetails: React.FunctionComponent = ({ cloneTemplate, reload, }) => { + const { uiMetricService } = useServices(); const decodedTemplateName = decodePath(templateName); const { error, data: templateDetails, isLoading } = loadIndexTemplate(decodedTemplateName); // TS complains if we use destructuring here. Fixed in 3.6.0 (https://github.com/microsoft/TypeScript/pull/31711). diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_list.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_list.tsx similarity index 98% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_list.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_list.tsx index 550fa941e1984..71c32e2e0177f 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_list.tsx +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_list.tsx @@ -20,7 +20,7 @@ import { SectionError, SectionLoading, Error } from '../../../components'; import { TemplateTable } from './template_table'; import { loadIndexTemplates } from '../../../services/api'; import { Template } from '../../../../../common/types'; -import { uiMetricService } from '../../../services/ui_metric'; +import { useServices } from '../../../app_context'; import { getTemplateEditLink, getTemplateListLink, @@ -39,6 +39,7 @@ export const TemplateList: React.FunctionComponent { + const { uiMetricService } = useServices(); const { error, isLoading, data: templates, sendRequest: reload } = loadIndexTemplates(); let content; diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_table/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_table/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_table/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_table/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_table/template_table.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx similarity index 98% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_table/template_table.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx index 6070b25fb1ca2..72321ccc14888 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_table/template_table.tsx +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx @@ -11,7 +11,7 @@ import { EuiInMemoryTable, EuiIcon, EuiButton, EuiLink, EuiBasicTableColumn } fr import { TemplateListItem, Template } from '../../../../../../common/types'; import { BASE_PATH, UIM_TEMPLATE_SHOW_DETAILS_CLICK } from '../../../../../../common/constants'; import { TemplateDeleteModal } from '../../../../components'; -import { uiMetricService } from '../../../../services/ui_metric'; +import { useServices } from '../../../../app_context'; import { getTemplateDetailsLink } from '../../../../services/routing'; import { SendRequestResponse } from '../../../../../shared_imports'; @@ -28,6 +28,7 @@ export const TemplateTable: React.FunctionComponent = ({ editTemplate, cloneTemplate, }) => { + const { uiMetricService } = useServices(); const [selection, setSelection] = useState([]); const [templatesToDelete, setTemplatesToDelete] = useState>([]); diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_clone/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/template_clone/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_clone/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/template_clone/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_clone/template_clone.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/template_clone/template_clone.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_clone/template_clone.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/template_clone/template_clone.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_create/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/template_create/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_create/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/template_create/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_create/template_create.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/template_create/template_create.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_create/template_create.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/template_create/template_create.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_edit/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/template_edit/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_edit/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/template_edit/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_edit/template_edit.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/template_edit/template_edit.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_edit/template_edit.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/template_edit/template_edit.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/services/api.ts b/x-pack/legacy/plugins/index_management/public/application/services/api.ts similarity index 94% rename from x-pack/legacy/plugins/index_management/public/app/services/api.ts rename to x-pack/legacy/plugins/index_management/public/application/services/api.ts index 8030a7f29d4ee..642fd441b353a 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/api.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/api.ts @@ -34,10 +34,19 @@ import { import { TAB_SETTINGS, TAB_MAPPING, TAB_STATS } from '../constants'; -import { uiMetricService } from './ui_metric'; import { useRequest, sendRequest } from './use_request'; import { httpService } from './http'; +import { UiMetricService } from './ui_metric'; import { Template } from '../../../common/types'; +import { IndexMgmtMetricsType } from '../../types'; + +// Temporary hack to provide the uiMetricService instance to this file. +// TODO: Refactor and export an ApiService instance through the app dependencies context +let uiMetricService: UiMetricService; +export const setUiMetricService = (_uiMetricService: UiMetricService) => { + uiMetricService = _uiMetricService; +}; +// End hack export async function loadIndices() { const response = await httpService.httpClient.get(`${API_BASE_PATH}/indices`); diff --git a/x-pack/legacy/plugins/index_management/public/app/services/breadcrumbs.ts b/x-pack/legacy/plugins/index_management/public/application/services/breadcrumbs.ts similarity index 81% rename from x-pack/legacy/plugins/index_management/public/app/services/breadcrumbs.ts rename to x-pack/legacy/plugins/index_management/public/application/services/breadcrumbs.ts index d35f064a3bcc4..299491756560e 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/breadcrumbs.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/breadcrumbs.ts @@ -5,26 +5,25 @@ */ import { i18n } from '@kbn/i18n'; import { BASE_PATH } from '../../../common/constants'; -import { ChromeStart } from '../../../../../../../src/core/public'; +import { ManagementAppMountParams } from '../../../../../../../src/plugins/management/public'; + +type SetBreadcrumbs = ManagementAppMountParams['setBreadcrumbs']; class BreadcrumbService { - private chrome: ChromeStart | undefined; private breadcrumbs: { [key: string]: Array<{ text: string; href?: string; }>; } = { - management: [], home: [], }; + private setBreadcrumbsHandler?: SetBreadcrumbs; - public init(chrome: ChromeStart, managementBreadcrumb: any): void { - this.chrome = chrome; - this.breadcrumbs.management = [managementBreadcrumb]; + public setup(setBreadcrumbsHandler: SetBreadcrumbs): void { + this.setBreadcrumbsHandler = setBreadcrumbsHandler; this.breadcrumbs.home = [ - ...this.breadcrumbs.management, { text: i18n.translate('xpack.idxMgmt.breadcrumb.homeLabel', { defaultMessage: 'Index Management', @@ -72,6 +71,10 @@ class BreadcrumbService { } public setBreadcrumbs(type: string): void { + if (!this.setBreadcrumbsHandler) { + throw new Error(`BreadcrumbService#setup() must be called first!`); + } + const newBreadcrumbs = this.breadcrumbs[type] ? [...this.breadcrumbs[type]] : [...this.breadcrumbs.home]; @@ -88,9 +91,7 @@ class BreadcrumbService { href: undefined, }); - if (this.chrome) { - this.chrome.setBreadcrumbs(newBreadcrumbs); - } + this.setBreadcrumbsHandler(newBreadcrumbs); } } diff --git a/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts b/x-pack/legacy/plugins/index_management/public/application/services/documentation.ts similarity index 99% rename from x-pack/legacy/plugins/index_management/public/app/services/documentation.ts rename to x-pack/legacy/plugins/index_management/public/application/services/documentation.ts index 9bf0d983df161..e0f261e586b1e 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/documentation.ts @@ -12,7 +12,7 @@ class DocumentationService { private esDocsBase: string = ''; private kibanaDocsBase: string = ''; - public init(docLinks: DocLinksStart): void { + public setup(docLinks: DocLinksStart): void { const { DOC_LINK_VERSION, ELASTIC_WEBSITE_URL } = docLinks; const docsBase = `${ELASTIC_WEBSITE_URL}guide/en`; diff --git a/x-pack/legacy/plugins/index_management/public/app/services/health_to_color.ts b/x-pack/legacy/plugins/index_management/public/application/services/health_to_color.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/services/health_to_color.ts rename to x-pack/legacy/plugins/index_management/public/application/services/health_to_color.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/services/http.ts b/x-pack/legacy/plugins/index_management/public/application/services/http.ts similarity index 86% rename from x-pack/legacy/plugins/index_management/public/app/services/http.ts rename to x-pack/legacy/plugins/index_management/public/application/services/http.ts index 34f5abe5983cc..a6973c263f00f 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/http.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/http.ts @@ -6,10 +6,10 @@ import { HttpSetup } from '../../../../../../../src/core/public'; -class HttpService { +export class HttpService { private client: any; - public init(httpClient: HttpSetup): void { + public setup(httpClient: HttpSetup): void { this.client = httpClient; } diff --git a/x-pack/legacy/plugins/index_management/public/app/services/index.ts b/x-pack/legacy/plugins/index_management/public/application/services/index.ts similarity index 82% rename from x-pack/legacy/plugins/index_management/public/app/services/index.ts rename to x-pack/legacy/plugins/index_management/public/application/services/index.ts index bb5c854e5d96c..78ff8cb5c314a 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/index.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/index.ts @@ -25,3 +25,7 @@ export { } from './api'; export { healthToColor } from './health_to_color'; export { sortTable } from './sort_table'; + +export { UiMetricService } from './ui_metric'; +export { HttpService } from './http'; +export { NotificationService } from './notification'; diff --git a/x-pack/legacy/plugins/index_management/public/app/services/navigation.ts b/x-pack/legacy/plugins/index_management/public/application/services/navigation.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/services/navigation.ts rename to x-pack/legacy/plugins/index_management/public/application/services/navigation.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/services/notification.ts b/x-pack/legacy/plugins/index_management/public/application/services/notification.ts similarity index 91% rename from x-pack/legacy/plugins/index_management/public/app/services/notification.ts rename to x-pack/legacy/plugins/index_management/public/application/services/notification.ts index 85558a7023491..0971ca77c004b 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/notification.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/notification.ts @@ -6,10 +6,10 @@ import { NotificationsStart } from '../../../../../../../src/core/public'; -class NotificationService { +export class NotificationService { private _toasts: any; - public init(notifications: NotificationsStart): void { + public setup(notifications: NotificationsStart): void { this._toasts = notifications.toasts; } diff --git a/x-pack/legacy/plugins/index_management/public/app/services/routing.ts b/x-pack/legacy/plugins/index_management/public/application/services/routing.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/services/routing.ts rename to x-pack/legacy/plugins/index_management/public/application/services/routing.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/services/sort_table.ts b/x-pack/legacy/plugins/index_management/public/application/services/sort_table.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/services/sort_table.ts rename to x-pack/legacy/plugins/index_management/public/application/services/sort_table.ts diff --git a/x-pack/legacy/plugins/index_management/public/application/services/ui_metric.ts b/x-pack/legacy/plugins/index_management/public/application/services/ui_metric.ts new file mode 100644 index 0000000000000..7c87ec9509085 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/services/ui_metric.ts @@ -0,0 +1,49 @@ +/* + * 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 { UiStatsMetricType } from '@kbn/analytics'; +import { UsageCollectionSetup } from '../../../../../../../src/plugins/usage_collection/public'; +import { IndexMgmtMetricsType } from '../../types'; + +let uiMetricService: UiMetricService; + +export class UiMetricService { + private appName: string; + private usageCollection: UsageCollectionSetup | undefined; + + constructor(appName: string) { + this.appName = appName; + } + + public setup(usageCollection: UsageCollectionSetup) { + this.usageCollection = usageCollection; + } + + private track(type: T, name: string) { + if (!this.usageCollection) { + throw Error('UiMetricService not initialized.'); + } + this.usageCollection.reportUiStats(this.appName, type as UiStatsMetricType, name); + } + + public trackMetric(type: T, eventName: string) { + return this.track(type, eventName); + } +} + +/** + * To minimize the refactor to migrate to NP where all deps should be explicitely declared + * we will export here the instance created in our plugin.ts setup() so other parts of the code can access it. + * + * TODO: Refactor the api.ts (convert it to a class with setup()) and detail_panel.ts (reducer) to explicitely declare their dependency on the UiMetricService + * @param instance UiMetricService instance from our plugin.ts setup() + */ +export const setUiMetricServiceInstance = (instance: UiMetricService) => { + uiMetricService = instance; +}; + +export const getUiMetricServiceInstance = () => { + return uiMetricService; +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/services/use_request.ts b/x-pack/legacy/plugins/index_management/public/application/services/use_request.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/services/use_request.ts rename to x-pack/legacy/plugins/index_management/public/application/services/use_request.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/clear_cache_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/clear_cache_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/clear_cache_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/clear_cache_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/clear_row_status.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/clear_row_status.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/clear_row_status.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/clear_row_status.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/close_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/close_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/close_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/close_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/delete_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/delete_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/delete_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/delete_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/detail_panel.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/detail_panel.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/detail_panel.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/detail_panel.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/edit_index_settings.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/edit_index_settings.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/edit_index_settings.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/edit_index_settings.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/extension_action.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/extension_action.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/extension_action.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/extension_action.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/flush_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/flush_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/flush_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/flush_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/forcemerge_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/forcemerge_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/forcemerge_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/forcemerge_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/freeze_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/freeze_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/freeze_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/freeze_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/index.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/index.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/load_index_data.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/load_index_data.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/load_index_data.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/load_index_data.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/load_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/load_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/load_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/load_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/open_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/open_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/open_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/open_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/refresh_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/refresh_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/refresh_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/refresh_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/reload_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/reload_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/reload_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/reload_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/table_state.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/table_state.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/table_state.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/table_state.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/unfreeze_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/unfreeze_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/unfreeze_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/unfreeze_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/update_index_settings.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/update_index_settings.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/update_index_settings.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/update_index_settings.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/index.ts b/x-pack/legacy/plugins/index_management/public/application/store/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/index.ts rename to x-pack/legacy/plugins/index_management/public/application/store/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/application/store/reducers/detail_panel.js b/x-pack/legacy/plugins/index_management/public/application/store/reducers/detail_panel.js new file mode 100644 index 0000000000000..c38971a633954 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/store/reducers/detail_panel.js @@ -0,0 +1,89 @@ +/* + * 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 { handleActions } from 'redux-actions'; +import { + UIM_DETAIL_PANEL_SUMMARY_TAB, + UIM_DETAIL_PANEL_SETTINGS_TAB, + UIM_DETAIL_PANEL_MAPPING_TAB, + UIM_DETAIL_PANEL_STATS_TAB, + UIM_DETAIL_PANEL_EDIT_SETTINGS_TAB, +} from '../../../../common/constants'; +import { + TAB_SUMMARY, + TAB_SETTINGS, + TAB_MAPPING, + TAB_STATS, + TAB_EDIT_SETTINGS, +} from '../../constants'; +import { openDetailPanel, closeDetailPanel } from '../actions/detail_panel'; +import { loadIndexDataSuccess } from '../actions/load_index_data'; +import { + updateIndexSettingsSuccess, + updateIndexSettingsError, +} from '../actions/update_index_settings'; +import { deleteIndicesSuccess } from '../actions/delete_indices'; + +const defaultState = {}; + +export const getDetailPanelReducer = uiMetricService => + handleActions( + { + [deleteIndicesSuccess](state, action) { + const { indexNames } = action.payload; + const { indexName } = state; + if (indexNames.includes(indexName)) { + return {}; + } else { + return state; + } + }, + [openDetailPanel](state, action) { + const { panelType, indexName, title } = action.payload; + + const panelTypeToUiMetricMap = { + [TAB_SUMMARY]: UIM_DETAIL_PANEL_SUMMARY_TAB, + [TAB_SETTINGS]: UIM_DETAIL_PANEL_SETTINGS_TAB, + [TAB_MAPPING]: UIM_DETAIL_PANEL_MAPPING_TAB, + [TAB_STATS]: UIM_DETAIL_PANEL_STATS_TAB, + [TAB_EDIT_SETTINGS]: UIM_DETAIL_PANEL_EDIT_SETTINGS_TAB, + }; + + if (panelTypeToUiMetricMap[panelType]) { + uiMetricService.trackMetric('count', panelTypeToUiMetricMap[panelType]); + } + + return { + panelType: panelType || state.panelType || TAB_SUMMARY, + indexName, + title, + }; + }, + [closeDetailPanel]() { + return {}; + }, + [loadIndexDataSuccess](state, action) { + const { data } = action.payload; + const newState = { + ...state, + data, + }; + return newState; + }, + [updateIndexSettingsError](state, action) { + const { error } = action.payload; + const newState = { + ...state, + error, + }; + return newState; + }, + [updateIndexSettingsSuccess]() { + return {}; + }, + }, + defaultState + ); diff --git a/x-pack/legacy/plugins/index_management/public/app/store/store.d.ts b/x-pack/legacy/plugins/index_management/public/application/store/reducers/index.js similarity index 82% rename from x-pack/legacy/plugins/index_management/public/app/store/store.d.ts rename to x-pack/legacy/plugins/index_management/public/application/store/reducers/index.js index 4772f2124bfe0..ff2b94b0d36e9 100644 --- a/x-pack/legacy/plugins/index_management/public/app/store/store.d.ts +++ b/x-pack/legacy/plugins/index_management/public/application/store/reducers/index.js @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export declare function indexManagementStore(): any; +export { getReducer } from './index_management'; diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/index_management.js b/x-pack/legacy/plugins/index_management/public/application/store/reducers/index_management.js similarity index 63% rename from x-pack/legacy/plugins/index_management/public/app/store/reducers/index_management.js rename to x-pack/legacy/plugins/index_management/public/application/store/reducers/index_management.js index 14f270670c0d6..233e6f692ca70 100644 --- a/x-pack/legacy/plugins/index_management/public/app/store/reducers/index_management.js +++ b/x-pack/legacy/plugins/index_management/public/application/store/reducers/index_management.js @@ -5,14 +5,15 @@ */ import { combineReducers } from 'redux'; -import { detailPanel } from './detail_panel'; +import { getDetailPanelReducer } from './detail_panel'; import { indices } from './indices'; import { rowStatus } from './row_status'; import { tableState } from './table_state'; -export const indexManagement = combineReducers({ - indices, - rowStatus, - tableState, - detailPanel, -}); +export const getReducer = ({ uiMetricService }) => + combineReducers({ + indices, + rowStatus, + tableState, + detailPanel: getDetailPanelReducer(uiMetricService), + }); diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/indices.js b/x-pack/legacy/plugins/index_management/public/application/store/reducers/indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/reducers/indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/reducers/indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/row_status.js b/x-pack/legacy/plugins/index_management/public/application/store/reducers/row_status.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/reducers/row_status.js rename to x-pack/legacy/plugins/index_management/public/application/store/reducers/row_status.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/table_state.js b/x-pack/legacy/plugins/index_management/public/application/store/reducers/table_state.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/reducers/table_state.js rename to x-pack/legacy/plugins/index_management/public/application/store/reducers/table_state.js diff --git a/x-pack/legacy/plugins/index_management/public/application/store/selectors/index.d.ts b/x-pack/legacy/plugins/index_management/public/application/store/selectors/index.d.ts new file mode 100644 index 0000000000000..999b11c5d6665 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/store/selectors/index.d.ts @@ -0,0 +1,8 @@ +/* + * 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 { ExtensionsService } from '../../../services'; + +export declare function setExtensionsService(extensionsService: ExtensionsService): any; diff --git a/x-pack/legacy/plugins/index_management/public/app/store/selectors/index.js b/x-pack/legacy/plugins/index_management/public/application/store/selectors/index.js similarity index 93% rename from x-pack/legacy/plugins/index_management/public/app/store/selectors/index.js rename to x-pack/legacy/plugins/index_management/public/application/store/selectors/index.js index 654e7276bbb08..3ddbf28651fa0 100644 --- a/x-pack/legacy/plugins/index_management/public/app/store/selectors/index.js +++ b/x-pack/legacy/plugins/index_management/public/application/store/selectors/index.js @@ -8,7 +8,15 @@ import { Pager, EuiSearchBar } from '@elastic/eui'; import { createSelector } from 'reselect'; import { indexStatusLabels } from '../../lib/index_status_labels'; import { sortTable } from '../../services'; -import { getToggleExtensions } from '../../../index_management_extensions'; + +// Temporary hack to provide the extensionsService instance to this file. +// TODO: Refactor and export all the app selectors through the app dependencies context + +let extensionsService; +export const setExtensionsService = _extensionsService => { + extensionsService = _extensionsService; +}; +// End hack export const getDetailPanelData = state => state.detailPanel.data; export const getDetailPanelError = state => state.detailPanel.error; @@ -46,7 +54,7 @@ export const hasSystemIndex = indexNames => { const defaultFilterFields = ['name']; const filterByToggles = (indices, toggleNameToVisibleMap) => { - const togglesByName = getToggleExtensions().reduce( + const togglesByName = extensionsService.toggles.reduce( (byName, toggle) => ({ ...byName, [toggle.name]: toggle, diff --git a/x-pack/legacy/plugins/index_management/public/application/store/store.d.ts b/x-pack/legacy/plugins/index_management/public/application/store/store.d.ts new file mode 100644 index 0000000000000..1568275badeee --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/store/store.d.ts @@ -0,0 +1,9 @@ +/* + * 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 { AppDependencies } from '../app_context'; + +export declare function indexManagementStore(services: AppDependencies['services']): any; diff --git a/x-pack/legacy/plugins/index_management/public/app/store/store.js b/x-pack/legacy/plugins/index_management/public/application/store/store.js similarity index 71% rename from x-pack/legacy/plugins/index_management/public/app/store/store.js rename to x-pack/legacy/plugins/index_management/public/application/store/store.js index 3e80274a96960..e103ff0778be1 100644 --- a/x-pack/legacy/plugins/index_management/public/app/store/store.js +++ b/x-pack/legacy/plugins/index_management/public/application/store/store.js @@ -6,19 +6,18 @@ import { createStore, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; -import { getToggleExtensions } from '../../index_management_extensions'; import { defaultTableState } from './reducers/table_state'; -import { indexManagement } from './reducers/'; +import { getReducer } from './reducers/'; -export function indexManagementStore() { +export function indexManagementStore(services) { const toggleNameToVisibleMap = {}; - getToggleExtensions().forEach(toggleExtension => { + services.extensionsService.toggles.forEach(toggleExtension => { toggleNameToVisibleMap[toggleExtension.name] = false; }); const initialState = { tableState: { ...defaultTableState, toggleNameToVisibleMap } }; const enhancers = [applyMiddleware(thunk)]; window.__REDUX_DEVTOOLS_EXTENSION__ && enhancers.push(window.__REDUX_DEVTOOLS_EXTENSION__()); - return createStore(indexManagement, initialState, compose(...enhancers)); + return createStore(getReducer(services), initialState, compose(...enhancers)); } diff --git a/x-pack/legacy/plugins/index_management/public/index.scss b/x-pack/legacy/plugins/index_management/public/index.scss index 7128e4a207ca1..0fbf8ea5036c5 100644 --- a/x-pack/legacy/plugins/index_management/public/index.scss +++ b/x-pack/legacy/plugins/index_management/public/index.scss @@ -10,7 +10,7 @@ // indChart__legend--small // indChart__legend-isLoading -@import './app/components/mappings_editor/index'; +@import './application/components/mappings_editor/index'; .indTable { // The index table is a bespoke table and can't make use of EuiBasicTable's width settings diff --git a/x-pack/legacy/plugins/index_management/public/index.ts b/x-pack/legacy/plugins/index_management/public/index.ts index 3003c4e909956..16e7bf21aee98 100644 --- a/x-pack/legacy/plugins/index_management/public/index.ts +++ b/x-pack/legacy/plugins/index_management/public/index.ts @@ -3,43 +3,19 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { npStart } from 'ui/new_platform'; +import { npSetup } from 'ui/new_platform'; -import { IndexMgmtPlugin } from './plugin'; -import { __LEGACYStart } from './legacy'; -import { - addSummaryExtension, - getSummaryExtensions, - addActionExtension, - getActionExtensions, - addBannerExtension, - getBannerExtensions, - addFilterExtension, - getFilterExtensions, - addToggleExtension, - getToggleExtensions, - addBadgeExtension, - getBadgeExtensions, -} from './index_management_extensions'; +import { IndexMgmtUIPlugin, IndexMgmtSetup } from './plugin'; + +/** @public */ +export { IndexMgmtSetup }; export const plugin = () => { - return new IndexMgmtPlugin(); + return new IndexMgmtUIPlugin(); }; -/** @public */ -export { - addSummaryExtension, - getSummaryExtensions, - addActionExtension, - getActionExtensions, - addBannerExtension, - getBannerExtensions, - addFilterExtension, - getFilterExtensions, - addToggleExtension, - getToggleExtensions, - addBadgeExtension, - getBadgeExtensions, -}; +// Temp. To be removed after moving to the "plugins" folder + +const { extensionsService } = plugin().setup(npSetup.core, npSetup.plugins); -plugin().start(npStart.core, npStart.plugins, __LEGACYStart); +export { extensionsService }; diff --git a/x-pack/legacy/plugins/index_management/public/index_management_extensions.ts b/x-pack/legacy/plugins/index_management/public/index_management_extensions.ts deleted file mode 100644 index 2f578e7c4a5a4..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/index_management_extensions.ts +++ /dev/null @@ -1,72 +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 { i18n } from '@kbn/i18n'; - -const summaryExtensions: any[] = []; -export const addSummaryExtension = (summaryExtension: any) => { - summaryExtensions.push(summaryExtension); -}; - -export const getSummaryExtensions = () => { - return summaryExtensions; -}; - -const actionExtensions: any[] = []; -export const addActionExtension = (actionExtension: any) => { - actionExtensions.push(actionExtension); -}; - -export const getActionExtensions = () => { - return actionExtensions; -}; - -const bannerExtensions: any[] = []; -export const addBannerExtension = (actionExtension: any) => { - bannerExtensions.push(actionExtension); -}; - -export const getBannerExtensions = () => { - return bannerExtensions; -}; - -const filterExtensions: any[] = []; -export const addFilterExtension = (filterExtension: any) => { - filterExtensions.push(filterExtension); -}; - -export const getFilterExtensions = () => { - return filterExtensions; -}; - -const toggleExtensions: any[] = []; -export const addToggleExtension = (toggleExtension: any) => { - toggleExtensions.push(toggleExtension); -}; - -export const getToggleExtensions = () => { - return toggleExtensions; -}; - -const badgeExtensions = [ - { - matchIndex: (index: { isFrozen: boolean }) => { - return index.isFrozen; - }, - label: i18n.translate('xpack.idxMgmt.frozenBadgeLabel', { - defaultMessage: 'Frozen', - }), - filterExpression: 'isFrozen:true', - color: 'primary', - }, -]; - -export const addBadgeExtension = (badgeExtension: any) => { - badgeExtensions.push(badgeExtension); -}; - -export const getBadgeExtensions = () => { - return badgeExtensions; -}; diff --git a/x-pack/legacy/plugins/index_management/public/legacy.ts b/x-pack/legacy/plugins/index_management/public/legacy.ts deleted file mode 100644 index eee24feff5a67..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/legacy.ts +++ /dev/null @@ -1,31 +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 { management, MANAGEMENT_BREADCRUMB } from 'ui/management'; -import { createUiStatsReporter } from '../../../../../src/legacy/core_plugins/ui_metric/public'; - -export interface LegacyStart { - management: { - getSection: typeof management.getSection; - constants: { - BREADCRUMB: typeof MANAGEMENT_BREADCRUMB; - }; - }; - uiMetric: { - createUiStatsReporter: typeof createUiStatsReporter; - }; -} - -export const __LEGACYStart = { - management: { - getSection: management.getSection.bind(management), - constants: { - BREADCRUMB: MANAGEMENT_BREADCRUMB, - }, - }, - uiMetric: { - createUiStatsReporter, - }, -}; diff --git a/x-pack/legacy/plugins/index_management/public/mocks.ts b/x-pack/legacy/plugins/index_management/public/mocks.ts new file mode 100644 index 0000000000000..7062e7bacace0 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/mocks.ts @@ -0,0 +1,21 @@ +/* + * 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 { extensionsServiceMock } from './services/extensions_service.mock'; + +export { extensionsServiceMock } from './services/extensions_service.mock'; + +function createIdxManagementSetupMock() { + const mock = { + extensionsService: extensionsServiceMock, + }; + + return mock; +} + +export const indexManagementMock = { + createSetup: createIdxManagementSetupMock, +}; diff --git a/x-pack/legacy/plugins/index_management/public/plugin.ts b/x-pack/legacy/plugins/index_management/public/plugin.ts index 71ecdd7a1fbef..539324766cf95 100644 --- a/x-pack/legacy/plugins/index_management/public/plugin.ts +++ b/x-pack/legacy/plugins/index_management/public/plugin.ts @@ -3,32 +3,90 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { CoreStart } from '../../../../../src/core/public'; - -import { registerManagementSection } from './register_management_section'; -import { registerRoutes } from './register_routes'; -import { LegacyStart } from './legacy'; - -import { httpService } from './app/services/http'; -import { breadcrumbService } from './app/services/breadcrumbs'; -import { documentationService } from './app/services/documentation'; -import { notificationService } from './app/services/notification'; -import { uiMetricService } from './app/services/ui_metric'; - -export class IndexMgmtPlugin { - public start(core: CoreStart, plugins: {}, __LEGACY: LegacyStart) { - const { management, uiMetric } = __LEGACY; - const { http, chrome, docLinks, notifications } = core; - - // Initialize services - httpService.init(http); - breadcrumbService.init(chrome, management.constants.BREADCRUMB); - documentationService.init(docLinks); - notificationService.init(notifications); - uiMetricService.init(uiMetric.createUiStatsReporter); - - // Register management section and Angular route - registerManagementSection(management.getSection('elasticsearch')); - registerRoutes(core); +import { i18n } from '@kbn/i18n'; + +import { CoreSetup } from '../../../../../src/core/public'; +import { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/public'; +import { ManagementSetup } from '../../../../../src/plugins/management/public'; +import { UIM_APP_NAME } from '../common/constants'; + +import { AppDependencies } from './application'; +import { httpService } from './application/services/http'; +import { breadcrumbService } from './application/services/breadcrumbs'; +import { documentationService } from './application/services/documentation'; +import { notificationService } from './application/services/notification'; +import { UiMetricService } from './application/services/ui_metric'; + +import { setExtensionsService } from './application/store/selectors'; +import { setUiMetricService } from './application/services/api'; + +import { IndexMgmtMetricsType } from './types'; +import { ExtensionsService, ExtensionsSetup } from './services'; + +export interface IndexMgmtSetup { + extensionsService: ExtensionsSetup; +} + +interface PluginsDependencies { + usageCollection: UsageCollectionSetup; + management: ManagementSetup; +} + +export class IndexMgmtUIPlugin { + private uiMetricService = new UiMetricService(UIM_APP_NAME); + private extensionsService = new ExtensionsService(); + + constructor() { + // Temporary hack to provide the service instances in module files in order to avoid a big refactor + // For the selectors we should expose them through app dependencies and read them from there on each container component. + setExtensionsService(this.extensionsService); + setUiMetricService(this.uiMetricService); } + + public setup(coreSetup: CoreSetup, plugins: PluginsDependencies): IndexMgmtSetup { + const { http, notifications, getStartServices } = coreSetup; + const { usageCollection, management } = plugins; + + httpService.setup(http); + notificationService.setup(notifications); + this.uiMetricService.setup(usageCollection); + + management.sections.getSection('elasticsearch')!.registerApp({ + id: 'index_management', + title: i18n.translate('xpack.idxMgmt.appTitle', { defaultMessage: 'Index Management' }), + order: 1, + mount: async ({ element, setBreadcrumbs }) => { + const [core] = await getStartServices(); + const { docLinks, fatalErrors } = core; + + breadcrumbService.setup(setBreadcrumbs); + documentationService.setup(docLinks); + + const appDependencies: AppDependencies = { + core: { + fatalErrors, + }, + plugins: { + usageCollection, + }, + services: { + uiMetricService: this.uiMetricService, + extensionsService: this.extensionsService, + httpService, + notificationService, + }, + }; + + const { renderApp } = await import('./application'); + return renderApp(element, { core, dependencies: appDependencies }); + }, + }); + + return { + extensionsService: this.extensionsService.setup(), + }; + } + + public start() {} + public stop() {} } diff --git a/x-pack/legacy/plugins/index_management/public/register_management_section.ts b/x-pack/legacy/plugins/index_management/public/register_management_section.ts deleted file mode 100644 index f090b322583d2..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/register_management_section.ts +++ /dev/null @@ -1,19 +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 { i18n } from '@kbn/i18n'; -import { BASE_PATH } from '../common/constants'; - -export const registerManagementSection = (esSection: { - register: (section: string, config: {}) => void; -}) => { - esSection.register('index_management', { - visible: true, - display: i18n.translate('xpack.idxMgmt.appTitle', { defaultMessage: 'Index Management' }), - order: 1, - url: `#${BASE_PATH}indices`, - }); -}; diff --git a/x-pack/legacy/plugins/index_management/public/register_routes.ts b/x-pack/legacy/plugins/index_management/public/register_routes.ts deleted file mode 100644 index 378a53cf65555..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/register_routes.ts +++ /dev/null @@ -1,34 +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 routes from 'ui/routes'; - -import { CoreStart } from '../../../../../src/core/public'; - -import { mountReactApp, unmountReactApp } from './app'; -import { REACT_ROOT_ID } from './app/constants'; -import { BASE_PATH } from '../common/constants'; - -import template from './index.html'; -import { manageAngularLifecycle } from './app/lib/manage_angular_lifecycle'; - -let elem: HTMLElement | null; - -export const registerRoutes = (core: CoreStart) => { - routes.when(`${BASE_PATH}:view?/:action?/:id?`, { - template, - controller: ($scope: any, $route: any) => { - // clean up previously rendered React app if one exists - // this happens because of React Router redirects - unmountReactApp(elem); - - $scope.$$postDigest(() => { - elem = document.getElementById(REACT_ROOT_ID); - mountReactApp(elem, { core }); - manageAngularLifecycle($scope, $route, elem); - }); - }, - }); -}; diff --git a/x-pack/legacy/plugins/index_management/public/services/extensions_service.mock.ts b/x-pack/legacy/plugins/index_management/public/services/extensions_service.mock.ts new file mode 100644 index 0000000000000..3075a114eedd1 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/services/extensions_service.mock.ts @@ -0,0 +1,31 @@ +/* + * 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 { ExtensionsService, ExtensionsSetup } from './extensions_service'; + +export type ExtensionsSetupMock = jest.Mocked; + +const createServiceMock = (): ExtensionsSetupMock => ({ + addAction: jest.fn(), + addBadge: jest.fn(), + addBanner: jest.fn(), + addFilter: jest.fn(), + addSummary: jest.fn(), + addToggle: jest.fn(), +}); + +const createMock = () => { + const mocked: jest.Mocked> = { + setup: jest.fn(), + }; + mocked.setup.mockReturnValue(createServiceMock()); + return mocked; +}; + +export const extensionsServiceMock = { + create: createMock, + createSetupContract: createServiceMock, +}; diff --git a/x-pack/legacy/plugins/index_management/public/services/extensions_service.ts b/x-pack/legacy/plugins/index_management/public/services/extensions_service.ts new file mode 100644 index 0000000000000..22e0546beff99 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/services/extensions_service.ts @@ -0,0 +1,97 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export interface ExtensionsSetup { + addSummary(summary: any): void; + addAction(action: any): void; + addBanner(banner: any): void; + addFilter(filter: any): void; + addBadge(badge: any): void; + addToggle(toggle: any): void; +} + +export class ExtensionsService { + private _summaries: any[] = []; + private _actions: any[] = []; + private _banners: any[] = []; + private _filters: any[] = []; + private _badges: any[] = [ + { + matchIndex: (index: { isFrozen: boolean }) => { + return index.isFrozen; + }, + label: i18n.translate('xpack.idxMgmt.frozenBadgeLabel', { + defaultMessage: 'Frozen', + }), + filterExpression: 'isFrozen:true', + color: 'primary', + }, + ]; + private _toggles: any[] = []; + private service?: ExtensionsSetup; + + public setup(): ExtensionsSetup { + this.service = { + addAction: this.addAction.bind(this), + addBadge: this.addBadge.bind(this), + addBanner: this.addBanner.bind(this), + addFilter: this.addFilter.bind(this), + addSummary: this.addSummary.bind(this), + addToggle: this.addToggle.bind(this), + }; + + return this.service; + } + + private addSummary(summary: any) { + this._summaries.push(summary); + } + + private addAction(action: any) { + this._actions.push(action); + } + + private addBanner(banner: any) { + this._banners.push(banner); + } + + private addFilter(filter: any) { + this._filters.push(filter); + } + + private addBadge(badge: any) { + this._badges.push(badge); + } + + private addToggle(toggle: any) { + this._toggles.push(toggle); + } + + public get summaries() { + return this._summaries; + } + + public get actions() { + return this._actions; + } + + public get banners() { + return this._banners; + } + + public get filters() { + return this._filters; + } + + public get badges() { + return this._badges; + } + + public get toggles() { + return this._toggles; + } +} diff --git a/x-pack/legacy/plugins/index_management/public/services/index.ts b/x-pack/legacy/plugins/index_management/public/services/index.ts new file mode 100644 index 0000000000000..e5dfabe1d1190 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/services/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 { ExtensionsService, ExtensionsSetup } from './extensions_service'; diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/index.js b/x-pack/legacy/plugins/index_management/public/types.ts similarity index 78% rename from x-pack/legacy/plugins/index_management/public/app/store/reducers/index.js rename to x-pack/legacy/plugins/index_management/public/types.ts index eeae581be9473..08fbf63450218 100644 --- a/x-pack/legacy/plugins/index_management/public/app/store/reducers/index.js +++ b/x-pack/legacy/plugins/index_management/public/types.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { indexManagement } from './index_management'; +export type IndexMgmtMetricsType = 'loaded' | 'click' | 'count'; diff --git a/x-pack/legacy/plugins/rollup/public/legacy.ts b/x-pack/legacy/plugins/rollup/public/legacy.ts index 17597672a898e..64eb1f6436389 100644 --- a/x-pack/legacy/plugins/rollup/public/legacy.ts +++ b/x-pack/legacy/plugins/rollup/public/legacy.ts @@ -10,7 +10,7 @@ import { aggTypeFieldFilters } from 'ui/agg_types'; import { addSearchStrategy } from '../../../../../src/plugins/data/public'; import { RollupPlugin } from './plugin'; import { setup as management } from '../../../../../src/legacy/core_plugins/management/public/legacy'; -import { addBadgeExtension, addToggleExtension } from '../../index_management/public'; +import { extensionsService } from '../../index_management/public'; const plugin = new RollupPlugin(); @@ -20,8 +20,7 @@ export const setup = plugin.setup(npSetup.core, { aggTypeFilters, aggTypeFieldFilters, addSearchStrategy, - addBadgeExtension, - addToggleExtension, + indexManagementExtensions: extensionsService, managementLegacy: management, }, }); diff --git a/x-pack/legacy/plugins/rollup/public/plugin.ts b/x-pack/legacy/plugins/rollup/public/plugin.ts index 4dae078c90f57..90d7e2d9d0191 100644 --- a/x-pack/legacy/plugins/rollup/public/plugin.ts +++ b/x-pack/legacy/plugins/rollup/public/plugin.ts @@ -27,6 +27,7 @@ import { // @ts-ignore import { CRUD_APP_BASE_PATH } from './crud_app/constants'; import { ManagementSetup } from '../../../../../src/plugins/management/public'; +import { IndexMgmtSetup } from '../../index_management/public'; // @ts-ignore import { setEsBaseAndXPackBase, setHttp } from './crud_app/services'; import { setNotifications, setFatalErrors } from './kibana_services'; @@ -38,8 +39,7 @@ export interface RollupPluginSetupDependencies { aggTypeFieldFilters: AggTypeFieldFilters; addSearchStrategy: (searchStrategy: SearchStrategyProvider) => void; managementLegacy: ManagementSetupLegacy; - addBadgeExtension: (badgeExtension: any) => void; - addToggleExtension: (toggleExtension: any) => void; + indexManagementExtensions: IndexMgmtSetup['extensionsService']; }; home?: HomePublicPluginSetup; management: ManagementSetup; @@ -54,16 +54,15 @@ export class RollupPlugin implements Plugin { aggTypeFieldFilters, addSearchStrategy, managementLegacy, - addBadgeExtension, - addToggleExtension, + indexManagementExtensions, }, home, management, }: RollupPluginSetupDependencies ) { setFatalErrors(core.fatalErrors); - addBadgeExtension(rollupBadgeExtension); - addToggleExtension(rollupToggleExtension); + indexManagementExtensions.addBadge(rollupBadgeExtension); + indexManagementExtensions.addToggle(rollupToggleExtension); const isRollupIndexPatternsEnabled = core.uiSettings.get(CONFIG_ROLLUPS); From f4d29abf1cd8763396bb9fbb1e19df73f31132c8 Mon Sep 17 00:00:00 2001 From: patrykkopycinski Date: Mon, 17 Feb 2020 09:58:54 +0100 Subject: [PATCH 29/32] Bump redux dependencies (#53348) --- package.json | 31 +- packages/kbn-pm/dist/index.js | 5298 +++++++---------- .../public/utils/typed_react.ts | 47 - .../workpad_app/workpad_telemetry.test.tsx | 13 +- .../workpad/workpad_app/workpad_telemetry.tsx | 37 +- .../canvas/public/components/router/router.js | 6 +- .../sidebar/element_settings/index.tsx | 5 - .../field_manager/field_manager.test.tsx | 4 +- .../field_manager/field_manager.tsx | 2 + .../components/logging/log_time_controls.tsx | 2 +- .../waffle/waffle_time_controls.tsx | 5 +- .../infra/public/utils/redux_context.tsx | 10 +- .../infra/public/utils/typed_react.tsx | 13 +- .../layer_addpanel/index.js | 2 +- .../connected_components/map/mb/index.js | 2 +- .../layer_control/layer_toc/index.js | 2 +- .../population_view/metric_selection.tsx | 5 +- .../jobs/new_job/pages/new_job/wizard.tsx | 10 +- .../drag_drop_context_wrapper.tsx | 11 +- .../drag_and_drop/draggable_wrapper.tsx | 24 +- .../error_toast_dispatcher/index.tsx | 25 +- .../public/components/events_viewer/index.tsx | 67 +- .../components/fields_browser/index.test.tsx | 29 + .../components/fields_browser/index.tsx | 27 +- .../public/components/flyout/header/index.tsx | 91 +- .../siem/public/components/flyout/index.tsx | 44 +- .../public/components/flyout/pane/index.tsx | 25 +- .../components/open_timeline/helpers.ts | 10 +- .../public/components/open_timeline/index.tsx | 16 +- .../public/components/open_timeline/types.ts | 17 - .../hosts/authentications_table/index.tsx | 35 +- .../page/hosts/hosts_table/index.tsx | 39 +- .../hosts/uncommon_process_table/index.tsx | 35 +- .../page/network/network_dns_table/index.tsx | 30 +- .../__snapshots__/index.test.tsx.snap | 2 +- .../network/network_http_table/index.test.tsx | 2 +- .../page/network/network_http_table/index.tsx | 201 +- .../network_top_countries_table/index.tsx | 36 +- .../network_top_n_flow_table/index.tsx | 36 +- .../page/network/tls_table/index.tsx | 34 +- .../page/network/users_table/index.tsx | 29 +- .../components/recent_timelines/index.tsx | 20 +- .../public/components/search_bar/index.tsx | 43 +- .../components/super_date_picker/index.tsx | 41 +- .../timeline/auto_save_warning/index.tsx | 38 +- .../components/timeline/body/index.test.tsx | 6 - .../public/components/timeline/body/index.tsx | 1 - .../timeline/body/stateful_body.tsx | 74 +- .../timeline/fetch_kql_timeline.tsx | 32 +- .../siem/public/components/timeline/index.tsx | 128 +- .../components/timeline/refetch_timeline.tsx | 32 +- .../timeline/search_or_filter/index.tsx | 64 +- .../public/components/timeline/timeline.tsx | 2 +- .../public/containers/global_time/index.tsx | 30 +- .../public/containers/ip_overview/index.tsx | 14 +- .../containers/kpi_host_details/index.tsx | 14 +- .../public/containers/kpi_hosts/index.tsx | 14 +- .../public/containers/kpi_network/index.tsx | 14 +- .../overview/overview_host/index.tsx | 14 +- .../overview/overview_network/index.tsx | 74 +- .../siem/public/containers/timeline/index.tsx | 15 +- .../containers/uncommon_processes/index.tsx | 16 +- .../siem/public/containers/users/index.tsx | 25 +- .../components/signals/index.tsx | 45 +- .../detection_engine/detection_engine.tsx | 33 +- .../detection_engine/rules/details/index.tsx | 32 +- .../plugins/siem/public/pages/home/index.tsx | 4 +- .../pages/hosts/details/details_tabs.tsx | 4 +- .../siem/public/pages/hosts/details/index.tsx | 25 +- .../siem/public/pages/hosts/hosts.test.tsx | 9 - .../plugins/siem/public/pages/hosts/hosts.tsx | 27 +- .../plugins/siem/public/pages/hosts/index.tsx | 8 +- .../plugins/siem/public/pages/hosts/types.ts | 28 +- .../pages/network/ip_details/index.test.tsx | 2 +- .../public/pages/network/ip_details/index.tsx | 19 +- .../public/pages/network/ip_details/types.ts | 26 +- .../siem/public/pages/network/network.tsx | 14 +- .../siem/public/pages/network/types.ts | 14 +- .../siem/public/pages/overview/overview.tsx | 22 +- .../siem/public/store/inputs/actions.ts | 4 +- .../siem/public/store/inputs/helpers.ts | 4 +- .../siem/public/store/network/selectors.ts | 9 +- .../functional/charts/ping_histogram.tsx | 2 +- .../contexts/uptime_refresh_context.tsx | 1 + .../plugins/uptime/public/uptime_app.tsx | 1 + x-pack/package.json | 37 +- yarn.lock | 481 +- 87 files changed, 2967 insertions(+), 4954 deletions(-) diff --git a/package.json b/package.json index e801f75b976f8..e4fdaf32a014a 100644 --- a/package.json +++ b/package.json @@ -80,12 +80,14 @@ }, "resolutions": { "**/@types/node": "10.12.27", - "**/@types/react": "^16.9.13", + "**/@types/react": "^16.9.19", "**/@types/react-router": "^5.1.3", "**/@types/hapi": "^17.0.18", "**/@types/angular": "^1.6.56", + "**/@types/hoist-non-react-statics": "^3.3.1", "**/typescript": "3.7.2", "**/graphql-toolkit/lodash": "^4.17.13", + "**/hoist-non-react-statics": "^3.3.2", "**/isomorphic-git/**/base64-js": "^1.2.1", "**/image-diff/gm/debug": "^2.6.9", "**/react-dom": "^16.12.0", @@ -234,19 +236,19 @@ "react-input-range": "^1.3.0", "react-markdown": "^3.4.1", "react-monaco-editor": "~0.27.0", - "react-redux": "^5.1.2", + "react-redux": "^7.1.3", "react-resize-detector": "^4.2.0", "react-router-dom": "^5.1.2", "react-sizeme": "^2.3.6", "react-use": "^13.13.0", "reactcss": "1.2.3", - "redux": "4.0.0", - "redux-actions": "2.6.5", - "redux-thunk": "2.3.0", + "redux": "^4.0.5", + "redux-actions": "^2.6.5", + "redux-thunk": "^2.3.0", "regenerator-runtime": "^0.13.3", "regression": "2.0.1", "request": "^2.88.0", - "reselect": "^3.0.1", + "reselect": "^4.0.0", "resize-observer-polyfill": "^1.5.0", "rison-node": "1.0.2", "rxjs": "^6.5.3", @@ -318,7 +320,7 @@ "@types/deep-freeze-strict": "^1.1.0", "@types/delete-empty": "^2.0.0", "@types/elasticsearch": "^5.0.33", - "@types/enzyme": "^3.9.0", + "@types/enzyme": "^3.10.5", "@types/eslint": "^6.1.3", "@types/fetch-mock": "^7.3.1", "@types/flot": "^0.0.31", @@ -356,16 +358,15 @@ "@types/podium": "^1.0.0", "@types/prop-types": "^15.5.3", "@types/reach__router": "^1.2.6", - "@types/react": "^16.9.11", - "@types/react-dom": "^16.9.4", + "@types/react": "^16.9.19", + "@types/react-dom": "^16.9.5", "@types/react-grid-layout": "^0.16.7", - "@types/react-redux": "^6.0.6", + "@types/react-redux": "^7.1.7", "@types/react-resize-detector": "^4.0.1", "@types/react-router": "^5.1.3", "@types/react-router-dom": "^5.1.3", "@types/react-virtualized": "^9.18.7", "@types/recompose": "^0.30.6", - "@types/redux": "^3.6.31", "@types/redux-actions": "^2.6.1", "@types/request": "^2.48.2", "@types/selenium-webdriver": "^4.0.5", @@ -398,10 +399,10 @@ "classnames": "2.2.6", "dedent": "^0.7.0", "delete-empty": "^2.0.0", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.15.1", - "enzyme-adapter-utils": "^1.12.1", - "enzyme-to-json": "^3.4.3", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.2", + "enzyme-adapter-utils": "^1.13.0", + "enzyme-to-json": "^3.4.4", "eslint": "^6.8.0", "eslint-config-prettier": "^6.9.0", "eslint-plugin-babel": "^5.3.0", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 314bcf31e6d05..2ccff3e9c3df2 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,7 +94,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); -/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(705); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(704); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); @@ -105,10 +105,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(516); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return _utils_project__WEBPACK_IMPORTED_MODULE_3__["Project"]; }); -/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(579); +/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(578); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__["copyWorkspacePackages"]; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(580); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(579); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -152,7 +152,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(690); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(689); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -2506,9 +2506,9 @@ module.exports = require("path"); __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); /* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(587); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(687); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(688); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(586); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(686); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(687); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -2551,8 +2551,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(501); -/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(581); -/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(586); +/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(580); +/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(585); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -44027,7 +44027,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515); /* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(516); -/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(579); +/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(578); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -47547,7 +47547,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(515); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); /* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(517); -/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(564); +/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(563); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -48399,33 +48399,38 @@ function bugsTypos(bugs, warn) { /* 522 */ /***/ (function(module, exports) { -exports = module.exports = SemVer; - -// The debug function is excluded entirely from the minified version. -/* nomin */ var debug; -/* nomin */ if (typeof process === 'object' && - /* nomin */ process.env && - /* nomin */ process.env.NODE_DEBUG && - /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) - /* nomin */ debug = function() { - /* nomin */ var args = Array.prototype.slice.call(arguments, 0); - /* nomin */ args.unshift('SEMVER'); - /* nomin */ console.log.apply(console, args); - /* nomin */ }; -/* nomin */ else - /* nomin */ debug = function() {}; +exports = module.exports = SemVer + +var debug +/* istanbul ignore next */ +if (typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG)) { + debug = function () { + var args = Array.prototype.slice.call(arguments, 0) + args.unshift('SEMVER') + console.log.apply(console, args) + } +} else { + debug = function () {} +} // Note: this is the semver.org version of the spec that it implements // Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0'; +exports.SEMVER_SPEC_VERSION = '2.0.0' + +var MAX_LENGTH = 256 +var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || + /* istanbul ignore next */ 9007199254740991 -var MAX_LENGTH = 256; -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; +// Max safe segment length for coercion. +var MAX_SAFE_COMPONENT_LENGTH = 16 // The actual regexps go on exports.re -var re = exports.re = []; -var src = exports.src = []; -var R = 0; +var re = exports.re = [] +var src = exports.src = [] +var R = 0 // The following Regular Expressions can be used for tokenizing, // validating, and parsing SemVer version strings. @@ -48433,71 +48438,67 @@ var R = 0; // ## Numeric Identifier // A single `0`, or a non-zero digit followed by zero or more digits. -var NUMERICIDENTIFIER = R++; -src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; -var NUMERICIDENTIFIERLOOSE = R++; -src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; - +var NUMERICIDENTIFIER = R++ +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*' +var NUMERICIDENTIFIERLOOSE = R++ +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+' // ## Non-numeric Identifier // Zero or more digits, followed by a letter or hyphen, and then zero or // more letters, digits, or hyphens. -var NONNUMERICIDENTIFIER = R++; -src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; - +var NONNUMERICIDENTIFIER = R++ +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' // ## Main Version // Three dot-separated numeric identifiers. -var MAINVERSION = R++; +var MAINVERSION = R++ src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')'; + '(' + src[NUMERICIDENTIFIER] + ')' -var MAINVERSIONLOOSE = R++; +var MAINVERSIONLOOSE = R++ src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; + '(' + src[NUMERICIDENTIFIERLOOSE] + ')' // ## Pre-release Version Identifier // A numeric identifier, or a non-numeric identifier. -var PRERELEASEIDENTIFIER = R++; +var PRERELEASEIDENTIFIER = R++ src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; + '|' + src[NONNUMERICIDENTIFIER] + ')' -var PRERELEASEIDENTIFIERLOOSE = R++; +var PRERELEASEIDENTIFIERLOOSE = R++ src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; - + '|' + src[NONNUMERICIDENTIFIER] + ')' // ## Pre-release Version // Hyphen, followed by one or more dot-separated pre-release version // identifiers. -var PRERELEASE = R++; +var PRERELEASE = R++ src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + - '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))' -var PRERELEASELOOSE = R++; +var PRERELEASELOOSE = R++ src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))' // ## Build Metadata Identifier // Any combination of digits, letters, or hyphens. -var BUILDIDENTIFIER = R++; -src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; +var BUILDIDENTIFIER = R++ +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+' // ## Build Metadata // Plus sign, followed by one or more period-separated build metadata // identifiers. -var BUILD = R++; +var BUILD = R++ src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + - '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; - + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))' // ## Full Version String // A main version, followed optionally by a pre-release version and @@ -48508,774 +48509,870 @@ src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + // capturing group, because it should not ever be used in version // comparison. -var FULL = R++; +var FULL = R++ var FULLPLAIN = 'v?' + src[MAINVERSION] + src[PRERELEASE] + '?' + - src[BUILD] + '?'; + src[BUILD] + '?' -src[FULL] = '^' + FULLPLAIN + '$'; +src[FULL] = '^' + FULLPLAIN + '$' // like full, but allows v1.2.3 and =1.2.3, which people do sometimes. // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty // common in the npm registry. var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + src[PRERELEASELOOSE] + '?' + - src[BUILD] + '?'; + src[BUILD] + '?' -var LOOSE = R++; -src[LOOSE] = '^' + LOOSEPLAIN + '$'; +var LOOSE = R++ +src[LOOSE] = '^' + LOOSEPLAIN + '$' -var GTLT = R++; -src[GTLT] = '((?:<|>)?=?)'; +var GTLT = R++ +src[GTLT] = '((?:<|>)?=?)' // Something like "2.*" or "1.2.x". // Note that "x.x" is a valid xRange identifer, meaning "any version" // Only the first item is strictly required. -var XRANGEIDENTIFIERLOOSE = R++; -src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; -var XRANGEIDENTIFIER = R++; -src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; +var XRANGEIDENTIFIERLOOSE = R++ +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' +var XRANGEIDENTIFIER = R++ +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*' -var XRANGEPLAIN = R++; +var XRANGEPLAIN = R++ src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + '(?:' + src[PRERELEASE] + ')?' + src[BUILD] + '?' + - ')?)?'; + ')?)?' -var XRANGEPLAINLOOSE = R++; +var XRANGEPLAINLOOSE = R++ src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:' + src[PRERELEASELOOSE] + ')?' + src[BUILD] + '?' + - ')?)?'; + ')?)?' + +var XRANGE = R++ +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$' +var XRANGELOOSE = R++ +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$' -var XRANGE = R++; -src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; -var XRANGELOOSE = R++; -src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +var COERCE = R++ +src[COERCE] = '(?:^|[^\\d])' + + '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:$|[^\\d])' // Tilde ranges. // Meaning is "reasonably at or greater than" -var LONETILDE = R++; -src[LONETILDE] = '(?:~>?)'; +var LONETILDE = R++ +src[LONETILDE] = '(?:~>?)' -var TILDETRIM = R++; -src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; -re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); -var tildeTrimReplace = '$1~'; +var TILDETRIM = R++ +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+' +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g') +var tildeTrimReplace = '$1~' -var TILDE = R++; -src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; -var TILDELOOSE = R++; -src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; +var TILDE = R++ +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$' +var TILDELOOSE = R++ +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$' // Caret ranges. // Meaning is "at least and backwards compatible with" -var LONECARET = R++; -src[LONECARET] = '(?:\\^)'; +var LONECARET = R++ +src[LONECARET] = '(?:\\^)' -var CARETTRIM = R++; -src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; -re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); -var caretTrimReplace = '$1^'; +var CARETTRIM = R++ +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+' +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g') +var caretTrimReplace = '$1^' -var CARET = R++; -src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; -var CARETLOOSE = R++; -src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; +var CARET = R++ +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$' +var CARETLOOSE = R++ +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$' // A simple gt/lt/eq thing, or just "" to indicate "any version" -var COMPARATORLOOSE = R++; -src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; -var COMPARATOR = R++; -src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; - +var COMPARATORLOOSE = R++ +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$' +var COMPARATOR = R++ +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$' // An expression to strip any whitespace between the gtlt and the thing // it modifies, so that `> 1.2.3` ==> `>1.2.3` -var COMPARATORTRIM = R++; +var COMPARATORTRIM = R++ src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + - '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')' // this one has to use the /g flag -re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); -var comparatorTrimReplace = '$1$2$3'; - +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g') +var comparatorTrimReplace = '$1$2$3' // Something like `1.2.3 - 1.2.4` // Note that these all use the loose form, because they'll be // checked against either the strict or loose comparator form // later. -var HYPHENRANGE = R++; +var HYPHENRANGE = R++ src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + '\\s+-\\s+' + '(' + src[XRANGEPLAIN] + ')' + - '\\s*$'; + '\\s*$' -var HYPHENRANGELOOSE = R++; +var HYPHENRANGELOOSE = R++ src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + '\\s+-\\s+' + '(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s*$'; + '\\s*$' // Star ranges basically just allow anything at all. -var STAR = R++; -src[STAR] = '(<|>)?=?\\s*\\*'; +var STAR = R++ +src[STAR] = '(<|>)?=?\\s*\\*' // Compile to actual regexp objects. // All are flag-free, unless they were created above with a flag. for (var i = 0; i < R; i++) { - debug(i, src[i]); - if (!re[i]) - re[i] = new RegExp(src[i]); + debug(i, src[i]) + if (!re[i]) { + re[i] = new RegExp(src[i]) + } } -exports.parse = parse; -function parse(version, loose) { - if (version instanceof SemVer) - return version; +exports.parse = parse +function parse (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (version instanceof SemVer) { + return version + } - if (typeof version !== 'string') - return null; + if (typeof version !== 'string') { + return null + } - if (version.length > MAX_LENGTH) - return null; + if (version.length > MAX_LENGTH) { + return null + } - var r = loose ? re[LOOSE] : re[FULL]; - if (!r.test(version)) - return null; + var r = options.loose ? re[LOOSE] : re[FULL] + if (!r.test(version)) { + return null + } try { - return new SemVer(version, loose); + return new SemVer(version, options) } catch (er) { - return null; + return null } } -exports.valid = valid; -function valid(version, loose) { - var v = parse(version, loose); - return v ? v.version : null; +exports.valid = valid +function valid (version, options) { + var v = parse(version, options) + return v ? v.version : null } - -exports.clean = clean; -function clean(version, loose) { - var s = parse(version.trim().replace(/^[=v]+/, ''), loose); - return s ? s.version : null; +exports.clean = clean +function clean (version, options) { + var s = parse(version.trim().replace(/^[=v]+/, ''), options) + return s ? s.version : null } -exports.SemVer = SemVer; +exports.SemVer = SemVer -function SemVer(version, loose) { +function SemVer (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } if (version instanceof SemVer) { - if (version.loose === loose) - return version; - else - version = version.version; + if (version.loose === options.loose) { + return version + } else { + version = version.version + } } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version); + throw new TypeError('Invalid Version: ' + version) } - if (version.length > MAX_LENGTH) + if (version.length > MAX_LENGTH) { throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') + } + + if (!(this instanceof SemVer)) { + return new SemVer(version, options) + } - if (!(this instanceof SemVer)) - return new SemVer(version, loose); + debug('SemVer', version, options) + this.options = options + this.loose = !!options.loose - debug('SemVer', version, loose); - this.loose = loose; - var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); + var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]) - if (!m) - throw new TypeError('Invalid Version: ' + version); + if (!m) { + throw new TypeError('Invalid Version: ' + version) + } - this.raw = version; + this.raw = version // these are actually numbers - this.major = +m[1]; - this.minor = +m[2]; - this.patch = +m[3]; + this.major = +m[1] + this.minor = +m[2] + this.patch = +m[3] - if (this.major > MAX_SAFE_INTEGER || this.major < 0) + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { throw new TypeError('Invalid major version') + } - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { throw new TypeError('Invalid minor version') + } - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { throw new TypeError('Invalid patch version') + } // numberify any prerelease numeric ids - if (!m[4]) - this.prerelease = []; - else - this.prerelease = m[4].split('.').map(function(id) { + if (!m[4]) { + this.prerelease = [] + } else { + this.prerelease = m[4].split('.').map(function (id) { if (/^[0-9]+$/.test(id)) { - var num = +id; - if (num >= 0 && num < MAX_SAFE_INTEGER) - return num; + var num = +id + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } } - return id; - }); + return id + }) + } - this.build = m[5] ? m[5].split('.') : []; - this.format(); + this.build = m[5] ? m[5].split('.') : [] + this.format() } -SemVer.prototype.format = function() { - this.version = this.major + '.' + this.minor + '.' + this.patch; - if (this.prerelease.length) - this.version += '-' + this.prerelease.join('.'); - return this.version; -}; +SemVer.prototype.format = function () { + this.version = this.major + '.' + this.minor + '.' + this.patch + if (this.prerelease.length) { + this.version += '-' + this.prerelease.join('.') + } + return this.version +} -SemVer.prototype.toString = function() { - return this.version; -}; +SemVer.prototype.toString = function () { + return this.version +} -SemVer.prototype.compare = function(other) { - debug('SemVer.compare', this.version, this.loose, other); - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); +SemVer.prototype.compare = function (other) { + debug('SemVer.compare', this.version, this.options, other) + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } - return this.compareMain(other) || this.comparePre(other); -}; + return this.compareMain(other) || this.comparePre(other) +} -SemVer.prototype.compareMain = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); +SemVer.prototype.compareMain = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch); -}; + compareIdentifiers(this.patch, other.patch) +} -SemVer.prototype.comparePre = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); +SemVer.prototype.comparePre = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) - return -1; - else if (!this.prerelease.length && other.prerelease.length) - return 1; - else if (!this.prerelease.length && !other.prerelease.length) - return 0; + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } - var i = 0; + var i = 0 do { - var a = this.prerelease[i]; - var b = other.prerelease[i]; - debug('prerelease compare', i, a, b); - if (a === undefined && b === undefined) - return 0; - else if (b === undefined) - return 1; - else if (a === undefined) - return -1; - else if (a === b) - continue; - else - return compareIdentifiers(a, b); - } while (++i); -}; + var a = this.prerelease[i] + var b = other.prerelease[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) +} // preminor will bump the version up to the next minor release, and immediately // down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function(release, identifier) { +SemVer.prototype.inc = function (release, identifier) { switch (release) { case 'premajor': - this.prerelease.length = 0; - this.patch = 0; - this.minor = 0; - this.major++; - this.inc('pre', identifier); - break; + this.prerelease.length = 0 + this.patch = 0 + this.minor = 0 + this.major++ + this.inc('pre', identifier) + break case 'preminor': - this.prerelease.length = 0; - this.patch = 0; - this.minor++; - this.inc('pre', identifier); - break; + this.prerelease.length = 0 + this.patch = 0 + this.minor++ + this.inc('pre', identifier) + break case 'prepatch': // If this is already a prerelease, it will bump to the next version // drop any prereleases that might already exist, since they are not // relevant at this point. - this.prerelease.length = 0; - this.inc('patch', identifier); - this.inc('pre', identifier); - break; + this.prerelease.length = 0 + this.inc('patch', identifier) + this.inc('pre', identifier) + break // If the input is a non-prerelease version, this acts the same as // prepatch. case 'prerelease': - if (this.prerelease.length === 0) - this.inc('patch', identifier); - this.inc('pre', identifier); - break; + if (this.prerelease.length === 0) { + this.inc('patch', identifier) + } + this.inc('pre', identifier) + break case 'major': // If this is a pre-major version, bump up to the same major version. // Otherwise increment major. // 1.0.0-5 bumps to 1.0.0 // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) - this.major++; - this.minor = 0; - this.patch = 0; - this.prerelease = []; - break; + if (this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0) { + this.major++ + } + this.minor = 0 + this.patch = 0 + this.prerelease = [] + break case 'minor': // If this is a pre-minor version, bump up to the same minor version. // Otherwise increment minor. // 1.2.0-5 bumps to 1.2.0 // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) - this.minor++; - this.patch = 0; - this.prerelease = []; - break; + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++ + } + this.patch = 0 + this.prerelease = [] + break case 'patch': // If this is not a pre-release version, it will increment the patch. // If it is a pre-release it will bump up to the same patch version. // 1.2.0-5 patches to 1.2.0 // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) - this.patch++; - this.prerelease = []; - break; + if (this.prerelease.length === 0) { + this.patch++ + } + this.prerelease = [] + break // This probably shouldn't be used publicly. // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. case 'pre': - if (this.prerelease.length === 0) - this.prerelease = [0]; - else { - var i = this.prerelease.length; + if (this.prerelease.length === 0) { + this.prerelease = [0] + } else { + var i = this.prerelease.length while (--i >= 0) { if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++; - i = -2; + this.prerelease[i]++ + i = -2 } } - if (i === -1) // didn't increment anything - this.prerelease.push(0); + if (i === -1) { + // didn't increment anything + this.prerelease.push(0) + } } if (identifier) { // 1.2.0-beta.1 bumps to 1.2.0-beta.2, // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) - this.prerelease = [identifier, 0]; - } else - this.prerelease = [identifier, 0]; + if (isNaN(this.prerelease[1])) { + this.prerelease = [identifier, 0] + } + } else { + this.prerelease = [identifier, 0] + } } - break; + break default: - throw new Error('invalid increment argument: ' + release); + throw new Error('invalid increment argument: ' + release) } - this.format(); - this.raw = this.version; - return this; -}; + this.format() + this.raw = this.version + return this +} -exports.inc = inc; -function inc(version, release, loose, identifier) { - if (typeof(loose) === 'string') { - identifier = loose; - loose = undefined; +exports.inc = inc +function inc (version, release, loose, identifier) { + if (typeof (loose) === 'string') { + identifier = loose + loose = undefined } try { - return new SemVer(version, loose).inc(release, identifier).version; + return new SemVer(version, loose).inc(release, identifier).version } catch (er) { - return null; + return null } } -exports.diff = diff; -function diff(version1, version2) { +exports.diff = diff +function diff (version1, version2) { if (eq(version1, version2)) { - return null; + return null } else { - var v1 = parse(version1); - var v2 = parse(version2); + var v1 = parse(version1) + var v2 = parse(version2) + var prefix = '' if (v1.prerelease.length || v2.prerelease.length) { - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return 'pre'+key; - } - } - } - return 'prerelease'; + prefix = 'pre' + var defaultResult = 'prerelease' } for (var key in v1) { if (key === 'major' || key === 'minor' || key === 'patch') { if (v1[key] !== v2[key]) { - return key; + return prefix + key } } } + return defaultResult // may be undefined } } -exports.compareIdentifiers = compareIdentifiers; +exports.compareIdentifiers = compareIdentifiers -var numeric = /^[0-9]+$/; -function compareIdentifiers(a, b) { - var anum = numeric.test(a); - var bnum = numeric.test(b); +var numeric = /^[0-9]+$/ +function compareIdentifiers (a, b) { + var anum = numeric.test(a) + var bnum = numeric.test(b) if (anum && bnum) { - a = +a; - b = +b; + a = +a + b = +b } - return (anum && !bnum) ? -1 : - (bnum && !anum) ? 1 : - a < b ? -1 : - a > b ? 1 : - 0; + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 } -exports.rcompareIdentifiers = rcompareIdentifiers; -function rcompareIdentifiers(a, b) { - return compareIdentifiers(b, a); +exports.rcompareIdentifiers = rcompareIdentifiers +function rcompareIdentifiers (a, b) { + return compareIdentifiers(b, a) } -exports.major = major; -function major(a, loose) { - return new SemVer(a, loose).major; +exports.major = major +function major (a, loose) { + return new SemVer(a, loose).major } -exports.minor = minor; -function minor(a, loose) { - return new SemVer(a, loose).minor; +exports.minor = minor +function minor (a, loose) { + return new SemVer(a, loose).minor } -exports.patch = patch; -function patch(a, loose) { - return new SemVer(a, loose).patch; +exports.patch = patch +function patch (a, loose) { + return new SemVer(a, loose).patch } -exports.compare = compare; -function compare(a, b, loose) { - return new SemVer(a, loose).compare(new SemVer(b, loose)); +exports.compare = compare +function compare (a, b, loose) { + return new SemVer(a, loose).compare(new SemVer(b, loose)) } -exports.compareLoose = compareLoose; -function compareLoose(a, b) { - return compare(a, b, true); +exports.compareLoose = compareLoose +function compareLoose (a, b) { + return compare(a, b, true) } -exports.rcompare = rcompare; -function rcompare(a, b, loose) { - return compare(b, a, loose); +exports.rcompare = rcompare +function rcompare (a, b, loose) { + return compare(b, a, loose) } -exports.sort = sort; -function sort(list, loose) { - return list.sort(function(a, b) { - return exports.compare(a, b, loose); - }); +exports.sort = sort +function sort (list, loose) { + return list.sort(function (a, b) { + return exports.compare(a, b, loose) + }) } -exports.rsort = rsort; -function rsort(list, loose) { - return list.sort(function(a, b) { - return exports.rcompare(a, b, loose); - }); +exports.rsort = rsort +function rsort (list, loose) { + return list.sort(function (a, b) { + return exports.rcompare(a, b, loose) + }) } -exports.gt = gt; -function gt(a, b, loose) { - return compare(a, b, loose) > 0; +exports.gt = gt +function gt (a, b, loose) { + return compare(a, b, loose) > 0 } -exports.lt = lt; -function lt(a, b, loose) { - return compare(a, b, loose) < 0; +exports.lt = lt +function lt (a, b, loose) { + return compare(a, b, loose) < 0 } -exports.eq = eq; -function eq(a, b, loose) { - return compare(a, b, loose) === 0; +exports.eq = eq +function eq (a, b, loose) { + return compare(a, b, loose) === 0 } -exports.neq = neq; -function neq(a, b, loose) { - return compare(a, b, loose) !== 0; +exports.neq = neq +function neq (a, b, loose) { + return compare(a, b, loose) !== 0 } -exports.gte = gte; -function gte(a, b, loose) { - return compare(a, b, loose) >= 0; +exports.gte = gte +function gte (a, b, loose) { + return compare(a, b, loose) >= 0 } -exports.lte = lte; -function lte(a, b, loose) { - return compare(a, b, loose) <= 0; +exports.lte = lte +function lte (a, b, loose) { + return compare(a, b, loose) <= 0 } -exports.cmp = cmp; -function cmp(a, op, b, loose) { - var ret; +exports.cmp = cmp +function cmp (a, op, b, loose) { switch (op) { case '===': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a === b; - break; - case '!==': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a !== b; - break; - case '': case '=': case '==': ret = eq(a, b, loose); break; - case '!=': ret = neq(a, b, loose); break; - case '>': ret = gt(a, b, loose); break; - case '>=': ret = gte(a, b, loose); break; - case '<': ret = lt(a, b, loose); break; - case '<=': ret = lte(a, b, loose); break; - default: throw new TypeError('Invalid operator: ' + op); - } - return ret; -} - -exports.Comparator = Comparator; -function Comparator(comp, loose) { - if (comp instanceof Comparator) { - if (comp.loose === loose) - return comp; - else - comp = comp.value; - } - - if (!(this instanceof Comparator)) - return new Comparator(comp, loose); + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a === b - debug('comparator', comp, loose); - this.loose = loose; - this.parse(comp); + case '!==': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a !== b - if (this.semver === ANY) - this.value = ''; - else - this.value = this.operator + this.semver.version; + case '': + case '=': + case '==': + return eq(a, b, loose) - debug('comp', this); -} + case '!=': + return neq(a, b, loose) -var ANY = {}; -Comparator.prototype.parse = function(comp) { - var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var m = comp.match(r); + case '>': + return gt(a, b, loose) - if (!m) - throw new TypeError('Invalid comparator: ' + comp); + case '>=': + return gte(a, b, loose) - this.operator = m[1]; - if (this.operator === '=') - this.operator = ''; + case '<': + return lt(a, b, loose) - // if it literally is just '>' or '' then allow anything. - if (!m[2]) - this.semver = ANY; - else - this.semver = new SemVer(m[2], this.loose); -}; + case '<=': + return lte(a, b, loose) -Comparator.prototype.toString = function() { - return this.value; -}; + default: + throw new TypeError('Invalid operator: ' + op) + } +} -Comparator.prototype.test = function(version) { - debug('Comparator.test', version, this.loose); +exports.Comparator = Comparator +function Comparator (comp, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } - if (this.semver === ANY) - return true; + if (comp instanceof Comparator) { + if (comp.loose === !!options.loose) { + return comp + } else { + comp = comp.value + } + } - if (typeof version === 'string') - version = new SemVer(version, this.loose); + if (!(this instanceof Comparator)) { + return new Comparator(comp, options) + } - return cmp(version, this.operator, this.semver, this.loose); -}; + debug('comparator', comp, options) + this.options = options + this.loose = !!options.loose + this.parse(comp) -Comparator.prototype.intersects = function(comp, loose) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required'); + if (this.semver === ANY) { + this.value = '' + } else { + this.value = this.operator + this.semver.version } - var rangeTmp; - + debug('comp', this) +} + +var ANY = {} +Comparator.prototype.parse = function (comp) { + var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var m = comp.match(r) + + if (!m) { + throw new TypeError('Invalid comparator: ' + comp) + } + + this.operator = m[1] + if (this.operator === '=') { + this.operator = '' + } + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) { + this.semver = ANY + } else { + this.semver = new SemVer(m[2], this.options.loose) + } +} + +Comparator.prototype.toString = function () { + return this.value +} + +Comparator.prototype.test = function (version) { + debug('Comparator.test', version, this.options.loose) + + if (this.semver === ANY) { + return true + } + + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } + + return cmp(version, this.operator, this.semver, this.options) +} + +Comparator.prototype.intersects = function (comp, options) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required') + } + + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + var rangeTmp + if (this.operator === '') { - rangeTmp = new Range(comp.value, loose); - return satisfies(this.value, rangeTmp, loose); + rangeTmp = new Range(comp.value, options) + return satisfies(this.value, rangeTmp, options) } else if (comp.operator === '') { - rangeTmp = new Range(this.value, loose); - return satisfies(comp.semver, rangeTmp, loose); + rangeTmp = new Range(this.value, options) + return satisfies(comp.semver, rangeTmp, options) } var sameDirectionIncreasing = (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>'); + (comp.operator === '>=' || comp.operator === '>') var sameDirectionDecreasing = (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<'); - var sameSemVer = this.semver.version === comp.semver.version; + (comp.operator === '<=' || comp.operator === '<') + var sameSemVer = this.semver.version === comp.semver.version var differentDirectionsInclusive = (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<='); + (comp.operator === '>=' || comp.operator === '<=') var oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, loose) && + cmp(this.semver, '<', comp.semver, options) && ((this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<')); + (comp.operator === '<=' || comp.operator === '<')) var oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, loose) && + cmp(this.semver, '>', comp.semver, options) && ((this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>')); + (comp.operator === '>=' || comp.operator === '>')) return sameDirectionIncreasing || sameDirectionDecreasing || (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || oppositeDirectionsGreaterThan; -}; + oppositeDirectionsLessThan || oppositeDirectionsGreaterThan +} +exports.Range = Range +function Range (range, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } -exports.Range = Range; -function Range(range, loose) { if (range instanceof Range) { - if (range.loose === loose) { - return range; + if (range.loose === !!options.loose && + range.includePrerelease === !!options.includePrerelease) { + return range } else { - return new Range(range.raw, loose); + return new Range(range.raw, options) } } if (range instanceof Comparator) { - return new Range(range.value, loose); + return new Range(range.value, options) } - if (!(this instanceof Range)) - return new Range(range, loose); + if (!(this instanceof Range)) { + return new Range(range, options) + } - this.loose = loose; + this.options = options + this.loose = !!options.loose + this.includePrerelease = !!options.includePrerelease // First, split based on boolean or || - this.raw = range; - this.set = range.split(/\s*\|\|\s*/).map(function(range) { - return this.parseRange(range.trim()); - }, this).filter(function(c) { + this.raw = range + this.set = range.split(/\s*\|\|\s*/).map(function (range) { + return this.parseRange(range.trim()) + }, this).filter(function (c) { // throw out any that are not relevant for whatever reason - return c.length; - }); + return c.length + }) if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range); + throw new TypeError('Invalid SemVer Range: ' + range) } - this.format(); + this.format() } -Range.prototype.format = function() { - this.range = this.set.map(function(comps) { - return comps.join(' ').trim(); - }).join('||').trim(); - return this.range; -}; +Range.prototype.format = function () { + this.range = this.set.map(function (comps) { + return comps.join(' ').trim() + }).join('||').trim() + return this.range +} -Range.prototype.toString = function() { - return this.range; -}; +Range.prototype.toString = function () { + return this.range +} -Range.prototype.parseRange = function(range) { - var loose = this.loose; - range = range.trim(); - debug('range', range, loose); +Range.prototype.parseRange = function (range) { + var loose = this.options.loose + range = range.trim() // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; - range = range.replace(hr, hyphenReplace); - debug('hyphen replace', range); + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE] + range = range.replace(hr, hyphenReplace) + debug('hyphen replace', range) // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); - debug('comparator trim', range, re[COMPARATORTRIM]); + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range, re[COMPARATORTRIM]) // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[TILDETRIM], tildeTrimReplace); + range = range.replace(re[TILDETRIM], tildeTrimReplace) // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[CARETTRIM], caretTrimReplace); + range = range.replace(re[CARETTRIM], caretTrimReplace) // normalize spaces - range = range.split(/\s+/).join(' '); + range = range.split(/\s+/).join(' ') // At this point, the range is completely trimmed and // ready to be split into comparators. - var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var set = range.split(' ').map(function(comp) { - return parseComparator(comp, loose); - }).join(' ').split(/\s+/); - if (this.loose) { + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var set = range.split(' ').map(function (comp) { + return parseComparator(comp, this.options) + }, this).join(' ').split(/\s+/) + if (this.options.loose) { // in loose mode, throw out any that are not valid comparators - set = set.filter(function(comp) { - return !!comp.match(compRe); - }); + set = set.filter(function (comp) { + return !!comp.match(compRe) + }) } - set = set.map(function(comp) { - return new Comparator(comp, loose); - }); + set = set.map(function (comp) { + return new Comparator(comp, this.options) + }, this) - return set; -}; + return set +} -Range.prototype.intersects = function(range, loose) { +Range.prototype.intersects = function (range, options) { if (!(range instanceof Range)) { - throw new TypeError('a Range is required'); + throw new TypeError('a Range is required') } - return this.set.some(function(thisComparators) { - return thisComparators.every(function(thisComparator) { - return range.set.some(function(rangeComparators) { - return rangeComparators.every(function(rangeComparator) { - return thisComparator.intersects(rangeComparator, loose); - }); - }); - }); - }); -}; + return this.set.some(function (thisComparators) { + return thisComparators.every(function (thisComparator) { + return range.set.some(function (rangeComparators) { + return rangeComparators.every(function (rangeComparator) { + return thisComparator.intersects(rangeComparator, options) + }) + }) + }) + }) +} // Mostly just for testing and legacy API reasons -exports.toComparators = toComparators; -function toComparators(range, loose) { - return new Range(range, loose).set.map(function(comp) { - return comp.map(function(c) { - return c.value; - }).join(' ').trim().split(' '); - }); +exports.toComparators = toComparators +function toComparators (range, options) { + return new Range(range, options).set.map(function (comp) { + return comp.map(function (c) { + return c.value + }).join(' ').trim().split(' ') + }) } // comprised of xranges, tildes, stars, and gtlt's at this point. // already replaced the hyphen ranges // turn into a set of JUST comparators. -function parseComparator(comp, loose) { - debug('comp', comp); - comp = replaceCarets(comp, loose); - debug('caret', comp); - comp = replaceTildes(comp, loose); - debug('tildes', comp); - comp = replaceXRanges(comp, loose); - debug('xrange', comp); - comp = replaceStars(comp, loose); - debug('stars', comp); - return comp; +function parseComparator (comp, options) { + debug('comp', comp, options) + comp = replaceCarets(comp, options) + debug('caret', comp) + comp = replaceTildes(comp, options) + debug('tildes', comp) + comp = replaceXRanges(comp, options) + debug('xrange', comp) + comp = replaceStars(comp, options) + debug('stars', comp) + return comp } -function isX(id) { - return !id || id.toLowerCase() === 'x' || id === '*'; +function isX (id) { + return !id || id.toLowerCase() === 'x' || id === '*' } // ~, ~> --> * (any, kinda silly) @@ -49284,39 +49381,38 @@ function isX(id) { // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceTilde(comp, loose); - }).join(' '); -} - -function replaceTilde(comp, loose) { - var r = loose ? re[TILDELOOSE] : re[TILDE]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr); - var ret; - - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) +function replaceTildes (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceTilde(comp, options) + }).join(' ') +} + +function replaceTilde (comp, options) { + var r = options.loose ? re[TILDELOOSE] : re[TILDE] + return comp.replace(r, function (_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else if (pr) { - debug('replaceTilde pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else if (pr) { + debug('replaceTilde pr', pr) + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } else { // ~1.2.3 == >=1.2.3 <1.3.0 ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; + ' <' + M + '.' + (+m + 1) + '.0' + } - debug('tilde return', ret); - return ret; - }); + debug('tilde return', ret) + return ret + }) } // ^ --> * (any, kinda silly) @@ -49325,138 +49421,144 @@ function replaceTilde(comp, loose) { // ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 // ^1.2.3 --> >=1.2.3 <2.0.0 // ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceCaret(comp, loose); - }).join(' '); -} - -function replaceCaret(comp, loose) { - debug('caret', comp, loose); - var r = loose ? re[CARETLOOSE] : re[CARET]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr); - var ret; - - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) { - if (M === '0') - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; +function replaceCarets (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceCaret(comp, options) + }).join(' ') +} + +function replaceCaret (comp, options) { + debug('caret', comp, options) + var r = options.loose ? re[CARETLOOSE] : re[CARET] + return comp.replace(r, function (_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { + if (M === '0') { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else { + ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' + } } else if (pr) { - debug('replaceCaret pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; + debug('replaceCaret pr', pr) if (M === '0') { - if (m === '0') - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + m + '.' + (+p + 1); - else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + (+M + 1) + '.0.0'; + if (m === '0') { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + m + '.' + (+p + 1) + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + (+M + 1) + '.0.0' + } } else { - debug('no pr'); + debug('no pr') if (M === '0') { - if (m === '0') + if (m === '0') { ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1); - else + ' <' + M + '.' + m + '.' + (+p + 1) + } else { ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; - } else + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0'; + ' <' + (+M + 1) + '.0.0' + } } - debug('caret return', ret); - return ret; - }); + debug('caret return', ret) + return ret + }) } -function replaceXRanges(comp, loose) { - debug('replaceXRanges', comp, loose); - return comp.split(/\s+/).map(function(comp) { - return replaceXRange(comp, loose); - }).join(' '); +function replaceXRanges (comp, options) { + debug('replaceXRanges', comp, options) + return comp.split(/\s+/).map(function (comp) { + return replaceXRange(comp, options) + }).join(' ') } -function replaceXRange(comp, loose) { - comp = comp.trim(); - var r = loose ? re[XRANGELOOSE] : re[XRANGE]; - return comp.replace(r, function(ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr); - var xM = isX(M); - var xm = xM || isX(m); - var xp = xm || isX(p); - var anyX = xp; +function replaceXRange (comp, options) { + comp = comp.trim() + var r = options.loose ? re[XRANGELOOSE] : re[XRANGE] + return comp.replace(r, function (ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr) + var xM = isX(M) + var xm = xM || isX(m) + var xp = xm || isX(p) + var anyX = xp - if (gtlt === '=' && anyX) - gtlt = ''; + if (gtlt === '=' && anyX) { + gtlt = '' + } if (xM) { if (gtlt === '>' || gtlt === '<') { // nothing is allowed - ret = '<0.0.0'; + ret = '<0.0.0' } else { // nothing is forbidden - ret = '*'; + ret = '*' } } else if (gtlt && anyX) { + // we know patch is an x, because we have any x at all. // replace X with 0 - if (xm) - m = 0; - if (xp) - p = 0; + if (xm) { + m = 0 + } + p = 0 if (gtlt === '>') { // >1 => >=2.0.0 // >1.2 => >=1.3.0 // >1.2.3 => >= 1.2.4 - gtlt = '>='; + gtlt = '>=' if (xm) { - M = +M + 1; - m = 0; - p = 0; - } else if (xp) { - m = +m + 1; - p = 0; + M = +M + 1 + m = 0 + p = 0 + } else { + m = +m + 1 + p = 0 } } else if (gtlt === '<=') { // <=0.7.x is actually <0.8.0, since any 0.7.x should // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<'; - if (xm) - M = +M + 1; - else - m = +m + 1; + gtlt = '<' + if (xm) { + M = +M + 1 + } else { + m = +m + 1 + } } - ret = gtlt + M + '.' + m + '.' + p; + ret = gtlt + M + '.' + m + '.' + p } else if (xm) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' } else if (xp) { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' } - debug('xRange return', ret); + debug('xRange return', ret) - return ret; - }); + return ret + }) } // Because * is AND-ed with everything else in the comparator, // and '' means "any version", just remove the *s entirely. -function replaceStars(comp, loose) { - debug('replaceStars', comp, loose); +function replaceStars (comp, options) { + debug('replaceStars', comp, options) // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[STAR], ''); + return comp.trim().replace(re[STAR], '') } // This function is passed to string.replace(re[HYPHENRANGE]) @@ -49464,238 +49566,323 @@ function replaceStars(comp, loose) { // 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 // 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do // 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { - - if (isX(fM)) - from = ''; - else if (isX(fm)) - from = '>=' + fM + '.0.0'; - else if (isX(fp)) - from = '>=' + fM + '.' + fm + '.0'; - else - from = '>=' + from; - - if (isX(tM)) - to = ''; - else if (isX(tm)) - to = '<' + (+tM + 1) + '.0.0'; - else if (isX(tp)) - to = '<' + tM + '.' + (+tm + 1) + '.0'; - else if (tpr) - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; - else - to = '<=' + to; +function hyphenReplace ($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { + if (isX(fM)) { + from = '' + } else if (isX(fm)) { + from = '>=' + fM + '.0.0' + } else if (isX(fp)) { + from = '>=' + fM + '.' + fm + '.0' + } else { + from = '>=' + from + } - return (from + ' ' + to).trim(); -} + if (isX(tM)) { + to = '' + } else if (isX(tm)) { + to = '<' + (+tM + 1) + '.0.0' + } else if (isX(tp)) { + to = '<' + tM + '.' + (+tm + 1) + '.0' + } else if (tpr) { + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr + } else { + to = '<=' + to + } + return (from + ' ' + to).trim() +} // if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function(version) { - if (!version) - return false; +Range.prototype.test = function (version) { + if (!version) { + return false + } - if (typeof version === 'string') - version = new SemVer(version, this.loose); + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version)) - return true; + if (testSet(this.set[i], version, this.options)) { + return true + } } - return false; -}; + return false +} -function testSet(set, version) { +function testSet (set, version, options) { for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) - return false; + if (!set[i].test(version)) { + return false + } } - if (version.prerelease.length) { + if (version.prerelease.length && !options.includePrerelease) { // Find the set of versions that are allowed to have prereleases // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 // That should allow `1.2.3-pr.2` to pass. // However, `1.2.4-alpha.notready` should NOT be allowed, // even though it's within the range set by the comparators. - for (var i = 0; i < set.length; i++) { - debug(set[i].semver); - if (set[i].semver === ANY) - continue; + for (i = 0; i < set.length; i++) { + debug(set[i].semver) + if (set[i].semver === ANY) { + continue + } if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver; + var allowed = set[i].semver if (allowed.major === version.major && allowed.minor === version.minor && - allowed.patch === version.patch) - return true; + allowed.patch === version.patch) { + return true + } } } // Version has a -pre, but it's not one of the ones we like. - return false; + return false } - return true; + return true } -exports.satisfies = satisfies; -function satisfies(version, range, loose) { +exports.satisfies = satisfies +function satisfies (version, range, options) { try { - range = new Range(range, loose); + range = new Range(range, options) } catch (er) { - return false; + return false } - return range.test(version); + return range.test(version) } -exports.maxSatisfying = maxSatisfying; -function maxSatisfying(versions, range, loose) { - var max = null; - var maxSV = null; +exports.maxSatisfying = maxSatisfying +function maxSatisfying (versions, range, options) { + var max = null + var maxSV = null try { - var rangeObj = new Range(range, loose); + var rangeObj = new Range(range, options) } catch (er) { - return null; + return null } versions.forEach(function (v) { - if (rangeObj.test(v)) { // satisfies(v, range, loose) - if (!max || maxSV.compare(v) === -1) { // compare(max, v, true) - max = v; - maxSV = new SemVer(max, loose); + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!max || maxSV.compare(v) === -1) { + // compare(max, v, true) + max = v + maxSV = new SemVer(max, options) } } }) - return max; + return max } -exports.minSatisfying = minSatisfying; -function minSatisfying(versions, range, loose) { - var min = null; - var minSV = null; +exports.minSatisfying = minSatisfying +function minSatisfying (versions, range, options) { + var min = null + var minSV = null try { - var rangeObj = new Range(range, loose); + var rangeObj = new Range(range, options) } catch (er) { - return null; + return null } versions.forEach(function (v) { - if (rangeObj.test(v)) { // satisfies(v, range, loose) - if (!min || minSV.compare(v) === 1) { // compare(min, v, true) - min = v; - minSV = new SemVer(min, loose); + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!min || minSV.compare(v) === 1) { + // compare(min, v, true) + min = v + minSV = new SemVer(min, options) } } }) - return min; + return min +} + +exports.minVersion = minVersion +function minVersion (range, loose) { + range = new Range(range, loose) + + var minver = new SemVer('0.0.0') + if (range.test(minver)) { + return minver + } + + minver = new SemVer('0.0.0-0') + if (range.test(minver)) { + return minver + } + + minver = null + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i] + + comparators.forEach(function (comparator) { + // Clone to avoid manipulating the comparator's semver object. + var compver = new SemVer(comparator.semver.version) + switch (comparator.operator) { + case '>': + if (compver.prerelease.length === 0) { + compver.patch++ + } else { + compver.prerelease.push(0) + } + compver.raw = compver.format() + /* fallthrough */ + case '': + case '>=': + if (!minver || gt(minver, compver)) { + minver = compver + } + break + case '<': + case '<=': + /* Ignore maximum versions */ + break + /* istanbul ignore next */ + default: + throw new Error('Unexpected operation: ' + comparator.operator) + } + }) + } + + if (minver && range.test(minver)) { + return minver + } + + return null } -exports.validRange = validRange; -function validRange(range, loose) { +exports.validRange = validRange +function validRange (range, options) { try { // Return '*' instead of '' so that truthiness works. // This will throw if it's invalid anyway - return new Range(range, loose).range || '*'; + return new Range(range, options).range || '*' } catch (er) { - return null; + return null } } // Determine if version is less than all the versions possible in the range -exports.ltr = ltr; -function ltr(version, range, loose) { - return outside(version, range, '<', loose); +exports.ltr = ltr +function ltr (version, range, options) { + return outside(version, range, '<', options) } // Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr; -function gtr(version, range, loose) { - return outside(version, range, '>', loose); +exports.gtr = gtr +function gtr (version, range, options) { + return outside(version, range, '>', options) } -exports.outside = outside; -function outside(version, range, hilo, loose) { - version = new SemVer(version, loose); - range = new Range(range, loose); +exports.outside = outside +function outside (version, range, hilo, options) { + version = new SemVer(version, options) + range = new Range(range, options) - var gtfn, ltefn, ltfn, comp, ecomp; + var gtfn, ltefn, ltfn, comp, ecomp switch (hilo) { case '>': - gtfn = gt; - ltefn = lte; - ltfn = lt; - comp = '>'; - ecomp = '>='; - break; + gtfn = gt + ltefn = lte + ltfn = lt + comp = '>' + ecomp = '>=' + break case '<': - gtfn = lt; - ltefn = gte; - ltfn = gt; - comp = '<'; - ecomp = '<='; - break; + gtfn = lt + ltefn = gte + ltfn = gt + comp = '<' + ecomp = '<=' + break default: - throw new TypeError('Must provide a hilo val of "<" or ">"'); + throw new TypeError('Must provide a hilo val of "<" or ">"') } // If it satisifes the range it is not outside - if (satisfies(version, range, loose)) { - return false; + if (satisfies(version, range, options)) { + return false } // From now on, variable terms are as if we're in "gtr" mode. // but note that everything is flipped for the "ltr" function. for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i]; + var comparators = range.set[i] - var high = null; - var low = null; + var high = null + var low = null - comparators.forEach(function(comparator) { + comparators.forEach(function (comparator) { if (comparator.semver === ANY) { comparator = new Comparator('>=0.0.0') } - high = high || comparator; - low = low || comparator; - if (gtfn(comparator.semver, high.semver, loose)) { - high = comparator; - } else if (ltfn(comparator.semver, low.semver, loose)) { - low = comparator; + high = high || comparator + low = low || comparator + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator } - }); + }) // If the edge version comparator has a operator then our version // isn't outside it if (high.operator === comp || high.operator === ecomp) { - return false; + return false } // If the lowest version comparator has an operator and our version // is less than it then it isn't higher than the range if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) { - return false; + return false } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false; + return false } } - return true; + return true } -exports.prerelease = prerelease; -function prerelease(version, loose) { - var parsed = parse(version, loose); - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null; +exports.prerelease = prerelease +function prerelease (version, options) { + var parsed = parse(version, options) + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null } -exports.intersects = intersects; -function intersects(r1, r2, loose) { - r1 = new Range(r1, loose) - r2 = new Range(r2, loose) +exports.intersects = intersects +function intersects (r1, r2, options) { + r1 = new Range(r1, options) + r2 = new Range(r2, options) return r1.intersects(r2) } +exports.coerce = coerce +function coerce (version) { + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + var match = version.match(re[COERCE]) + + if (match == null) { + return null + } + + return parse(match[1] + + '.' + (match[2] || '0') + + '.' + (match[3] || '0')) +} + /***/ }), /* 523 */ @@ -52531,8 +52718,8 @@ const fs = __webpack_require__(546); const writeFileAtomic = __webpack_require__(550); const sortKeys = __webpack_require__(557); const makeDir = __webpack_require__(559); -const pify = __webpack_require__(562); -const detectIndent = __webpack_require__(563); +const pify = __webpack_require__(561); +const detectIndent = __webpack_require__(562); const init = (fn, filePath, data, options) => { if (!filePath) { @@ -54607,7 +54794,7 @@ module.exports = function (x) { const fs = __webpack_require__(23); const path = __webpack_require__(16); const pify = __webpack_require__(560); -const semver = __webpack_require__(561); +const semver = __webpack_require__(522); const defaults = { mode: 0o777 & (~process.umask()), @@ -54669,1647 +54856,158 @@ const makeDir = (input, options) => Promise.resolve().then(() => { if (error.code === 'ENOENT') { if (path.dirname(pth) === pth) { throw permissionError(pth); - } - - if (error.message.includes('null bytes')) { - throw error; - } - - return make(path.dirname(pth)).then(() => make(pth)); - } - - return stat(pth) - .then(stats => stats.isDirectory() ? pth : Promise.reject()) - .catch(() => { - throw error; - }); - }); - }; - - return make(path.resolve(input)); -}); - -module.exports = makeDir; -module.exports.default = makeDir; - -module.exports.sync = (input, options) => { - checkPath(input); - options = Object.assign({}, defaults, options); - - if (useNativeRecursiveOption && options.fs.mkdirSync === fs.mkdirSync) { - const pth = path.resolve(input); - - fs.mkdirSync(pth, { - mode: options.mode, - recursive: true - }); - - return pth; - } - - const make = pth => { - try { - options.fs.mkdirSync(pth, options.mode); - } catch (error) { - if (error.code === 'EPERM') { - throw error; - } - - if (error.code === 'ENOENT') { - if (path.dirname(pth) === pth) { - throw permissionError(pth); - } - - if (error.message.includes('null bytes')) { - throw error; - } - - make(path.dirname(pth)); - return make(pth); - } - - try { - if (!options.fs.statSync(pth).isDirectory()) { - throw new Error('The path is not a directory'); - } - } catch (_) { - throw error; - } - } - - return pth; - }; - - return make(path.resolve(input)); -}; - - -/***/ }), -/* 560 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const processFn = (fn, options) => function (...args) { - const P = options.promiseModule; - - return new P((resolve, reject) => { - if (options.multiArgs) { - args.push((...result) => { - if (options.errorFirst) { - if (result[0]) { - reject(result); - } else { - result.shift(); - resolve(result); - } - } else { - resolve(result); - } - }); - } else if (options.errorFirst) { - args.push((error, result) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); - } else { - args.push(resolve); - } - - fn.apply(this, args); - }); -}; - -module.exports = (input, options) => { - options = Object.assign({ - exclude: [/.+(Sync|Stream)$/], - errorFirst: true, - promiseModule: Promise - }, options); - - const objType = typeof input; - if (!(input !== null && (objType === 'object' || objType === 'function'))) { - throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); - } - - const filter = key => { - const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); - return options.include ? options.include.some(match) : !options.exclude.some(match); - }; - - let ret; - if (objType === 'function') { - ret = function (...args) { - return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); - }; - } else { - ret = Object.create(Object.getPrototypeOf(input)); - } - - for (const key in input) { // eslint-disable-line guard-for-in - const property = input[key]; - ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; - } - - return ret; -}; - - -/***/ }), -/* 561 */ -/***/ (function(module, exports) { - -exports = module.exports = SemVer - -var debug -/* istanbul ignore next */ -if (typeof process === 'object' && - process.env && - process.env.NODE_DEBUG && - /\bsemver\b/i.test(process.env.NODE_DEBUG)) { - debug = function () { - var args = Array.prototype.slice.call(arguments, 0) - args.unshift('SEMVER') - console.log.apply(console, args) - } -} else { - debug = function () {} -} - -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0' - -var MAX_LENGTH = 256 -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || - /* istanbul ignore next */ 9007199254740991 - -// Max safe segment length for coercion. -var MAX_SAFE_COMPONENT_LENGTH = 16 - -// The actual regexps go on exports.re -var re = exports.re = [] -var src = exports.src = [] -var R = 0 - -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. - -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. - -var NUMERICIDENTIFIER = R++ -src[NUMERICIDENTIFIER] = '0|[1-9]\\d*' -var NUMERICIDENTIFIERLOOSE = R++ -src[NUMERICIDENTIFIERLOOSE] = '[0-9]+' - -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. - -var NONNUMERICIDENTIFIER = R++ -src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' - -// ## Main Version -// Three dot-separated numeric identifiers. - -var MAINVERSION = R++ -src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')' - -var MAINVERSIONLOOSE = R++ -src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')' - -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. - -var PRERELEASEIDENTIFIER = R++ -src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + - '|' + src[NONNUMERICIDENTIFIER] + ')' - -var PRERELEASEIDENTIFIERLOOSE = R++ -src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + - '|' + src[NONNUMERICIDENTIFIER] + ')' - -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. - -var PRERELEASE = R++ -src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + - '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))' - -var PRERELEASELOOSE = R++ -src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))' - -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. - -var BUILDIDENTIFIER = R++ -src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+' - -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. - -var BUILD = R++ -src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + - '(?:\\.' + src[BUILDIDENTIFIER] + ')*))' - -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. - -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. - -var FULL = R++ -var FULLPLAIN = 'v?' + src[MAINVERSION] + - src[PRERELEASE] + '?' + - src[BUILD] + '?' - -src[FULL] = '^' + FULLPLAIN + '$' - -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + - src[PRERELEASELOOSE] + '?' + - src[BUILD] + '?' - -var LOOSE = R++ -src[LOOSE] = '^' + LOOSEPLAIN + '$' - -var GTLT = R++ -src[GTLT] = '((?:<|>)?=?)' - -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -var XRANGEIDENTIFIERLOOSE = R++ -src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' -var XRANGEIDENTIFIER = R++ -src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*' - -var XRANGEPLAIN = R++ -src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:' + src[PRERELEASE] + ')?' + - src[BUILD] + '?' + - ')?)?' - -var XRANGEPLAINLOOSE = R++ -src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:' + src[PRERELEASELOOSE] + ')?' + - src[BUILD] + '?' + - ')?)?' - -var XRANGE = R++ -src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$' -var XRANGELOOSE = R++ -src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$' - -// Coercion. -// Extract anything that could conceivably be a part of a valid semver -var COERCE = R++ -src[COERCE] = '(?:^|[^\\d])' + - '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:$|[^\\d])' - -// Tilde ranges. -// Meaning is "reasonably at or greater than" -var LONETILDE = R++ -src[LONETILDE] = '(?:~>?)' - -var TILDETRIM = R++ -src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+' -re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g') -var tildeTrimReplace = '$1~' - -var TILDE = R++ -src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$' -var TILDELOOSE = R++ -src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$' - -// Caret ranges. -// Meaning is "at least and backwards compatible with" -var LONECARET = R++ -src[LONECARET] = '(?:\\^)' - -var CARETTRIM = R++ -src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+' -re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g') -var caretTrimReplace = '$1^' - -var CARET = R++ -src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$' -var CARETLOOSE = R++ -src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$' - -// A simple gt/lt/eq thing, or just "" to indicate "any version" -var COMPARATORLOOSE = R++ -src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$' -var COMPARATOR = R++ -src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$' - -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -var COMPARATORTRIM = R++ -src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + - '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')' - -// this one has to use the /g flag -re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g') -var comparatorTrimReplace = '$1$2$3' - -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -var HYPHENRANGE = R++ -src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAIN] + ')' + - '\\s*$' - -var HYPHENRANGELOOSE = R++ -src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s*$' - -// Star ranges basically just allow anything at all. -var STAR = R++ -src[STAR] = '(<|>)?=?\\s*\\*' - -// Compile to actual regexp objects. -// All are flag-free, unless they were created above with a flag. -for (var i = 0; i < R; i++) { - debug(i, src[i]) - if (!re[i]) { - re[i] = new RegExp(src[i]) - } -} - -exports.parse = parse -function parse (version, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (version instanceof SemVer) { - return version - } - - if (typeof version !== 'string') { - return null - } - - if (version.length > MAX_LENGTH) { - return null - } - - var r = options.loose ? re[LOOSE] : re[FULL] - if (!r.test(version)) { - return null - } - - try { - return new SemVer(version, options) - } catch (er) { - return null - } -} - -exports.valid = valid -function valid (version, options) { - var v = parse(version, options) - return v ? v.version : null -} - -exports.clean = clean -function clean (version, options) { - var s = parse(version.trim().replace(/^[=v]+/, ''), options) - return s ? s.version : null -} - -exports.SemVer = SemVer - -function SemVer (version, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - if (version instanceof SemVer) { - if (version.loose === options.loose) { - return version - } else { - version = version.version - } - } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version) - } - - if (version.length > MAX_LENGTH) { - throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') - } - - if (!(this instanceof SemVer)) { - return new SemVer(version, options) - } - - debug('SemVer', version, options) - this.options = options - this.loose = !!options.loose - - var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]) - - if (!m) { - throw new TypeError('Invalid Version: ' + version) - } - - this.raw = version - - // these are actually numbers - this.major = +m[1] - this.minor = +m[2] - this.patch = +m[3] - - if (this.major > MAX_SAFE_INTEGER || this.major < 0) { - throw new TypeError('Invalid major version') - } - - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { - throw new TypeError('Invalid minor version') - } - - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { - throw new TypeError('Invalid patch version') - } - - // numberify any prerelease numeric ids - if (!m[4]) { - this.prerelease = [] - } else { - this.prerelease = m[4].split('.').map(function (id) { - if (/^[0-9]+$/.test(id)) { - var num = +id - if (num >= 0 && num < MAX_SAFE_INTEGER) { - return num - } - } - return id - }) - } - - this.build = m[5] ? m[5].split('.') : [] - this.format() -} - -SemVer.prototype.format = function () { - this.version = this.major + '.' + this.minor + '.' + this.patch - if (this.prerelease.length) { - this.version += '-' + this.prerelease.join('.') - } - return this.version -} - -SemVer.prototype.toString = function () { - return this.version -} - -SemVer.prototype.compare = function (other) { - debug('SemVer.compare', this.version, this.options, other) - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - return this.compareMain(other) || this.comparePre(other) -} - -SemVer.prototype.compareMain = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - return compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch) -} - -SemVer.prototype.comparePre = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) { - return -1 - } else if (!this.prerelease.length && other.prerelease.length) { - return 1 - } else if (!this.prerelease.length && !other.prerelease.length) { - return 0 - } - - var i = 0 - do { - var a = this.prerelease[i] - var b = other.prerelease[i] - debug('prerelease compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) -} - -// preminor will bump the version up to the next minor release, and immediately -// down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function (release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0 - this.patch = 0 - this.minor = 0 - this.major++ - this.inc('pre', identifier) - break - case 'preminor': - this.prerelease.length = 0 - this.patch = 0 - this.minor++ - this.inc('pre', identifier) - break - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0 - this.inc('patch', identifier) - this.inc('pre', identifier) - break - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) { - this.inc('patch', identifier) - } - this.inc('pre', identifier) - break - - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || - this.patch !== 0 || - this.prerelease.length === 0) { - this.major++ - } - this.minor = 0 - this.patch = 0 - this.prerelease = [] - break - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) { - this.minor++ - } - this.patch = 0 - this.prerelease = [] - break - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) { - this.patch++ - } - this.prerelease = [] - break - // This probably shouldn't be used publicly. - // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) { - this.prerelease = [0] - } else { - var i = this.prerelease.length - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++ - i = -2 - } - } - if (i === -1) { - // didn't increment anything - this.prerelease.push(0) - } - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) { - this.prerelease = [identifier, 0] - } - } else { - this.prerelease = [identifier, 0] - } - } - break - - default: - throw new Error('invalid increment argument: ' + release) - } - this.format() - this.raw = this.version - return this -} - -exports.inc = inc -function inc (version, release, loose, identifier) { - if (typeof (loose) === 'string') { - identifier = loose - loose = undefined - } - - try { - return new SemVer(version, loose).inc(release, identifier).version - } catch (er) { - return null - } -} - -exports.diff = diff -function diff (version1, version2) { - if (eq(version1, version2)) { - return null - } else { - var v1 = parse(version1) - var v2 = parse(version2) - var prefix = '' - if (v1.prerelease.length || v2.prerelease.length) { - prefix = 'pre' - var defaultResult = 'prerelease' - } - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return prefix + key - } - } - } - return defaultResult // may be undefined - } -} - -exports.compareIdentifiers = compareIdentifiers - -var numeric = /^[0-9]+$/ -function compareIdentifiers (a, b) { - var anum = numeric.test(a) - var bnum = numeric.test(b) - - if (anum && bnum) { - a = +a - b = +b - } - - return a === b ? 0 - : (anum && !bnum) ? -1 - : (bnum && !anum) ? 1 - : a < b ? -1 - : 1 -} - -exports.rcompareIdentifiers = rcompareIdentifiers -function rcompareIdentifiers (a, b) { - return compareIdentifiers(b, a) -} - -exports.major = major -function major (a, loose) { - return new SemVer(a, loose).major -} - -exports.minor = minor -function minor (a, loose) { - return new SemVer(a, loose).minor -} - -exports.patch = patch -function patch (a, loose) { - return new SemVer(a, loose).patch -} - -exports.compare = compare -function compare (a, b, loose) { - return new SemVer(a, loose).compare(new SemVer(b, loose)) -} - -exports.compareLoose = compareLoose -function compareLoose (a, b) { - return compare(a, b, true) -} - -exports.rcompare = rcompare -function rcompare (a, b, loose) { - return compare(b, a, loose) -} - -exports.sort = sort -function sort (list, loose) { - return list.sort(function (a, b) { - return exports.compare(a, b, loose) - }) -} - -exports.rsort = rsort -function rsort (list, loose) { - return list.sort(function (a, b) { - return exports.rcompare(a, b, loose) - }) -} - -exports.gt = gt -function gt (a, b, loose) { - return compare(a, b, loose) > 0 -} - -exports.lt = lt -function lt (a, b, loose) { - return compare(a, b, loose) < 0 -} - -exports.eq = eq -function eq (a, b, loose) { - return compare(a, b, loose) === 0 -} - -exports.neq = neq -function neq (a, b, loose) { - return compare(a, b, loose) !== 0 -} - -exports.gte = gte -function gte (a, b, loose) { - return compare(a, b, loose) >= 0 -} - -exports.lte = lte -function lte (a, b, loose) { - return compare(a, b, loose) <= 0 -} - -exports.cmp = cmp -function cmp (a, op, b, loose) { - switch (op) { - case '===': - if (typeof a === 'object') - a = a.version - if (typeof b === 'object') - b = b.version - return a === b - - case '!==': - if (typeof a === 'object') - a = a.version - if (typeof b === 'object') - b = b.version - return a !== b - - case '': - case '=': - case '==': - return eq(a, b, loose) - - case '!=': - return neq(a, b, loose) - - case '>': - return gt(a, b, loose) - - case '>=': - return gte(a, b, loose) - - case '<': - return lt(a, b, loose) - - case '<=': - return lte(a, b, loose) - - default: - throw new TypeError('Invalid operator: ' + op) - } -} - -exports.Comparator = Comparator -function Comparator (comp, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (comp instanceof Comparator) { - if (comp.loose === !!options.loose) { - return comp - } else { - comp = comp.value - } - } - - if (!(this instanceof Comparator)) { - return new Comparator(comp, options) - } - - debug('comparator', comp, options) - this.options = options - this.loose = !!options.loose - this.parse(comp) - - if (this.semver === ANY) { - this.value = '' - } else { - this.value = this.operator + this.semver.version - } - - debug('comp', this) -} - -var ANY = {} -Comparator.prototype.parse = function (comp) { - var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR] - var m = comp.match(r) - - if (!m) { - throw new TypeError('Invalid comparator: ' + comp) - } - - this.operator = m[1] - if (this.operator === '=') { - this.operator = '' - } - - // if it literally is just '>' or '' then allow anything. - if (!m[2]) { - this.semver = ANY - } else { - this.semver = new SemVer(m[2], this.options.loose) - } -} - -Comparator.prototype.toString = function () { - return this.value -} - -Comparator.prototype.test = function (version) { - debug('Comparator.test', version, this.options.loose) - - if (this.semver === ANY) { - return true - } - - if (typeof version === 'string') { - version = new SemVer(version, this.options) - } - - return cmp(version, this.operator, this.semver, this.options) -} - -Comparator.prototype.intersects = function (comp, options) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required') - } - - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - var rangeTmp - - if (this.operator === '') { - rangeTmp = new Range(comp.value, options) - return satisfies(this.value, rangeTmp, options) - } else if (comp.operator === '') { - rangeTmp = new Range(this.value, options) - return satisfies(comp.semver, rangeTmp, options) - } - - var sameDirectionIncreasing = - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>') - var sameDirectionDecreasing = - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<') - var sameSemVer = this.semver.version === comp.semver.version - var differentDirectionsInclusive = - (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<=') - var oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, options) && - ((this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<')) - var oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, options) && - ((this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>')) - - return sameDirectionIncreasing || sameDirectionDecreasing || - (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || oppositeDirectionsGreaterThan -} - -exports.Range = Range -function Range (range, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (range instanceof Range) { - if (range.loose === !!options.loose && - range.includePrerelease === !!options.includePrerelease) { - return range - } else { - return new Range(range.raw, options) - } - } - - if (range instanceof Comparator) { - return new Range(range.value, options) - } - - if (!(this instanceof Range)) { - return new Range(range, options) - } - - this.options = options - this.loose = !!options.loose - this.includePrerelease = !!options.includePrerelease - - // First, split based on boolean or || - this.raw = range - this.set = range.split(/\s*\|\|\s*/).map(function (range) { - return this.parseRange(range.trim()) - }, this).filter(function (c) { - // throw out any that are not relevant for whatever reason - return c.length - }) - - if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range) - } - - this.format() -} - -Range.prototype.format = function () { - this.range = this.set.map(function (comps) { - return comps.join(' ').trim() - }).join('||').trim() - return this.range -} - -Range.prototype.toString = function () { - return this.range -} - -Range.prototype.parseRange = function (range) { - var loose = this.options.loose - range = range.trim() - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE] - range = range.replace(hr, hyphenReplace) - debug('hyphen replace', range) - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace) - debug('comparator trim', range, re[COMPARATORTRIM]) - - // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[TILDETRIM], tildeTrimReplace) - - // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[CARETTRIM], caretTrimReplace) - - // normalize spaces - range = range.split(/\s+/).join(' ') - - // At this point, the range is completely trimmed and - // ready to be split into comparators. - - var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR] - var set = range.split(' ').map(function (comp) { - return parseComparator(comp, this.options) - }, this).join(' ').split(/\s+/) - if (this.options.loose) { - // in loose mode, throw out any that are not valid comparators - set = set.filter(function (comp) { - return !!comp.match(compRe) - }) - } - set = set.map(function (comp) { - return new Comparator(comp, this.options) - }, this) - - return set -} - -Range.prototype.intersects = function (range, options) { - if (!(range instanceof Range)) { - throw new TypeError('a Range is required') - } - - return this.set.some(function (thisComparators) { - return thisComparators.every(function (thisComparator) { - return range.set.some(function (rangeComparators) { - return rangeComparators.every(function (rangeComparator) { - return thisComparator.intersects(rangeComparator, options) - }) - }) - }) - }) -} - -// Mostly just for testing and legacy API reasons -exports.toComparators = toComparators -function toComparators (range, options) { - return new Range(range, options).set.map(function (comp) { - return comp.map(function (c) { - return c.value - }).join(' ').trim().split(' ') - }) -} - -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -function parseComparator (comp, options) { - debug('comp', comp, options) - comp = replaceCarets(comp, options) - debug('caret', comp) - comp = replaceTildes(comp, options) - debug('tildes', comp) - comp = replaceXRanges(comp, options) - debug('xrange', comp) - comp = replaceStars(comp, options) - debug('stars', comp) - return comp -} - -function isX (id) { - return !id || id.toLowerCase() === 'x' || id === '*' -} - -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes (comp, options) { - return comp.trim().split(/\s+/).map(function (comp) { - return replaceTilde(comp, options) - }).join(' ') -} - -function replaceTilde (comp, options) { - var r = options.loose ? re[TILDELOOSE] : re[TILDE] - return comp.replace(r, function (_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr) - var ret - - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (isX(p)) { - // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } else if (pr) { - debug('replaceTilde pr', pr) - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + (+m + 1) + '.0' - } else { - // ~1.2.3 == >=1.2.3 <1.3.0 - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0' - } - - debug('tilde return', ret) - return ret - }) -} - -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 -// ^1.2.3 --> >=1.2.3 <2.0.0 -// ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets (comp, options) { - return comp.trim().split(/\s+/).map(function (comp) { - return replaceCaret(comp, options) - }).join(' ') -} - -function replaceCaret (comp, options) { - debug('caret', comp, options) - var r = options.loose ? re[CARETLOOSE] : re[CARET] - return comp.replace(r, function (_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr) - var ret - - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (isX(p)) { - if (M === '0') { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } else { - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' - } - } else if (pr) { - debug('replaceCaret pr', pr) - if (M === '0') { - if (m === '0') { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + m + '.' + (+p + 1) - } else { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + (+m + 1) + '.0' - } - } else { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + (+M + 1) + '.0.0' - } - } else { - debug('no pr') - if (M === '0') { - if (m === '0') { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1) - } else { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0' - } - } else { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0' - } - } - - debug('caret return', ret) - return ret - }) -} - -function replaceXRanges (comp, options) { - debug('replaceXRanges', comp, options) - return comp.split(/\s+/).map(function (comp) { - return replaceXRange(comp, options) - }).join(' ') -} - -function replaceXRange (comp, options) { - comp = comp.trim() - var r = options.loose ? re[XRANGELOOSE] : re[XRANGE] - return comp.replace(r, function (ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr) - var xM = isX(M) - var xm = xM || isX(m) - var xp = xm || isX(p) - var anyX = xp - - if (gtlt === '=' && anyX) { - gtlt = '' - } - - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0' - } else { - // nothing is forbidden - ret = '*' - } - } else if (gtlt && anyX) { - // we know patch is an x, because we have any x at all. - // replace X with 0 - if (xm) { - m = 0 - } - p = 0 - - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - // >1.2.3 => >= 1.2.4 - gtlt = '>=' - if (xm) { - M = +M + 1 - m = 0 - p = 0 - } else { - m = +m + 1 - p = 0 - } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<' - if (xm) { - M = +M + 1 - } else { - m = +m + 1 - } - } - - ret = gtlt + M + '.' + m + '.' + p - } else if (xm) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (xp) { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } - - debug('xRange return', ret) - - return ret - }) -} - -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -function replaceStars (comp, options) { - debug('replaceStars', comp, options) - // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[STAR], '') -} - -// This function is passed to string.replace(re[HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace ($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { - if (isX(fM)) { - from = '' - } else if (isX(fm)) { - from = '>=' + fM + '.0.0' - } else if (isX(fp)) { - from = '>=' + fM + '.' + fm + '.0' - } else { - from = '>=' + from - } - - if (isX(tM)) { - to = '' - } else if (isX(tm)) { - to = '<' + (+tM + 1) + '.0.0' - } else if (isX(tp)) { - to = '<' + tM + '.' + (+tm + 1) + '.0' - } else if (tpr) { - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr - } else { - to = '<=' + to - } - - return (from + ' ' + to).trim() -} - -// if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function (version) { - if (!version) { - return false - } - - if (typeof version === 'string') { - version = new SemVer(version, this.options) - } - - for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version, this.options)) { - return true - } - } - return false -} - -function testSet (set, version, options) { - for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) { - return false - } - } - - if (version.prerelease.length && !options.includePrerelease) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (i = 0; i < set.length; i++) { - debug(set[i].semver) - if (set[i].semver === ANY) { - continue - } - - if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) { - return true - } - } - } - - // Version has a -pre, but it's not one of the ones we like. - return false - } - - return true -} - -exports.satisfies = satisfies -function satisfies (version, range, options) { - try { - range = new Range(range, options) - } catch (er) { - return false - } - return range.test(version) -} - -exports.maxSatisfying = maxSatisfying -function maxSatisfying (versions, range, options) { - var max = null - var maxSV = null - try { - var rangeObj = new Range(range, options) - } catch (er) { - return null - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!max || maxSV.compare(v) === -1) { - // compare(max, v, true) - max = v - maxSV = new SemVer(max, options) - } - } - }) - return max -} - -exports.minSatisfying = minSatisfying -function minSatisfying (versions, range, options) { - var min = null - var minSV = null - try { - var rangeObj = new Range(range, options) - } catch (er) { - return null - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!min || minSV.compare(v) === 1) { - // compare(min, v, true) - min = v - minSV = new SemVer(min, options) - } - } - }) - return min -} + } -exports.minVersion = minVersion -function minVersion (range, loose) { - range = new Range(range, loose) + if (error.message.includes('null bytes')) { + throw error; + } - var minver = new SemVer('0.0.0') - if (range.test(minver)) { - return minver - } + return make(path.dirname(pth)).then(() => make(pth)); + } - minver = new SemVer('0.0.0-0') - if (range.test(minver)) { - return minver - } + return stat(pth) + .then(stats => stats.isDirectory() ? pth : Promise.reject()) + .catch(() => { + throw error; + }); + }); + }; - minver = null - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i] + return make(path.resolve(input)); +}); - comparators.forEach(function (comparator) { - // Clone to avoid manipulating the comparator's semver object. - var compver = new SemVer(comparator.semver.version) - switch (comparator.operator) { - case '>': - if (compver.prerelease.length === 0) { - compver.patch++ - } else { - compver.prerelease.push(0) - } - compver.raw = compver.format() - /* fallthrough */ - case '': - case '>=': - if (!minver || gt(minver, compver)) { - minver = compver - } - break - case '<': - case '<=': - /* Ignore maximum versions */ - break - /* istanbul ignore next */ - default: - throw new Error('Unexpected operation: ' + comparator.operator) - } - }) - } +module.exports = makeDir; +module.exports.default = makeDir; - if (minver && range.test(minver)) { - return minver - } +module.exports.sync = (input, options) => { + checkPath(input); + options = Object.assign({}, defaults, options); - return null -} + if (useNativeRecursiveOption && options.fs.mkdirSync === fs.mkdirSync) { + const pth = path.resolve(input); -exports.validRange = validRange -function validRange (range, options) { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range(range, options).range || '*' - } catch (er) { - return null - } -} + fs.mkdirSync(pth, { + mode: options.mode, + recursive: true + }); -// Determine if version is less than all the versions possible in the range -exports.ltr = ltr -function ltr (version, range, options) { - return outside(version, range, '<', options) -} + return pth; + } -// Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr -function gtr (version, range, options) { - return outside(version, range, '>', options) -} + const make = pth => { + try { + options.fs.mkdirSync(pth, options.mode); + } catch (error) { + if (error.code === 'EPERM') { + throw error; + } -exports.outside = outside -function outside (version, range, hilo, options) { - version = new SemVer(version, options) - range = new Range(range, options) + if (error.code === 'ENOENT') { + if (path.dirname(pth) === pth) { + throw permissionError(pth); + } - var gtfn, ltefn, ltfn, comp, ecomp - switch (hilo) { - case '>': - gtfn = gt - ltefn = lte - ltfn = lt - comp = '>' - ecomp = '>=' - break - case '<': - gtfn = lt - ltefn = gte - ltfn = gt - comp = '<' - ecomp = '<=' - break - default: - throw new TypeError('Must provide a hilo val of "<" or ">"') - } + if (error.message.includes('null bytes')) { + throw error; + } - // If it satisifes the range it is not outside - if (satisfies(version, range, options)) { - return false - } + make(path.dirname(pth)); + return make(pth); + } - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. + try { + if (!options.fs.statSync(pth).isDirectory()) { + throw new Error('The path is not a directory'); + } + } catch (_) { + throw error; + } + } - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i] + return pth; + }; - var high = null - var low = null + return make(path.resolve(input)); +}; - comparators.forEach(function (comparator) { - if (comparator.semver === ANY) { - comparator = new Comparator('>=0.0.0') - } - high = high || comparator - low = low || comparator - if (gtfn(comparator.semver, high.semver, options)) { - high = comparator - } else if (ltfn(comparator.semver, low.semver, options)) { - low = comparator - } - }) - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false - } +/***/ }), +/* 560 */ +/***/ (function(module, exports, __webpack_require__) { - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false - } - } - return true -} +"use strict"; -exports.prerelease = prerelease -function prerelease (version, options) { - var parsed = parse(version, options) - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null -} -exports.intersects = intersects -function intersects (r1, r2, options) { - r1 = new Range(r1, options) - r2 = new Range(r2, options) - return r1.intersects(r2) -} +const processFn = (fn, options) => function (...args) { + const P = options.promiseModule; -exports.coerce = coerce -function coerce (version) { - if (version instanceof SemVer) { - return version - } + return new P((resolve, reject) => { + if (options.multiArgs) { + args.push((...result) => { + if (options.errorFirst) { + if (result[0]) { + reject(result); + } else { + result.shift(); + resolve(result); + } + } else { + resolve(result); + } + }); + } else if (options.errorFirst) { + args.push((error, result) => { + if (error) { + reject(error); + } else { + resolve(result); + } + }); + } else { + args.push(resolve); + } - if (typeof version !== 'string') { - return null - } + fn.apply(this, args); + }); +}; - var match = version.match(re[COERCE]) +module.exports = (input, options) => { + options = Object.assign({ + exclude: [/.+(Sync|Stream)$/], + errorFirst: true, + promiseModule: Promise + }, options); - if (match == null) { - return null - } + const objType = typeof input; + if (!(input !== null && (objType === 'object' || objType === 'function'))) { + throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); + } - return parse(match[1] + - '.' + (match[2] || '0') + - '.' + (match[3] || '0')) -} + const filter = key => { + const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); + return options.include ? options.include.some(match) : !options.exclude.some(match); + }; + + let ret; + if (objType === 'function') { + ret = function (...args) { + return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); + }; + } else { + ret = Object.create(Object.getPrototypeOf(input)); + } + + for (const key in input) { // eslint-disable-line guard-for-in + const property = input[key]; + ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; + } + + return ret; +}; /***/ }), -/* 562 */ +/* 561 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56384,7 +55082,7 @@ module.exports = (input, options) => { /***/ }), -/* 563 */ +/* 562 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56513,7 +55211,7 @@ module.exports = str => { /***/ }), -/* 564 */ +/* 563 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56522,7 +55220,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackage", function() { return runScriptInPackage; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackageStreaming", function() { return runScriptInPackageStreaming; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "yarnWorkspacesInfo", function() { return yarnWorkspacesInfo; }); -/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(565); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(564); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -56592,7 +55290,7 @@ async function yarnWorkspacesInfo(directory) { } /***/ }), -/* 565 */ +/* 564 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56603,9 +55301,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(351); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(566); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(565); /* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(log_symbols__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(571); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(570); /* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } @@ -56671,12 +55369,12 @@ function spawnStreaming(command, args, opts, { } /***/ }), -/* 566 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(567); +const chalk = __webpack_require__(566); const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; @@ -56698,16 +55396,16 @@ module.exports = isSupported ? main : fallbacks; /***/ }), -/* 567 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(568); -const stdoutColor = __webpack_require__(569).stdout; +const ansiStyles = __webpack_require__(567); +const stdoutColor = __webpack_require__(568).stdout; -const template = __webpack_require__(570); +const template = __webpack_require__(569); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -56933,7 +55631,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 568 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57106,7 +55804,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 569 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57248,7 +55946,7 @@ module.exports = { /***/ }), -/* 570 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57383,7 +56081,7 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 571 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { // Copyright IBM Corp. 2014,2018. All Rights Reserved. @@ -57391,12 +56089,12 @@ module.exports = (chalk, tmp) => { // This file is licensed under the Apache License 2.0. // License text available at https://opensource.org/licenses/Apache-2.0 -module.exports = __webpack_require__(572); -module.exports.cli = __webpack_require__(576); +module.exports = __webpack_require__(571); +module.exports.cli = __webpack_require__(575); /***/ }), -/* 572 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57411,9 +56109,9 @@ var stream = __webpack_require__(27); var util = __webpack_require__(29); var fs = __webpack_require__(23); -var through = __webpack_require__(573); -var duplexer = __webpack_require__(574); -var StringDecoder = __webpack_require__(575).StringDecoder; +var through = __webpack_require__(572); +var duplexer = __webpack_require__(573); +var StringDecoder = __webpack_require__(574).StringDecoder; module.exports = Logger; @@ -57602,7 +56300,7 @@ function lineMerger(host) { /***/ }), -/* 573 */ +/* 572 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(27) @@ -57716,7 +56414,7 @@ function through (write, end, opts) { /***/ }), -/* 574 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(27) @@ -57809,13 +56507,13 @@ function duplex(writer, reader) { /***/ }), -/* 575 */ +/* 574 */ /***/ (function(module, exports) { module.exports = require("string_decoder"); /***/ }), -/* 576 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57826,11 +56524,11 @@ module.exports = require("string_decoder"); -var minimist = __webpack_require__(577); +var minimist = __webpack_require__(576); var path = __webpack_require__(16); -var Logger = __webpack_require__(572); -var pkg = __webpack_require__(578); +var Logger = __webpack_require__(571); +var pkg = __webpack_require__(577); module.exports = cli; @@ -57884,7 +56582,7 @@ function usage($0, p) { /***/ }), -/* 577 */ +/* 576 */ /***/ (function(module, exports) { module.exports = function (args, opts) { @@ -58126,13 +56824,13 @@ function isNumber (x) { /***/ }), -/* 578 */ +/* 577 */ /***/ (function(module) { module.exports = JSON.parse("{\"name\":\"strong-log-transformer\",\"version\":\"2.1.0\",\"description\":\"Stream transformer that prefixes lines with timestamps and other things.\",\"author\":\"Ryan Graham \",\"license\":\"Apache-2.0\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/strongloop/strong-log-transformer\"},\"keywords\":[\"logging\",\"streams\"],\"bugs\":{\"url\":\"https://github.com/strongloop/strong-log-transformer/issues\"},\"homepage\":\"https://github.com/strongloop/strong-log-transformer\",\"directories\":{\"test\":\"test\"},\"bin\":{\"sl-log-transformer\":\"bin/sl-log-transformer.js\"},\"main\":\"index.js\",\"scripts\":{\"test\":\"tap --100 test/test-*\"},\"dependencies\":{\"duplexer\":\"^0.1.1\",\"minimist\":\"^1.2.0\",\"through\":\"^2.3.4\"},\"devDependencies\":{\"tap\":\"^12.0.1\"},\"engines\":{\"node\":\">=4\"}}"); /***/ }), -/* 579 */ +/* 578 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58145,7 +56843,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(580); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579); /* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); /* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(517); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(501); @@ -58240,7 +56938,7 @@ function packagesFromGlobPattern({ } /***/ }), -/* 580 */ +/* 579 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58309,7 +57007,7 @@ function getProjectPaths({ } /***/ }), -/* 581 */ +/* 580 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58317,13 +57015,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getAllChecksums", function() { return getAllChecksums; }); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(23); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(582); +/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(581); /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(351); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(583); +/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(582); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -58540,19 +57238,19 @@ async function getAllChecksums(kbn, log) { } /***/ }), -/* 582 */ +/* 581 */ /***/ (function(module, exports) { module.exports = require("crypto"); /***/ }), -/* 583 */ +/* 582 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readYarnLock", function() { return readYarnLock; }); -/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(584); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(583); /* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); /* @@ -58596,7 +57294,7 @@ async function readYarnLock(kbn) { } /***/ }), -/* 584 */ +/* 583 */ /***/ (function(module, exports, __webpack_require__) { module.exports = @@ -60155,7 +58853,7 @@ module.exports = invariant; /* 9 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(582); +module.exports = __webpack_require__(581); /***/ }), /* 10 */, @@ -62479,7 +61177,7 @@ function onceStrict (fn) { /* 63 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(585); +module.exports = __webpack_require__(584); /***/ }), /* 64 */, @@ -68874,13 +67572,13 @@ module.exports = process && support(supportLevel); /******/ ]); /***/ }), -/* 585 */ +/* 584 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 586 */ +/* 585 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -68977,7 +67675,7 @@ class BootstrapCacheFile { } /***/ }), -/* 587 */ +/* 586 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -68985,9 +67683,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(588); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(587); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(676); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(675); /* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); @@ -69087,21 +67785,21 @@ const CleanCommand = { }; /***/ }), -/* 588 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const path = __webpack_require__(16); -const globby = __webpack_require__(589); -const isGlob = __webpack_require__(606); -const slash = __webpack_require__(667); +const globby = __webpack_require__(588); +const isGlob = __webpack_require__(605); +const slash = __webpack_require__(666); const gracefulFs = __webpack_require__(22); -const isPathCwd = __webpack_require__(669); -const isPathInside = __webpack_require__(670); -const rimraf = __webpack_require__(671); -const pMap = __webpack_require__(672); +const isPathCwd = __webpack_require__(668); +const isPathInside = __webpack_require__(669); +const rimraf = __webpack_require__(670); +const pMap = __webpack_require__(671); const rimrafP = promisify(rimraf); @@ -69215,19 +67913,19 @@ module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options /***/ }), -/* 589 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(590); -const merge2 = __webpack_require__(591); -const glob = __webpack_require__(592); -const fastGlob = __webpack_require__(597); -const dirGlob = __webpack_require__(663); -const gitignore = __webpack_require__(665); -const {FilterStream, UniqueStream} = __webpack_require__(668); +const arrayUnion = __webpack_require__(589); +const merge2 = __webpack_require__(590); +const glob = __webpack_require__(591); +const fastGlob = __webpack_require__(596); +const dirGlob = __webpack_require__(662); +const gitignore = __webpack_require__(664); +const {FilterStream, UniqueStream} = __webpack_require__(667); const DEFAULT_FILTER = () => false; @@ -69400,7 +68098,7 @@ module.exports.gitignore = gitignore; /***/ }), -/* 590 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69412,7 +68110,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 591 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69526,7 +68224,7 @@ function pauseStreams (streams, options) { /***/ }), -/* 592 */ +/* 591 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -69575,13 +68273,13 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(503) var minimatch = __webpack_require__(505) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(593) +var inherits = __webpack_require__(592) var EE = __webpack_require__(379).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(511) -var globSync = __webpack_require__(595) -var common = __webpack_require__(596) +var globSync = __webpack_require__(594) +var common = __webpack_require__(595) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -70322,7 +69020,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 593 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -70332,12 +69030,12 @@ try { module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(594); + module.exports = __webpack_require__(593); } /***/ }), -/* 594 */ +/* 593 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -70370,7 +69068,7 @@ if (typeof Object.create === 'function') { /***/ }), -/* 595 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync @@ -70380,12 +69078,12 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(503) var minimatch = __webpack_require__(505) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(592).Glob +var Glob = __webpack_require__(591).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(511) -var common = __webpack_require__(596) +var common = __webpack_require__(595) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -70862,7 +69560,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 596 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -71108,17 +69806,17 @@ function childrenIgnored (self, path) { /***/ }), -/* 597 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const taskManager = __webpack_require__(598); -const async_1 = __webpack_require__(626); -const stream_1 = __webpack_require__(659); -const sync_1 = __webpack_require__(660); -const settings_1 = __webpack_require__(662); -const utils = __webpack_require__(599); +const taskManager = __webpack_require__(597); +const async_1 = __webpack_require__(625); +const stream_1 = __webpack_require__(658); +const sync_1 = __webpack_require__(659); +const settings_1 = __webpack_require__(661); +const utils = __webpack_require__(598); function FastGlob(source, options) { try { assertPatternsInput(source); @@ -71176,13 +69874,13 @@ module.exports = FastGlob; /***/ }), -/* 598 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(599); +const utils = __webpack_require__(598); function generate(patterns, settings) { const positivePatterns = getPositivePatterns(patterns); const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); @@ -71250,28 +69948,28 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 599 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const array = __webpack_require__(600); +const array = __webpack_require__(599); exports.array = array; -const errno = __webpack_require__(601); +const errno = __webpack_require__(600); exports.errno = errno; -const fs = __webpack_require__(602); +const fs = __webpack_require__(601); exports.fs = fs; -const path = __webpack_require__(603); +const path = __webpack_require__(602); exports.path = path; -const pattern = __webpack_require__(604); +const pattern = __webpack_require__(603); exports.pattern = pattern; -const stream = __webpack_require__(625); +const stream = __webpack_require__(624); exports.stream = stream; /***/ }), -/* 600 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71284,7 +69982,7 @@ exports.flatten = flatten; /***/ }), -/* 601 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71297,7 +69995,7 @@ exports.isEnoentCodeError = isEnoentCodeError; /***/ }), -/* 602 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71322,7 +70020,7 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 603 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71343,16 +70041,16 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 604 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const globParent = __webpack_require__(605); -const isGlob = __webpack_require__(606); -const micromatch = __webpack_require__(608); +const globParent = __webpack_require__(604); +const isGlob = __webpack_require__(605); +const micromatch = __webpack_require__(607); const GLOBSTAR = '**'; function isStaticPattern(pattern) { return !isDynamicPattern(pattern); @@ -71441,13 +70139,13 @@ exports.matchAny = matchAny; /***/ }), -/* 605 */ +/* 604 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isGlob = __webpack_require__(606); +var isGlob = __webpack_require__(605); var pathPosixDirname = __webpack_require__(16).posix.dirname; var isWin32 = __webpack_require__(11).platform() === 'win32'; @@ -71482,7 +70180,7 @@ module.exports = function globParent(str) { /***/ }), -/* 606 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -71492,7 +70190,7 @@ module.exports = function globParent(str) { * Released under the MIT License. */ -var isExtglob = __webpack_require__(607); +var isExtglob = __webpack_require__(606); var chars = { '{': '}', '(': ')', '[': ']'}; var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; @@ -71536,7 +70234,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 607 */ +/* 606 */ /***/ (function(module, exports) { /*! @@ -71562,16 +70260,16 @@ module.exports = function isExtglob(str) { /***/ }), -/* 608 */ +/* 607 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const util = __webpack_require__(29); -const braces = __webpack_require__(609); -const picomatch = __webpack_require__(619); -const utils = __webpack_require__(622); +const braces = __webpack_require__(608); +const picomatch = __webpack_require__(618); +const utils = __webpack_require__(621); const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); /** @@ -72036,16 +70734,16 @@ module.exports = micromatch; /***/ }), -/* 609 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(610); -const compile = __webpack_require__(612); -const expand = __webpack_require__(616); -const parse = __webpack_require__(617); +const stringify = __webpack_require__(609); +const compile = __webpack_require__(611); +const expand = __webpack_require__(615); +const parse = __webpack_require__(616); /** * Expand the given pattern or create a regex-compatible string. @@ -72213,13 +70911,13 @@ module.exports = braces; /***/ }), -/* 610 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(611); +const utils = __webpack_require__(610); module.exports = (ast, options = {}) => { let stringify = (node, parent = {}) => { @@ -72252,7 +70950,7 @@ module.exports = (ast, options = {}) => { /***/ }), -/* 611 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72371,14 +71069,14 @@ exports.flatten = (...args) => { /***/ }), -/* 612 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fill = __webpack_require__(613); -const utils = __webpack_require__(611); +const fill = __webpack_require__(612); +const utils = __webpack_require__(610); const compile = (ast, options = {}) => { let walk = (node, parent = {}) => { @@ -72435,7 +71133,7 @@ module.exports = compile; /***/ }), -/* 613 */ +/* 612 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72449,7 +71147,7 @@ module.exports = compile; const util = __webpack_require__(29); -const toRegexRange = __webpack_require__(614); +const toRegexRange = __webpack_require__(613); const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); @@ -72691,7 +71389,7 @@ module.exports = fill; /***/ }), -/* 614 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72704,7 +71402,7 @@ module.exports = fill; -const isNumber = __webpack_require__(615); +const isNumber = __webpack_require__(614); const toRegexRange = (min, max, options) => { if (isNumber(min) === false) { @@ -72986,7 +71684,7 @@ module.exports = toRegexRange; /***/ }), -/* 615 */ +/* 614 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73011,15 +71709,15 @@ module.exports = function(num) { /***/ }), -/* 616 */ +/* 615 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fill = __webpack_require__(613); -const stringify = __webpack_require__(610); -const utils = __webpack_require__(611); +const fill = __webpack_require__(612); +const stringify = __webpack_require__(609); +const utils = __webpack_require__(610); const append = (queue = '', stash = '', enclose = false) => { let result = []; @@ -73131,13 +71829,13 @@ module.exports = expand; /***/ }), -/* 617 */ +/* 616 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(610); +const stringify = __webpack_require__(609); /** * Constants @@ -73159,7 +71857,7 @@ const { CHAR_SINGLE_QUOTE, /* ' */ CHAR_NO_BREAK_SPACE, CHAR_ZERO_WIDTH_NOBREAK_SPACE -} = __webpack_require__(618); +} = __webpack_require__(617); /** * parse @@ -73471,7 +72169,7 @@ module.exports = parse; /***/ }), -/* 618 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73535,26 +72233,26 @@ module.exports = { /***/ }), -/* 619 */ +/* 618 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(620); +module.exports = __webpack_require__(619); /***/ }), -/* 620 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const scan = __webpack_require__(621); -const parse = __webpack_require__(624); -const utils = __webpack_require__(622); +const scan = __webpack_require__(620); +const parse = __webpack_require__(623); +const utils = __webpack_require__(621); /** * Creates a matcher function from one or more glob patterns. The @@ -73857,7 +72555,7 @@ picomatch.toRegex = (source, options) => { * @return {Object} */ -picomatch.constants = __webpack_require__(623); +picomatch.constants = __webpack_require__(622); /** * Expose "picomatch" @@ -73867,13 +72565,13 @@ module.exports = picomatch; /***/ }), -/* 621 */ +/* 620 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(622); +const utils = __webpack_require__(621); const { CHAR_ASTERISK, /* * */ @@ -73891,7 +72589,7 @@ const { CHAR_RIGHT_CURLY_BRACE, /* } */ CHAR_RIGHT_PARENTHESES, /* ) */ CHAR_RIGHT_SQUARE_BRACKET /* ] */ -} = __webpack_require__(623); +} = __webpack_require__(622); const isPathSeparator = code => { return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; @@ -74093,7 +72791,7 @@ module.exports = (input, options) => { /***/ }), -/* 622 */ +/* 621 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74105,7 +72803,7 @@ const { REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL, REGEX_REMOVE_BACKSLASH -} = __webpack_require__(623); +} = __webpack_require__(622); exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); @@ -74143,7 +72841,7 @@ exports.escapeLast = (input, char, lastIdx) => { /***/ }), -/* 623 */ +/* 622 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74329,14 +73027,14 @@ module.exports = { /***/ }), -/* 624 */ +/* 623 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(622); -const constants = __webpack_require__(623); +const utils = __webpack_require__(621); +const constants = __webpack_require__(622); /** * Constants @@ -75347,13 +74045,13 @@ module.exports = parse; /***/ }), -/* 625 */ +/* 624 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const merge2 = __webpack_require__(591); +const merge2 = __webpack_require__(590); function merge(streams) { const mergedStream = merge2(streams); streams.forEach((stream) => { @@ -75365,14 +74063,14 @@ exports.merge = merge; /***/ }), -/* 626 */ +/* 625 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(627); -const provider_1 = __webpack_require__(654); +const stream_1 = __webpack_require__(626); +const provider_1 = __webpack_require__(653); class ProviderAsync extends provider_1.default { constructor() { super(...arguments); @@ -75400,16 +74098,16 @@ exports.default = ProviderAsync; /***/ }), -/* 627 */ +/* 626 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const fsStat = __webpack_require__(628); -const fsWalk = __webpack_require__(633); -const reader_1 = __webpack_require__(653); +const fsStat = __webpack_require__(627); +const fsWalk = __webpack_require__(632); +const reader_1 = __webpack_require__(652); class ReaderStream extends reader_1.default { constructor() { super(...arguments); @@ -75462,15 +74160,15 @@ exports.default = ReaderStream; /***/ }), -/* 628 */ +/* 627 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(629); -const sync = __webpack_require__(630); -const settings_1 = __webpack_require__(631); +const async = __webpack_require__(628); +const sync = __webpack_require__(629); +const settings_1 = __webpack_require__(630); exports.Settings = settings_1.default; function stat(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -75493,7 +74191,7 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 629 */ +/* 628 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75531,7 +74229,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 630 */ +/* 629 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75560,13 +74258,13 @@ exports.read = read; /***/ }), -/* 631 */ +/* 630 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(632); +const fs = __webpack_require__(631); class Settings { constructor(_options = {}) { this._options = _options; @@ -75583,7 +74281,7 @@ exports.default = Settings; /***/ }), -/* 632 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75606,16 +74304,16 @@ exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 633 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(634); -const stream_1 = __webpack_require__(649); -const sync_1 = __webpack_require__(650); -const settings_1 = __webpack_require__(652); +const async_1 = __webpack_require__(633); +const stream_1 = __webpack_require__(648); +const sync_1 = __webpack_require__(649); +const settings_1 = __webpack_require__(651); exports.Settings = settings_1.default; function walk(dir, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -75645,13 +74343,13 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 634 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(635); +const async_1 = __webpack_require__(634); class AsyncProvider { constructor(_root, _settings) { this._root = _root; @@ -75682,17 +74380,17 @@ function callSuccessCallback(callback, entries) { /***/ }), -/* 635 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const events_1 = __webpack_require__(379); -const fsScandir = __webpack_require__(636); -const fastq = __webpack_require__(645); -const common = __webpack_require__(647); -const reader_1 = __webpack_require__(648); +const fsScandir = __webpack_require__(635); +const fastq = __webpack_require__(644); +const common = __webpack_require__(646); +const reader_1 = __webpack_require__(647); class AsyncReader extends reader_1.default { constructor(_root, _settings) { super(_root, _settings); @@ -75782,15 +74480,15 @@ exports.default = AsyncReader; /***/ }), -/* 636 */ +/* 635 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(637); -const sync = __webpack_require__(642); -const settings_1 = __webpack_require__(643); +const async = __webpack_require__(636); +const sync = __webpack_require__(641); +const settings_1 = __webpack_require__(642); exports.Settings = settings_1.default; function scandir(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -75813,16 +74511,16 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 637 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(628); -const rpl = __webpack_require__(638); -const constants_1 = __webpack_require__(639); -const utils = __webpack_require__(640); +const fsStat = __webpack_require__(627); +const rpl = __webpack_require__(637); +const constants_1 = __webpack_require__(638); +const utils = __webpack_require__(639); function read(dir, settings, callback) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { return readdirWithFileTypes(dir, settings, callback); @@ -75911,7 +74609,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 638 */ +/* 637 */ /***/ (function(module, exports) { module.exports = runParallel @@ -75965,7 +74663,7 @@ function runParallel (tasks, cb) { /***/ }), -/* 639 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75981,18 +74679,18 @@ exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = MAJOR_VERSION > 10 || (MAJOR_VERSIO /***/ }), -/* 640 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(641); +const fs = __webpack_require__(640); exports.fs = fs; /***/ }), -/* 641 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76017,15 +74715,15 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 642 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(628); -const constants_1 = __webpack_require__(639); -const utils = __webpack_require__(640); +const fsStat = __webpack_require__(627); +const constants_1 = __webpack_require__(638); +const utils = __webpack_require__(639); function read(dir, settings) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { return readdirWithFileTypes(dir, settings); @@ -76076,15 +74774,15 @@ exports.readdir = readdir; /***/ }), -/* 643 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsStat = __webpack_require__(628); -const fs = __webpack_require__(644); +const fsStat = __webpack_require__(627); +const fs = __webpack_require__(643); class Settings { constructor(_options = {}) { this._options = _options; @@ -76107,7 +74805,7 @@ exports.default = Settings; /***/ }), -/* 644 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76132,13 +74830,13 @@ exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 645 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var reusify = __webpack_require__(646) +var reusify = __webpack_require__(645) function fastqueue (context, worker, concurrency) { if (typeof context === 'function') { @@ -76312,7 +75010,7 @@ module.exports = fastqueue /***/ }), -/* 646 */ +/* 645 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76352,7 +75050,7 @@ module.exports = reusify /***/ }), -/* 647 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76383,13 +75081,13 @@ exports.joinPathSegments = joinPathSegments; /***/ }), -/* 648 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const common = __webpack_require__(647); +const common = __webpack_require__(646); class Reader { constructor(_root, _settings) { this._root = _root; @@ -76401,14 +75099,14 @@ exports.default = Reader; /***/ }), -/* 649 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const async_1 = __webpack_require__(635); +const async_1 = __webpack_require__(634); class StreamProvider { constructor(_root, _settings) { this._root = _root; @@ -76438,13 +75136,13 @@ exports.default = StreamProvider; /***/ }), -/* 650 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(651); +const sync_1 = __webpack_require__(650); class SyncProvider { constructor(_root, _settings) { this._root = _root; @@ -76459,15 +75157,15 @@ exports.default = SyncProvider; /***/ }), -/* 651 */ +/* 650 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsScandir = __webpack_require__(636); -const common = __webpack_require__(647); -const reader_1 = __webpack_require__(648); +const fsScandir = __webpack_require__(635); +const common = __webpack_require__(646); +const reader_1 = __webpack_require__(647); class SyncReader extends reader_1.default { constructor() { super(...arguments); @@ -76525,14 +75223,14 @@ exports.default = SyncReader; /***/ }), -/* 652 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsScandir = __webpack_require__(636); +const fsScandir = __webpack_require__(635); class Settings { constructor(_options = {}) { this._options = _options; @@ -76558,15 +75256,15 @@ exports.default = Settings; /***/ }), -/* 653 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsStat = __webpack_require__(628); -const utils = __webpack_require__(599); +const fsStat = __webpack_require__(627); +const utils = __webpack_require__(598); class Reader { constructor(_settings) { this._settings = _settings; @@ -76598,17 +75296,17 @@ exports.default = Reader; /***/ }), -/* 654 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const deep_1 = __webpack_require__(655); -const entry_1 = __webpack_require__(656); -const error_1 = __webpack_require__(657); -const entry_2 = __webpack_require__(658); +const deep_1 = __webpack_require__(654); +const entry_1 = __webpack_require__(655); +const error_1 = __webpack_require__(656); +const entry_2 = __webpack_require__(657); class Provider { constructor(_settings) { this._settings = _settings; @@ -76653,13 +75351,13 @@ exports.default = Provider; /***/ }), -/* 655 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(599); +const utils = __webpack_require__(598); class DeepFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -76719,13 +75417,13 @@ exports.default = DeepFilter; /***/ }), -/* 656 */ +/* 655 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(599); +const utils = __webpack_require__(598); class EntryFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -76780,13 +75478,13 @@ exports.default = EntryFilter; /***/ }), -/* 657 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(599); +const utils = __webpack_require__(598); class ErrorFilter { constructor(_settings) { this._settings = _settings; @@ -76802,13 +75500,13 @@ exports.default = ErrorFilter; /***/ }), -/* 658 */ +/* 657 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(599); +const utils = __webpack_require__(598); class EntryTransformer { constructor(_settings) { this._settings = _settings; @@ -76835,15 +75533,15 @@ exports.default = EntryTransformer; /***/ }), -/* 659 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const stream_2 = __webpack_require__(627); -const provider_1 = __webpack_require__(654); +const stream_2 = __webpack_require__(626); +const provider_1 = __webpack_require__(653); class ProviderStream extends provider_1.default { constructor() { super(...arguments); @@ -76871,14 +75569,14 @@ exports.default = ProviderStream; /***/ }), -/* 660 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(661); -const provider_1 = __webpack_require__(654); +const sync_1 = __webpack_require__(660); +const provider_1 = __webpack_require__(653); class ProviderSync extends provider_1.default { constructor() { super(...arguments); @@ -76901,15 +75599,15 @@ exports.default = ProviderSync; /***/ }), -/* 661 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(628); -const fsWalk = __webpack_require__(633); -const reader_1 = __webpack_require__(653); +const fsStat = __webpack_require__(627); +const fsWalk = __webpack_require__(632); +const reader_1 = __webpack_require__(652); class ReaderSync extends reader_1.default { constructor() { super(...arguments); @@ -76951,7 +75649,7 @@ exports.default = ReaderSync; /***/ }), -/* 662 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77011,13 +75709,13 @@ exports.default = Settings; /***/ }), -/* 663 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(664); +const pathType = __webpack_require__(663); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -77093,7 +75791,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 664 */ +/* 663 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77143,7 +75841,7 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 665 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77151,9 +75849,9 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); const {promisify} = __webpack_require__(29); const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(597); -const gitIgnore = __webpack_require__(666); -const slash = __webpack_require__(667); +const fastGlob = __webpack_require__(596); +const gitIgnore = __webpack_require__(665); +const slash = __webpack_require__(666); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -77267,7 +75965,7 @@ module.exports.sync = options => { /***/ }), -/* 666 */ +/* 665 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -77858,7 +76556,7 @@ if ( /***/ }), -/* 667 */ +/* 666 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77876,7 +76574,7 @@ module.exports = path => { /***/ }), -/* 668 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77929,7 +76627,7 @@ module.exports = { /***/ }), -/* 669 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77951,7 +76649,7 @@ module.exports = path_ => { /***/ }), -/* 670 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77979,7 +76677,7 @@ module.exports = (childPath, parentPath) => { /***/ }), -/* 671 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { const assert = __webpack_require__(30) @@ -77987,7 +76685,7 @@ const path = __webpack_require__(16) const fs = __webpack_require__(23) let glob = undefined try { - glob = __webpack_require__(592) + glob = __webpack_require__(591) } catch (_err) { // treat glob as optional. } @@ -78353,12 +77051,12 @@ rimraf.sync = rimrafSync /***/ }), -/* 672 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const AggregateError = __webpack_require__(673); +const AggregateError = __webpack_require__(672); module.exports = async ( iterable, @@ -78441,13 +77139,13 @@ module.exports = async ( /***/ }), -/* 673 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const indentString = __webpack_require__(674); -const cleanStack = __webpack_require__(675); +const indentString = __webpack_require__(673); +const cleanStack = __webpack_require__(674); const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); @@ -78495,7 +77193,7 @@ module.exports = AggregateError; /***/ }), -/* 674 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78537,7 +77235,7 @@ module.exports = (string, count = 1, options) => { /***/ }), -/* 675 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78584,15 +77282,15 @@ module.exports = (stack, options) => { /***/ }), -/* 676 */ +/* 675 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(677); -const cliCursor = __webpack_require__(681); -const cliSpinners = __webpack_require__(685); -const logSymbols = __webpack_require__(566); +const chalk = __webpack_require__(676); +const cliCursor = __webpack_require__(680); +const cliSpinners = __webpack_require__(684); +const logSymbols = __webpack_require__(565); class Ora { constructor(options) { @@ -78739,16 +77437,16 @@ module.exports.promise = (action, options) => { /***/ }), -/* 677 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(678); -const stdoutColor = __webpack_require__(679).stdout; +const ansiStyles = __webpack_require__(677); +const stdoutColor = __webpack_require__(678).stdout; -const template = __webpack_require__(680); +const template = __webpack_require__(679); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -78974,7 +77672,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 678 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79147,7 +77845,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 679 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79289,7 +77987,7 @@ module.exports = { /***/ }), -/* 680 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79424,12 +78122,12 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 681 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(682); +const restoreCursor = __webpack_require__(681); let hidden = false; @@ -79470,12 +78168,12 @@ exports.toggle = (force, stream) => { /***/ }), -/* 682 */ +/* 681 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(683); +const onetime = __webpack_require__(682); const signalExit = __webpack_require__(377); module.exports = onetime(() => { @@ -79486,12 +78184,12 @@ module.exports = onetime(() => { /***/ }), -/* 683 */ +/* 682 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const mimicFn = __webpack_require__(684); +const mimicFn = __webpack_require__(683); module.exports = (fn, opts) => { // TODO: Remove this in v3 @@ -79532,7 +78230,7 @@ module.exports = (fn, opts) => { /***/ }), -/* 684 */ +/* 683 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79548,22 +78246,22 @@ module.exports = (to, from) => { /***/ }), -/* 685 */ +/* 684 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(686); +module.exports = __webpack_require__(685); /***/ }), -/* 686 */ +/* 685 */ /***/ (function(module) { module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]}}"); /***/ }), -/* 687 */ +/* 686 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79623,7 +78321,7 @@ const RunCommand = { }; /***/ }), -/* 688 */ +/* 687 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79634,7 +78332,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(500); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(501); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(689); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(688); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -79718,7 +78416,7 @@ const WatchCommand = { }; /***/ }), -/* 689 */ +/* 688 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79792,7 +78490,7 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 690 */ +/* 689 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79800,15 +78498,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(691); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(690); /* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(692); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(691); /* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(34); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(501); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(699); -/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(700); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(698); +/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(699); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -79896,7 +78594,7 @@ function toArray(value) { } /***/ }), -/* 691 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79930,13 +78628,13 @@ module.exports = (str, count, opts) => { /***/ }), -/* 692 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringWidth = __webpack_require__(693); -const stripAnsi = __webpack_require__(697); +const stringWidth = __webpack_require__(692); +const stripAnsi = __webpack_require__(696); const ESCAPES = new Set([ '\u001B', @@ -80130,13 +78828,13 @@ module.exports = (str, cols, opts) => { /***/ }), -/* 693 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stripAnsi = __webpack_require__(694); -const isFullwidthCodePoint = __webpack_require__(696); +const stripAnsi = __webpack_require__(693); +const isFullwidthCodePoint = __webpack_require__(695); module.exports = str => { if (typeof str !== 'string' || str.length === 0) { @@ -80173,18 +78871,18 @@ module.exports = str => { /***/ }), -/* 694 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(695); +const ansiRegex = __webpack_require__(694); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 695 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80201,7 +78899,7 @@ module.exports = () => { /***/ }), -/* 696 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80254,18 +78952,18 @@ module.exports = x => { /***/ }), -/* 697 */ +/* 696 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(698); +const ansiRegex = __webpack_require__(697); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 698 */ +/* 697 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80282,7 +78980,7 @@ module.exports = () => { /***/ }), -/* 699 */ +/* 698 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -80435,7 +79133,7 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 700 */ +/* 699 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -80443,10 +79141,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Kibana", function() { return Kibana; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(701); +/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(700); /* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(501); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(580); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -80578,15 +79276,15 @@ class Kibana { } /***/ }), -/* 701 */ +/* 700 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const minimatch = __webpack_require__(505); -const arrayUnion = __webpack_require__(702); -const arrayDiffer = __webpack_require__(703); -const arrify = __webpack_require__(704); +const arrayUnion = __webpack_require__(701); +const arrayDiffer = __webpack_require__(702); +const arrify = __webpack_require__(703); module.exports = (list, patterns, options = {}) => { list = arrify(list); @@ -80610,7 +79308,7 @@ module.exports = (list, patterns, options = {}) => { /***/ }), -/* 702 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80622,7 +79320,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 703 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80637,7 +79335,7 @@ module.exports = arrayDiffer; /***/ }), -/* 704 */ +/* 703 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80667,15 +79365,15 @@ module.exports = arrify; /***/ }), -/* 705 */ +/* 704 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(706); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(705); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(929); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(928); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); /* @@ -80700,19 +79398,19 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 706 */ +/* 705 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(707); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(706); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(588); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(587); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(580); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(517); @@ -80848,7 +79546,7 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { } /***/ }), -/* 707 */ +/* 706 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80856,13 +79554,13 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { const EventEmitter = __webpack_require__(379); const path = __webpack_require__(16); const os = __webpack_require__(11); -const pAll = __webpack_require__(708); -const arrify = __webpack_require__(710); -const globby = __webpack_require__(711); -const isGlob = __webpack_require__(606); -const cpFile = __webpack_require__(914); -const junk = __webpack_require__(926); -const CpyError = __webpack_require__(927); +const pAll = __webpack_require__(707); +const arrify = __webpack_require__(709); +const globby = __webpack_require__(710); +const isGlob = __webpack_require__(605); +const cpFile = __webpack_require__(913); +const junk = __webpack_require__(925); +const CpyError = __webpack_require__(926); const defaultOptions = { ignoreJunk: true @@ -80981,12 +79679,12 @@ module.exports = (source, destination, { /***/ }), -/* 708 */ +/* 707 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(709); +const pMap = __webpack_require__(708); module.exports = (iterable, options) => pMap(iterable, element => element(), options); // TODO: Remove this for the next major release @@ -80994,7 +79692,7 @@ module.exports.default = module.exports; /***/ }), -/* 709 */ +/* 708 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81073,7 +79771,7 @@ module.exports.default = pMap; /***/ }), -/* 710 */ +/* 709 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81103,17 +79801,17 @@ module.exports = arrify; /***/ }), -/* 711 */ +/* 710 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(712); -const glob = __webpack_require__(714); -const fastGlob = __webpack_require__(719); -const dirGlob = __webpack_require__(907); -const gitignore = __webpack_require__(910); +const arrayUnion = __webpack_require__(711); +const glob = __webpack_require__(713); +const fastGlob = __webpack_require__(718); +const dirGlob = __webpack_require__(906); +const gitignore = __webpack_require__(909); const DEFAULT_FILTER = () => false; @@ -81258,12 +79956,12 @@ module.exports.gitignore = gitignore; /***/ }), -/* 712 */ +/* 711 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(713); +var arrayUniq = __webpack_require__(712); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -81271,7 +79969,7 @@ module.exports = function () { /***/ }), -/* 713 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81340,7 +80038,7 @@ if ('Set' in global) { /***/ }), -/* 714 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -81389,13 +80087,13 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(503) var minimatch = __webpack_require__(505) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(715) +var inherits = __webpack_require__(714) var EE = __webpack_require__(379).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(511) -var globSync = __webpack_require__(717) -var common = __webpack_require__(718) +var globSync = __webpack_require__(716) +var common = __webpack_require__(717) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -82136,7 +80834,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 715 */ +/* 714 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -82146,12 +80844,12 @@ try { module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(716); + module.exports = __webpack_require__(715); } /***/ }), -/* 716 */ +/* 715 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -82184,7 +80882,7 @@ if (typeof Object.create === 'function') { /***/ }), -/* 717 */ +/* 716 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync @@ -82194,12 +80892,12 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(503) var minimatch = __webpack_require__(505) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(714).Glob +var Glob = __webpack_require__(713).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(511) -var common = __webpack_require__(718) +var common = __webpack_require__(717) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -82676,7 +81374,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 718 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -82922,10 +81620,10 @@ function childrenIgnored (self, path) { /***/ }), -/* 719 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(720); +const pkg = __webpack_require__(719); module.exports = pkg.async; module.exports.default = pkg.async; @@ -82938,19 +81636,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 720 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(721); -var taskManager = __webpack_require__(722); -var reader_async_1 = __webpack_require__(878); -var reader_stream_1 = __webpack_require__(902); -var reader_sync_1 = __webpack_require__(903); -var arrayUtils = __webpack_require__(905); -var streamUtils = __webpack_require__(906); +var optionsManager = __webpack_require__(720); +var taskManager = __webpack_require__(721); +var reader_async_1 = __webpack_require__(877); +var reader_stream_1 = __webpack_require__(901); +var reader_sync_1 = __webpack_require__(902); +var arrayUtils = __webpack_require__(904); +var streamUtils = __webpack_require__(905); /** * Synchronous API. */ @@ -83016,7 +81714,7 @@ function isString(source) { /***/ }), -/* 721 */ +/* 720 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83054,13 +81752,13 @@ exports.prepare = prepare; /***/ }), -/* 722 */ +/* 721 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(723); +var patternUtils = __webpack_require__(722); /** * Generate tasks based on parent directory of each pattern. */ @@ -83151,16 +81849,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 723 */ +/* 722 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var globParent = __webpack_require__(724); -var isGlob = __webpack_require__(727); -var micromatch = __webpack_require__(728); +var globParent = __webpack_require__(723); +var isGlob = __webpack_require__(726); +var micromatch = __webpack_require__(727); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -83306,15 +82004,15 @@ exports.matchAny = matchAny; /***/ }), -/* 724 */ +/* 723 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(16); -var isglob = __webpack_require__(725); -var pathDirname = __webpack_require__(726); +var isglob = __webpack_require__(724); +var pathDirname = __webpack_require__(725); var isWin32 = __webpack_require__(11).platform() === 'win32'; module.exports = function globParent(str) { @@ -83337,7 +82035,7 @@ module.exports = function globParent(str) { /***/ }), -/* 725 */ +/* 724 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -83347,7 +82045,7 @@ module.exports = function globParent(str) { * Licensed under the MIT License. */ -var isExtglob = __webpack_require__(607); +var isExtglob = __webpack_require__(606); module.exports = function isGlob(str) { if (typeof str !== 'string' || str === '') { @@ -83368,7 +82066,7 @@ module.exports = function isGlob(str) { /***/ }), -/* 726 */ +/* 725 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83518,7 +82216,7 @@ module.exports.win32 = win32; /***/ }), -/* 727 */ +/* 726 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -83528,7 +82226,7 @@ module.exports.win32 = win32; * Released under the MIT License. */ -var isExtglob = __webpack_require__(607); +var isExtglob = __webpack_require__(606); var chars = { '{': '}', '(': ')', '[': ']'}; module.exports = function isGlob(str, options) { @@ -83570,7 +82268,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 728 */ +/* 727 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83581,18 +82279,18 @@ module.exports = function isGlob(str, options) { */ var util = __webpack_require__(29); -var braces = __webpack_require__(729); -var toRegex = __webpack_require__(831); -var extend = __webpack_require__(839); +var braces = __webpack_require__(728); +var toRegex = __webpack_require__(830); +var extend = __webpack_require__(838); /** * Local dependencies */ -var compilers = __webpack_require__(842); -var parsers = __webpack_require__(874); -var cache = __webpack_require__(875); -var utils = __webpack_require__(876); +var compilers = __webpack_require__(841); +var parsers = __webpack_require__(873); +var cache = __webpack_require__(874); +var utils = __webpack_require__(875); var MAX_LENGTH = 1024 * 64; /** @@ -84454,7 +83152,7 @@ module.exports = micromatch; /***/ }), -/* 729 */ +/* 728 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84464,18 +83162,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(730); -var unique = __webpack_require__(742); -var extend = __webpack_require__(739); +var toRegex = __webpack_require__(729); +var unique = __webpack_require__(741); +var extend = __webpack_require__(738); /** * Local dependencies */ -var compilers = __webpack_require__(743); -var parsers = __webpack_require__(758); -var Braces = __webpack_require__(768); -var utils = __webpack_require__(744); +var compilers = __webpack_require__(742); +var parsers = __webpack_require__(757); +var Braces = __webpack_require__(767); +var utils = __webpack_require__(743); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -84779,15 +83477,15 @@ module.exports = braces; /***/ }), -/* 730 */ +/* 729 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(731); -var extend = __webpack_require__(739); -var not = __webpack_require__(741); +var define = __webpack_require__(730); +var extend = __webpack_require__(738); +var not = __webpack_require__(740); var MAX_LENGTH = 1024 * 64; /** @@ -84934,7 +83632,7 @@ module.exports.makeRe = makeRe; /***/ }), -/* 731 */ +/* 730 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84947,7 +83645,7 @@ module.exports.makeRe = makeRe; -var isDescriptor = __webpack_require__(732); +var isDescriptor = __webpack_require__(731); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -84972,7 +83670,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 732 */ +/* 731 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84985,9 +83683,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(733); -var isAccessor = __webpack_require__(734); -var isData = __webpack_require__(737); +var typeOf = __webpack_require__(732); +var isAccessor = __webpack_require__(733); +var isData = __webpack_require__(736); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -85001,7 +83699,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 733 */ +/* 732 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -85154,7 +83852,7 @@ function isBuffer(val) { /***/ }), -/* 734 */ +/* 733 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85167,7 +83865,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(735); +var typeOf = __webpack_require__(734); // accessor descriptor properties var accessor = { @@ -85230,10 +83928,10 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 735 */ +/* 734 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(736); +var isBuffer = __webpack_require__(735); var toString = Object.prototype.toString; /** @@ -85352,7 +84050,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 736 */ +/* 735 */ /***/ (function(module, exports) { /*! @@ -85379,7 +84077,7 @@ function isSlowBuffer (obj) { /***/ }), -/* 737 */ +/* 736 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85392,7 +84090,7 @@ function isSlowBuffer (obj) { -var typeOf = __webpack_require__(738); +var typeOf = __webpack_require__(737); // data descriptor properties var data = { @@ -85441,10 +84139,10 @@ module.exports = isDataDescriptor; /***/ }), -/* 738 */ +/* 737 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(736); +var isBuffer = __webpack_require__(735); var toString = Object.prototype.toString; /** @@ -85563,13 +84261,13 @@ module.exports = function kindOf(val) { /***/ }), -/* 739 */ +/* 738 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(740); +var isObject = __webpack_require__(739); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -85603,7 +84301,7 @@ function hasOwn(obj, key) { /***/ }), -/* 740 */ +/* 739 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85623,13 +84321,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 741 */ +/* 740 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(739); +var extend = __webpack_require__(738); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -85696,7 +84394,7 @@ module.exports = toRegex; /***/ }), -/* 742 */ +/* 741 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85746,13 +84444,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 743 */ +/* 742 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(744); +var utils = __webpack_require__(743); module.exports = function(braces, options) { braces.compiler @@ -86035,25 +84733,25 @@ function hasQueue(node) { /***/ }), -/* 744 */ +/* 743 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(745); +var splitString = __webpack_require__(744); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(739); -utils.flatten = __webpack_require__(751); -utils.isObject = __webpack_require__(749); -utils.fillRange = __webpack_require__(752); -utils.repeat = __webpack_require__(757); -utils.unique = __webpack_require__(742); +utils.extend = __webpack_require__(738); +utils.flatten = __webpack_require__(750); +utils.isObject = __webpack_require__(748); +utils.fillRange = __webpack_require__(751); +utils.repeat = __webpack_require__(756); +utils.unique = __webpack_require__(741); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -86385,7 +85083,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 745 */ +/* 744 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86398,7 +85096,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(746); +var extend = __webpack_require__(745); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -86563,14 +85261,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 746 */ +/* 745 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(747); -var assignSymbols = __webpack_require__(750); +var isExtendable = __webpack_require__(746); +var assignSymbols = __webpack_require__(749); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -86630,7 +85328,7 @@ function isEnum(obj, key) { /***/ }), -/* 747 */ +/* 746 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86643,7 +85341,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(748); +var isPlainObject = __webpack_require__(747); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -86651,7 +85349,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 748 */ +/* 747 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86664,7 +85362,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(749); +var isObject = __webpack_require__(748); function isObjectObject(o) { return isObject(o) === true @@ -86695,7 +85393,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 749 */ +/* 748 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86714,7 +85412,7 @@ module.exports = function isObject(val) { /***/ }), -/* 750 */ +/* 749 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86761,7 +85459,7 @@ module.exports = function(receiver, objects) { /***/ }), -/* 751 */ +/* 750 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86790,7 +85488,7 @@ function flat(arr, res) { /***/ }), -/* 752 */ +/* 751 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86804,10 +85502,10 @@ function flat(arr, res) { var util = __webpack_require__(29); -var isNumber = __webpack_require__(753); -var extend = __webpack_require__(739); -var repeat = __webpack_require__(755); -var toRegex = __webpack_require__(756); +var isNumber = __webpack_require__(752); +var extend = __webpack_require__(738); +var repeat = __webpack_require__(754); +var toRegex = __webpack_require__(755); /** * Return a range of numbers or letters. @@ -87005,7 +85703,7 @@ module.exports = fillRange; /***/ }), -/* 753 */ +/* 752 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87018,7 +85716,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(754); +var typeOf = __webpack_require__(753); module.exports = function isNumber(num) { var type = typeOf(num); @@ -87034,10 +85732,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 754 */ +/* 753 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(736); +var isBuffer = __webpack_require__(735); var toString = Object.prototype.toString; /** @@ -87156,7 +85854,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 755 */ +/* 754 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87233,7 +85931,7 @@ function repeat(str, num) { /***/ }), -/* 756 */ +/* 755 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87246,8 +85944,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(755); -var isNumber = __webpack_require__(753); +var repeat = __webpack_require__(754); +var isNumber = __webpack_require__(752); var cache = {}; function toRegexRange(min, max, options) { @@ -87534,7 +86232,7 @@ module.exports = toRegexRange; /***/ }), -/* 757 */ +/* 756 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87559,14 +86257,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 758 */ +/* 757 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(759); -var utils = __webpack_require__(744); +var Node = __webpack_require__(758); +var utils = __webpack_require__(743); /** * Braces parsers @@ -87926,15 +86624,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 759 */ +/* 758 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(749); -var define = __webpack_require__(760); -var utils = __webpack_require__(767); +var isObject = __webpack_require__(748); +var define = __webpack_require__(759); +var utils = __webpack_require__(766); var ownNames; /** @@ -88425,7 +87123,7 @@ exports = module.exports = Node; /***/ }), -/* 760 */ +/* 759 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88438,7 +87136,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(761); +var isDescriptor = __webpack_require__(760); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -88463,7 +87161,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 761 */ +/* 760 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88476,9 +87174,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(762); -var isAccessor = __webpack_require__(763); -var isData = __webpack_require__(765); +var typeOf = __webpack_require__(761); +var isAccessor = __webpack_require__(762); +var isData = __webpack_require__(764); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -88492,7 +87190,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 762 */ +/* 761 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -88627,7 +87325,7 @@ function isBuffer(val) { /***/ }), -/* 763 */ +/* 762 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88640,7 +87338,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(764); +var typeOf = __webpack_require__(763); // accessor descriptor properties var accessor = { @@ -88703,7 +87401,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 764 */ +/* 763 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -88838,7 +87536,7 @@ function isBuffer(val) { /***/ }), -/* 765 */ +/* 764 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88851,7 +87549,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(766); +var typeOf = __webpack_require__(765); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -88894,7 +87592,7 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 766 */ +/* 765 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -89029,13 +87727,13 @@ function isBuffer(val) { /***/ }), -/* 767 */ +/* 766 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(754); +var typeOf = __webpack_require__(753); var utils = module.exports; /** @@ -90055,17 +88753,17 @@ function assert(val, message) { /***/ }), -/* 768 */ +/* 767 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(739); -var Snapdragon = __webpack_require__(769); -var compilers = __webpack_require__(743); -var parsers = __webpack_require__(758); -var utils = __webpack_require__(744); +var extend = __webpack_require__(738); +var Snapdragon = __webpack_require__(768); +var compilers = __webpack_require__(742); +var parsers = __webpack_require__(757); +var utils = __webpack_require__(743); /** * Customize Snapdragon parser and renderer @@ -90166,17 +88864,17 @@ module.exports = Braces; /***/ }), -/* 769 */ +/* 768 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(770); -var define = __webpack_require__(731); -var Compiler = __webpack_require__(799); -var Parser = __webpack_require__(828); -var utils = __webpack_require__(808); +var Base = __webpack_require__(769); +var define = __webpack_require__(730); +var Compiler = __webpack_require__(798); +var Parser = __webpack_require__(827); +var utils = __webpack_require__(807); var regexCache = {}; var cache = {}; @@ -90347,20 +89045,20 @@ module.exports.Parser = Parser; /***/ }), -/* 770 */ +/* 769 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var define = __webpack_require__(771); -var CacheBase = __webpack_require__(772); -var Emitter = __webpack_require__(773); -var isObject = __webpack_require__(749); -var merge = __webpack_require__(790); -var pascal = __webpack_require__(793); -var cu = __webpack_require__(794); +var define = __webpack_require__(770); +var CacheBase = __webpack_require__(771); +var Emitter = __webpack_require__(772); +var isObject = __webpack_require__(748); +var merge = __webpack_require__(789); +var pascal = __webpack_require__(792); +var cu = __webpack_require__(793); /** * Optionally define a custom `cache` namespace to use. @@ -90789,7 +89487,7 @@ module.exports.namespace = namespace; /***/ }), -/* 771 */ +/* 770 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90802,7 +89500,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(761); +var isDescriptor = __webpack_require__(760); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -90827,21 +89525,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 772 */ +/* 771 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(749); -var Emitter = __webpack_require__(773); -var visit = __webpack_require__(774); -var toPath = __webpack_require__(777); -var union = __webpack_require__(778); -var del = __webpack_require__(782); -var get = __webpack_require__(780); -var has = __webpack_require__(787); -var set = __webpack_require__(781); +var isObject = __webpack_require__(748); +var Emitter = __webpack_require__(772); +var visit = __webpack_require__(773); +var toPath = __webpack_require__(776); +var union = __webpack_require__(777); +var del = __webpack_require__(781); +var get = __webpack_require__(779); +var has = __webpack_require__(786); +var set = __webpack_require__(780); /** * Create a `Cache` constructor that when instantiated will @@ -91095,7 +89793,7 @@ module.exports.namespace = namespace; /***/ }), -/* 773 */ +/* 772 */ /***/ (function(module, exports, __webpack_require__) { @@ -91264,7 +89962,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 774 */ +/* 773 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91277,8 +89975,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(775); -var mapVisit = __webpack_require__(776); +var visit = __webpack_require__(774); +var mapVisit = __webpack_require__(775); module.exports = function(collection, method, val) { var result; @@ -91301,7 +89999,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 775 */ +/* 774 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91314,7 +90012,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(749); +var isObject = __webpack_require__(748); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -91341,14 +90039,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 776 */ +/* 775 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var visit = __webpack_require__(775); +var visit = __webpack_require__(774); /** * Map `visit` over an array of objects. @@ -91385,7 +90083,7 @@ function isObject(val) { /***/ }), -/* 777 */ +/* 776 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91398,7 +90096,7 @@ function isObject(val) { -var typeOf = __webpack_require__(754); +var typeOf = __webpack_require__(753); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -91425,16 +90123,16 @@ function filter(arr) { /***/ }), -/* 778 */ +/* 777 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(740); -var union = __webpack_require__(779); -var get = __webpack_require__(780); -var set = __webpack_require__(781); +var isObject = __webpack_require__(739); +var union = __webpack_require__(778); +var get = __webpack_require__(779); +var set = __webpack_require__(780); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -91462,7 +90160,7 @@ function arrayify(val) { /***/ }), -/* 779 */ +/* 778 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91498,7 +90196,7 @@ module.exports = function union(init) { /***/ }), -/* 780 */ +/* 779 */ /***/ (function(module, exports) { /*! @@ -91554,7 +90252,7 @@ function toString(val) { /***/ }), -/* 781 */ +/* 780 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91567,10 +90265,10 @@ function toString(val) { -var split = __webpack_require__(745); -var extend = __webpack_require__(739); -var isPlainObject = __webpack_require__(748); -var isObject = __webpack_require__(740); +var split = __webpack_require__(744); +var extend = __webpack_require__(738); +var isPlainObject = __webpack_require__(747); +var isObject = __webpack_require__(739); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -91616,7 +90314,7 @@ function isValidKey(key) { /***/ }), -/* 782 */ +/* 781 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91629,8 +90327,8 @@ function isValidKey(key) { -var isObject = __webpack_require__(749); -var has = __webpack_require__(783); +var isObject = __webpack_require__(748); +var has = __webpack_require__(782); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -91655,7 +90353,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 783 */ +/* 782 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91668,9 +90366,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(784); -var hasValues = __webpack_require__(786); -var get = __webpack_require__(780); +var isObject = __webpack_require__(783); +var hasValues = __webpack_require__(785); +var get = __webpack_require__(779); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -91681,7 +90379,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 784 */ +/* 783 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91694,7 +90392,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(785); +var isArray = __webpack_require__(784); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -91702,7 +90400,7 @@ module.exports = function isObject(val) { /***/ }), -/* 785 */ +/* 784 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -91713,7 +90411,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 786 */ +/* 785 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91756,7 +90454,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 787 */ +/* 786 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91769,9 +90467,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(749); -var hasValues = __webpack_require__(788); -var get = __webpack_require__(780); +var isObject = __webpack_require__(748); +var hasValues = __webpack_require__(787); +var get = __webpack_require__(779); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -91779,7 +90477,7 @@ module.exports = function(val, prop) { /***/ }), -/* 788 */ +/* 787 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91792,8 +90490,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(789); -var isNumber = __webpack_require__(753); +var typeOf = __webpack_require__(788); +var isNumber = __webpack_require__(752); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -91846,10 +90544,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 789 */ +/* 788 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(736); +var isBuffer = __webpack_require__(735); var toString = Object.prototype.toString; /** @@ -91971,14 +90669,14 @@ module.exports = function kindOf(val) { /***/ }), -/* 790 */ +/* 789 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(791); -var forIn = __webpack_require__(792); +var isExtendable = __webpack_require__(790); +var forIn = __webpack_require__(791); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -92042,7 +90740,7 @@ module.exports = mixinDeep; /***/ }), -/* 791 */ +/* 790 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92055,7 +90753,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(748); +var isPlainObject = __webpack_require__(747); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -92063,7 +90761,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 792 */ +/* 791 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92086,7 +90784,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 793 */ +/* 792 */ /***/ (function(module, exports) { /*! @@ -92113,14 +90811,14 @@ module.exports = pascalcase; /***/ }), -/* 794 */ +/* 793 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var utils = __webpack_require__(795); +var utils = __webpack_require__(794); /** * Expose class utils @@ -92485,7 +91183,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 795 */ +/* 794 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92499,10 +91197,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(779); -utils.define = __webpack_require__(731); -utils.isObj = __webpack_require__(749); -utils.staticExtend = __webpack_require__(796); +utils.union = __webpack_require__(778); +utils.define = __webpack_require__(730); +utils.isObj = __webpack_require__(748); +utils.staticExtend = __webpack_require__(795); /** @@ -92513,7 +91211,7 @@ module.exports = utils; /***/ }), -/* 796 */ +/* 795 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92526,8 +91224,8 @@ module.exports = utils; -var copy = __webpack_require__(797); -var define = __webpack_require__(731); +var copy = __webpack_require__(796); +var define = __webpack_require__(730); var util = __webpack_require__(29); /** @@ -92610,15 +91308,15 @@ module.exports = extend; /***/ }), -/* 797 */ +/* 796 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(754); -var copyDescriptor = __webpack_require__(798); -var define = __webpack_require__(731); +var typeOf = __webpack_require__(753); +var copyDescriptor = __webpack_require__(797); +var define = __webpack_require__(730); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -92791,7 +91489,7 @@ module.exports.has = has; /***/ }), -/* 798 */ +/* 797 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92879,16 +91577,16 @@ function isObject(val) { /***/ }), -/* 799 */ +/* 798 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(800); -var define = __webpack_require__(731); -var debug = __webpack_require__(802)('snapdragon:compiler'); -var utils = __webpack_require__(808); +var use = __webpack_require__(799); +var define = __webpack_require__(730); +var debug = __webpack_require__(801)('snapdragon:compiler'); +var utils = __webpack_require__(807); /** * Create a new `Compiler` with the given `options`. @@ -93042,7 +91740,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(827); + var sourcemaps = __webpack_require__(826); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -93063,7 +91761,7 @@ module.exports = Compiler; /***/ }), -/* 800 */ +/* 799 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -93076,7 +91774,7 @@ module.exports = Compiler; -var utils = __webpack_require__(801); +var utils = __webpack_require__(800); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -93191,7 +91889,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 801 */ +/* 800 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -93205,8 +91903,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(731); -utils.isObject = __webpack_require__(749); +utils.define = __webpack_require__(730); +utils.isObject = __webpack_require__(748); utils.isString = function(val) { @@ -93221,7 +91919,7 @@ module.exports = utils; /***/ }), -/* 802 */ +/* 801 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -93230,14 +91928,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(803); + module.exports = __webpack_require__(802); } else { - module.exports = __webpack_require__(806); + module.exports = __webpack_require__(805); } /***/ }), -/* 803 */ +/* 802 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -93246,7 +91944,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(804); +exports = module.exports = __webpack_require__(803); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -93428,7 +92126,7 @@ function localstorage() { /***/ }), -/* 804 */ +/* 803 */ /***/ (function(module, exports, __webpack_require__) { @@ -93444,7 +92142,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(805); +exports.humanize = __webpack_require__(804); /** * The currently active debug mode names, and names to skip. @@ -93636,7 +92334,7 @@ function coerce(val) { /***/ }), -/* 805 */ +/* 804 */ /***/ (function(module, exports) { /** @@ -93794,7 +92492,7 @@ function plural(ms, n, name) { /***/ }), -/* 806 */ +/* 805 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -93810,7 +92508,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(804); +exports = module.exports = __webpack_require__(803); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -93989,7 +92687,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(807); + var net = __webpack_require__(806); stream = new net.Socket({ fd: fd, readable: false, @@ -94048,13 +92746,13 @@ exports.enable(load()); /***/ }), -/* 807 */ +/* 806 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 808 */ +/* 807 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -94064,9 +92762,9 @@ module.exports = require("net"); * Module dependencies */ -exports.extend = __webpack_require__(739); -exports.SourceMap = __webpack_require__(809); -exports.sourceMapResolve = __webpack_require__(820); +exports.extend = __webpack_require__(738); +exports.SourceMap = __webpack_require__(808); +exports.sourceMapResolve = __webpack_require__(819); /** * Convert backslash in the given string to forward slashes @@ -94109,7 +92807,7 @@ exports.last = function(arr, n) { /***/ }), -/* 809 */ +/* 808 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -94117,13 +92815,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(810).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(816).SourceMapConsumer; -exports.SourceNode = __webpack_require__(819).SourceNode; +exports.SourceMapGenerator = __webpack_require__(809).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(815).SourceMapConsumer; +exports.SourceNode = __webpack_require__(818).SourceNode; /***/ }), -/* 810 */ +/* 809 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -94133,10 +92831,10 @@ exports.SourceNode = __webpack_require__(819).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(811); -var util = __webpack_require__(813); -var ArraySet = __webpack_require__(814).ArraySet; -var MappingList = __webpack_require__(815).MappingList; +var base64VLQ = __webpack_require__(810); +var util = __webpack_require__(812); +var ArraySet = __webpack_require__(813).ArraySet; +var MappingList = __webpack_require__(814).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -94545,7 +93243,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 811 */ +/* 810 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -94585,7 +93283,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(812); +var base64 = __webpack_require__(811); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -94691,7 +93389,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 812 */ +/* 811 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -94764,7 +93462,7 @@ exports.decode = function (charCode) { /***/ }), -/* 813 */ +/* 812 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95187,7 +93885,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 814 */ +/* 813 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95197,7 +93895,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(813); +var util = __webpack_require__(812); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -95314,7 +94012,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 815 */ +/* 814 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95324,7 +94022,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(813); +var util = __webpack_require__(812); /** * Determine whether mappingB is after mappingA with respect to generated @@ -95399,7 +94097,7 @@ exports.MappingList = MappingList; /***/ }), -/* 816 */ +/* 815 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95409,11 +94107,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(813); -var binarySearch = __webpack_require__(817); -var ArraySet = __webpack_require__(814).ArraySet; -var base64VLQ = __webpack_require__(811); -var quickSort = __webpack_require__(818).quickSort; +var util = __webpack_require__(812); +var binarySearch = __webpack_require__(816); +var ArraySet = __webpack_require__(813).ArraySet; +var base64VLQ = __webpack_require__(810); +var quickSort = __webpack_require__(817).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -96487,7 +95185,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 817 */ +/* 816 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -96604,7 +95302,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 818 */ +/* 817 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -96724,7 +95422,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 819 */ +/* 818 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -96734,8 +95432,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(810).SourceMapGenerator; -var util = __webpack_require__(813); +var SourceMapGenerator = __webpack_require__(809).SourceMapGenerator; +var util = __webpack_require__(812); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -97143,17 +95841,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 820 */ +/* 819 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(821) -var resolveUrl = __webpack_require__(822) -var decodeUriComponent = __webpack_require__(823) -var urix = __webpack_require__(825) -var atob = __webpack_require__(826) +var sourceMappingURL = __webpack_require__(820) +var resolveUrl = __webpack_require__(821) +var decodeUriComponent = __webpack_require__(822) +var urix = __webpack_require__(824) +var atob = __webpack_require__(825) @@ -97451,7 +96149,7 @@ module.exports = { /***/ }), -/* 821 */ +/* 820 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -97514,7 +96212,7 @@ void (function(root, factory) { /***/ }), -/* 822 */ +/* 821 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -97532,13 +96230,13 @@ module.exports = resolveUrl /***/ }), -/* 823 */ +/* 822 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(824) +var decodeUriComponent = __webpack_require__(823) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -97549,7 +96247,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 824 */ +/* 823 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -97650,7 +96348,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 825 */ +/* 824 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -97673,7 +96371,7 @@ module.exports = urix /***/ }), -/* 826 */ +/* 825 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -97687,7 +96385,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 827 */ +/* 826 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -97695,8 +96393,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(23); var path = __webpack_require__(16); -var define = __webpack_require__(731); -var utils = __webpack_require__(808); +var define = __webpack_require__(730); +var utils = __webpack_require__(807); /** * Expose `mixin()`. @@ -97839,19 +96537,19 @@ exports.comment = function(node) { /***/ }), -/* 828 */ +/* 827 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(800); +var use = __webpack_require__(799); var util = __webpack_require__(29); -var Cache = __webpack_require__(829); -var define = __webpack_require__(731); -var debug = __webpack_require__(802)('snapdragon:parser'); -var Position = __webpack_require__(830); -var utils = __webpack_require__(808); +var Cache = __webpack_require__(828); +var define = __webpack_require__(730); +var debug = __webpack_require__(801)('snapdragon:parser'); +var Position = __webpack_require__(829); +var utils = __webpack_require__(807); /** * Create a new `Parser` with the given `input` and `options`. @@ -98379,7 +97077,7 @@ module.exports = Parser; /***/ }), -/* 829 */ +/* 828 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -98486,13 +97184,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 830 */ +/* 829 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(731); +var define = __webpack_require__(730); /** * Store position for a node @@ -98507,16 +97205,16 @@ module.exports = function Position(start, parser) { /***/ }), -/* 831 */ +/* 830 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(832); -var define = __webpack_require__(838); -var extend = __webpack_require__(839); -var not = __webpack_require__(841); +var safe = __webpack_require__(831); +var define = __webpack_require__(837); +var extend = __webpack_require__(838); +var not = __webpack_require__(840); var MAX_LENGTH = 1024 * 64; /** @@ -98669,10 +97367,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 832 */ +/* 831 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(833); +var parse = __webpack_require__(832); var types = parse.types; module.exports = function (re, opts) { @@ -98718,13 +97416,13 @@ function isRegExp (x) { /***/ }), -/* 833 */ +/* 832 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(834); -var types = __webpack_require__(835); -var sets = __webpack_require__(836); -var positions = __webpack_require__(837); +var util = __webpack_require__(833); +var types = __webpack_require__(834); +var sets = __webpack_require__(835); +var positions = __webpack_require__(836); module.exports = function(regexpStr) { @@ -99006,11 +97704,11 @@ module.exports.types = types; /***/ }), -/* 834 */ +/* 833 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(835); -var sets = __webpack_require__(836); +var types = __webpack_require__(834); +var sets = __webpack_require__(835); // All of these are private and only used by randexp. @@ -99123,7 +97821,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 835 */ +/* 834 */ /***/ (function(module, exports) { module.exports = { @@ -99139,10 +97837,10 @@ module.exports = { /***/ }), -/* 836 */ +/* 835 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(835); +var types = __webpack_require__(834); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -99227,10 +97925,10 @@ exports.anyChar = function() { /***/ }), -/* 837 */ +/* 836 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(835); +var types = __webpack_require__(834); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -99250,7 +97948,7 @@ exports.end = function() { /***/ }), -/* 838 */ +/* 837 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99263,8 +97961,8 @@ exports.end = function() { -var isobject = __webpack_require__(749); -var isDescriptor = __webpack_require__(761); +var isobject = __webpack_require__(748); +var isDescriptor = __webpack_require__(760); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -99295,14 +97993,14 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 839 */ +/* 838 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(840); -var assignSymbols = __webpack_require__(750); +var isExtendable = __webpack_require__(839); +var assignSymbols = __webpack_require__(749); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -99362,7 +98060,7 @@ function isEnum(obj, key) { /***/ }), -/* 840 */ +/* 839 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99375,7 +98073,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(748); +var isPlainObject = __webpack_require__(747); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -99383,14 +98081,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 841 */ +/* 840 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(839); -var safe = __webpack_require__(832); +var extend = __webpack_require__(838); +var safe = __webpack_require__(831); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -99462,14 +98160,14 @@ module.exports = toRegex; /***/ }), -/* 842 */ +/* 841 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(843); -var extglob = __webpack_require__(858); +var nanomatch = __webpack_require__(842); +var extglob = __webpack_require__(857); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -99546,7 +98244,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 843 */ +/* 842 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99557,17 +98255,17 @@ function escapeExtglobs(compiler) { */ var util = __webpack_require__(29); -var toRegex = __webpack_require__(730); -var extend = __webpack_require__(844); +var toRegex = __webpack_require__(729); +var extend = __webpack_require__(843); /** * Local dependencies */ -var compilers = __webpack_require__(846); -var parsers = __webpack_require__(847); -var cache = __webpack_require__(850); -var utils = __webpack_require__(852); +var compilers = __webpack_require__(845); +var parsers = __webpack_require__(846); +var cache = __webpack_require__(849); +var utils = __webpack_require__(851); var MAX_LENGTH = 1024 * 64; /** @@ -100391,14 +99089,14 @@ module.exports = nanomatch; /***/ }), -/* 844 */ +/* 843 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(845); -var assignSymbols = __webpack_require__(750); +var isExtendable = __webpack_require__(844); +var assignSymbols = __webpack_require__(749); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -100458,7 +99156,7 @@ function isEnum(obj, key) { /***/ }), -/* 845 */ +/* 844 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100471,7 +99169,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(748); +var isPlainObject = __webpack_require__(747); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -100479,7 +99177,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 846 */ +/* 845 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100825,15 +99523,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 847 */ +/* 846 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(741); -var toRegex = __webpack_require__(730); -var isOdd = __webpack_require__(848); +var regexNot = __webpack_require__(740); +var toRegex = __webpack_require__(729); +var isOdd = __webpack_require__(847); /** * Characters to use in negation regex (we want to "not" match @@ -101219,7 +99917,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 848 */ +/* 847 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101232,7 +99930,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(849); +var isNumber = __webpack_require__(848); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -101246,7 +99944,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 849 */ +/* 848 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101274,14 +99972,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 850 */ +/* 849 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(851))(); +module.exports = new (__webpack_require__(850))(); /***/ }), -/* 851 */ +/* 850 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101294,7 +99992,7 @@ module.exports = new (__webpack_require__(851))(); -var MapCache = __webpack_require__(829); +var MapCache = __webpack_require__(828); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -101416,7 +100114,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 852 */ +/* 851 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101429,14 +100127,14 @@ var path = __webpack_require__(16); * Module dependencies */ -var isWindows = __webpack_require__(853)(); -var Snapdragon = __webpack_require__(769); -utils.define = __webpack_require__(854); -utils.diff = __webpack_require__(855); -utils.extend = __webpack_require__(844); -utils.pick = __webpack_require__(856); -utils.typeOf = __webpack_require__(857); -utils.unique = __webpack_require__(742); +var isWindows = __webpack_require__(852)(); +var Snapdragon = __webpack_require__(768); +utils.define = __webpack_require__(853); +utils.diff = __webpack_require__(854); +utils.extend = __webpack_require__(843); +utils.pick = __webpack_require__(855); +utils.typeOf = __webpack_require__(856); +utils.unique = __webpack_require__(741); /** * Returns true if the given value is effectively an empty string @@ -101802,7 +100500,7 @@ utils.unixify = function(options) { /***/ }), -/* 853 */ +/* 852 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -101830,7 +100528,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 854 */ +/* 853 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101843,8 +100541,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(749); -var isDescriptor = __webpack_require__(761); +var isobject = __webpack_require__(748); +var isDescriptor = __webpack_require__(760); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -101875,7 +100573,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 855 */ +/* 854 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101929,7 +100627,7 @@ function diffArray(one, two) { /***/ }), -/* 856 */ +/* 855 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101942,7 +100640,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(749); +var isObject = __webpack_require__(748); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -101971,7 +100669,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 857 */ +/* 856 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -102106,7 +100804,7 @@ function isBuffer(val) { /***/ }), -/* 858 */ +/* 857 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102116,18 +100814,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(739); -var unique = __webpack_require__(742); -var toRegex = __webpack_require__(730); +var extend = __webpack_require__(738); +var unique = __webpack_require__(741); +var toRegex = __webpack_require__(729); /** * Local dependencies */ -var compilers = __webpack_require__(859); -var parsers = __webpack_require__(870); -var Extglob = __webpack_require__(873); -var utils = __webpack_require__(872); +var compilers = __webpack_require__(858); +var parsers = __webpack_require__(869); +var Extglob = __webpack_require__(872); +var utils = __webpack_require__(871); var MAX_LENGTH = 1024 * 64; /** @@ -102444,13 +101142,13 @@ module.exports = extglob; /***/ }), -/* 859 */ +/* 858 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(860); +var brackets = __webpack_require__(859); /** * Extglob compilers @@ -102620,7 +101318,7 @@ module.exports = function(extglob) { /***/ }), -/* 860 */ +/* 859 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102630,17 +101328,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(861); -var parsers = __webpack_require__(863); +var compilers = __webpack_require__(860); +var parsers = __webpack_require__(862); /** * Module dependencies */ -var debug = __webpack_require__(865)('expand-brackets'); -var extend = __webpack_require__(739); -var Snapdragon = __webpack_require__(769); -var toRegex = __webpack_require__(730); +var debug = __webpack_require__(864)('expand-brackets'); +var extend = __webpack_require__(738); +var Snapdragon = __webpack_require__(768); +var toRegex = __webpack_require__(729); /** * Parses the given POSIX character class `pattern` and returns a @@ -102838,13 +101536,13 @@ module.exports = brackets; /***/ }), -/* 861 */ +/* 860 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(862); +var posix = __webpack_require__(861); module.exports = function(brackets) { brackets.compiler @@ -102932,7 +101630,7 @@ module.exports = function(brackets) { /***/ }), -/* 862 */ +/* 861 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102961,14 +101659,14 @@ module.exports = { /***/ }), -/* 863 */ +/* 862 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(864); -var define = __webpack_require__(731); +var utils = __webpack_require__(863); +var define = __webpack_require__(730); /** * Text regex @@ -103187,14 +101885,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 864 */ +/* 863 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(730); -var regexNot = __webpack_require__(741); +var toRegex = __webpack_require__(729); +var regexNot = __webpack_require__(740); var cached; /** @@ -103228,7 +101926,7 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 865 */ +/* 864 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -103237,14 +101935,14 @@ exports.createRegex = function(pattern, include) { */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(866); + module.exports = __webpack_require__(865); } else { - module.exports = __webpack_require__(869); + module.exports = __webpack_require__(868); } /***/ }), -/* 866 */ +/* 865 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -103253,7 +101951,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(867); +exports = module.exports = __webpack_require__(866); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -103435,7 +102133,7 @@ function localstorage() { /***/ }), -/* 867 */ +/* 866 */ /***/ (function(module, exports, __webpack_require__) { @@ -103451,7 +102149,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(868); +exports.humanize = __webpack_require__(867); /** * The currently active debug mode names, and names to skip. @@ -103643,7 +102341,7 @@ function coerce(val) { /***/ }), -/* 868 */ +/* 867 */ /***/ (function(module, exports) { /** @@ -103801,7 +102499,7 @@ function plural(ms, n, name) { /***/ }), -/* 869 */ +/* 868 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -103817,7 +102515,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(867); +exports = module.exports = __webpack_require__(866); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -103996,7 +102694,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(807); + var net = __webpack_require__(806); stream = new net.Socket({ fd: fd, readable: false, @@ -104055,15 +102753,15 @@ exports.enable(load()); /***/ }), -/* 870 */ +/* 869 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(860); -var define = __webpack_require__(871); -var utils = __webpack_require__(872); +var brackets = __webpack_require__(859); +var define = __webpack_require__(870); +var utils = __webpack_require__(871); /** * Characters to use in text regex (we want to "not" match @@ -104218,7 +102916,7 @@ module.exports = parsers; /***/ }), -/* 871 */ +/* 870 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104231,7 +102929,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(761); +var isDescriptor = __webpack_require__(760); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -104256,14 +102954,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 872 */ +/* 871 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(741); -var Cache = __webpack_require__(851); +var regex = __webpack_require__(740); +var Cache = __webpack_require__(850); /** * Utils @@ -104332,7 +103030,7 @@ utils.createRegex = function(str) { /***/ }), -/* 873 */ +/* 872 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104342,16 +103040,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(769); -var define = __webpack_require__(871); -var extend = __webpack_require__(739); +var Snapdragon = __webpack_require__(768); +var define = __webpack_require__(870); +var extend = __webpack_require__(738); /** * Local dependencies */ -var compilers = __webpack_require__(859); -var parsers = __webpack_require__(870); +var compilers = __webpack_require__(858); +var parsers = __webpack_require__(869); /** * Customize Snapdragon parser and renderer @@ -104417,16 +103115,16 @@ module.exports = Extglob; /***/ }), -/* 874 */ +/* 873 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(858); -var nanomatch = __webpack_require__(843); -var regexNot = __webpack_require__(741); -var toRegex = __webpack_require__(831); +var extglob = __webpack_require__(857); +var nanomatch = __webpack_require__(842); +var regexNot = __webpack_require__(740); +var toRegex = __webpack_require__(830); var not; /** @@ -104507,14 +103205,14 @@ function textRegex(pattern) { /***/ }), -/* 875 */ +/* 874 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(851))(); +module.exports = new (__webpack_require__(850))(); /***/ }), -/* 876 */ +/* 875 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104527,13 +103225,13 @@ var path = __webpack_require__(16); * Module dependencies */ -var Snapdragon = __webpack_require__(769); -utils.define = __webpack_require__(838); -utils.diff = __webpack_require__(855); -utils.extend = __webpack_require__(839); -utils.pick = __webpack_require__(856); -utils.typeOf = __webpack_require__(877); -utils.unique = __webpack_require__(742); +var Snapdragon = __webpack_require__(768); +utils.define = __webpack_require__(837); +utils.diff = __webpack_require__(854); +utils.extend = __webpack_require__(838); +utils.pick = __webpack_require__(855); +utils.typeOf = __webpack_require__(876); +utils.unique = __webpack_require__(741); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -104830,7 +103528,7 @@ utils.unixify = function(options) { /***/ }), -/* 877 */ +/* 876 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -104965,7 +103663,7 @@ function isBuffer(val) { /***/ }), -/* 878 */ +/* 877 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104984,9 +103682,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(879); -var reader_1 = __webpack_require__(892); -var fs_stream_1 = __webpack_require__(896); +var readdir = __webpack_require__(878); +var reader_1 = __webpack_require__(891); +var fs_stream_1 = __webpack_require__(895); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -105047,15 +103745,15 @@ exports.default = ReaderAsync; /***/ }), -/* 879 */ +/* 878 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(880); -const readdirAsync = __webpack_require__(888); -const readdirStream = __webpack_require__(891); +const readdirSync = __webpack_require__(879); +const readdirAsync = __webpack_require__(887); +const readdirStream = __webpack_require__(890); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -105139,7 +103837,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 880 */ +/* 879 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105147,11 +103845,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(881); +const DirectoryReader = __webpack_require__(880); let syncFacade = { - fs: __webpack_require__(886), - forEach: __webpack_require__(887), + fs: __webpack_require__(885), + forEach: __webpack_require__(886), sync: true }; @@ -105180,7 +103878,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 881 */ +/* 880 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105189,9 +103887,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(27).Readable; const EventEmitter = __webpack_require__(379).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(882); -const stat = __webpack_require__(884); -const call = __webpack_require__(885); +const normalizeOptions = __webpack_require__(881); +const stat = __webpack_require__(883); +const call = __webpack_require__(884); /** * Asynchronously reads the contents of a directory and streams the results @@ -105567,14 +104265,14 @@ module.exports = DirectoryReader; /***/ }), -/* 882 */ +/* 881 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(883); +const globToRegExp = __webpack_require__(882); module.exports = normalizeOptions; @@ -105751,7 +104449,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 883 */ +/* 882 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -105888,13 +104586,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 884 */ +/* 883 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(885); +const call = __webpack_require__(884); module.exports = stat; @@ -105969,7 +104667,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 885 */ +/* 884 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106030,14 +104728,14 @@ function callOnce (fn) { /***/ }), -/* 886 */ +/* 885 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(885); +const call = __webpack_require__(884); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -106101,7 +104799,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 887 */ +/* 886 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106130,7 +104828,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 888 */ +/* 887 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106138,12 +104836,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(889); -const DirectoryReader = __webpack_require__(881); +const maybe = __webpack_require__(888); +const DirectoryReader = __webpack_require__(880); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(890), + forEach: __webpack_require__(889), async: true }; @@ -106185,7 +104883,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 889 */ +/* 888 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106212,7 +104910,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 890 */ +/* 889 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106248,7 +104946,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 891 */ +/* 890 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106256,11 +104954,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(881); +const DirectoryReader = __webpack_require__(880); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(890), + forEach: __webpack_require__(889), async: true }; @@ -106280,16 +104978,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 892 */ +/* 891 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(893); -var entry_1 = __webpack_require__(895); -var pathUtil = __webpack_require__(894); +var deep_1 = __webpack_require__(892); +var entry_1 = __webpack_require__(894); +var pathUtil = __webpack_require__(893); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -106355,14 +105053,14 @@ exports.default = Reader; /***/ }), -/* 893 */ +/* 892 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(894); -var patternUtils = __webpack_require__(723); +var pathUtils = __webpack_require__(893); +var patternUtils = __webpack_require__(722); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -106445,7 +105143,7 @@ exports.default = DeepFilter; /***/ }), -/* 894 */ +/* 893 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106476,14 +105174,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 895 */ +/* 894 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(894); -var patternUtils = __webpack_require__(723); +var pathUtils = __webpack_require__(893); +var patternUtils = __webpack_require__(722); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -106568,7 +105266,7 @@ exports.default = EntryFilter; /***/ }), -/* 896 */ +/* 895 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106588,8 +105286,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var fsStat = __webpack_require__(897); -var fs_1 = __webpack_require__(901); +var fsStat = __webpack_require__(896); +var fs_1 = __webpack_require__(900); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -106639,14 +105337,14 @@ exports.default = FileSystemStream; /***/ }), -/* 897 */ +/* 896 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(898); -const statProvider = __webpack_require__(900); +const optionsManager = __webpack_require__(897); +const statProvider = __webpack_require__(899); /** * Asynchronous API. */ @@ -106677,13 +105375,13 @@ exports.statSync = statSync; /***/ }), -/* 898 */ +/* 897 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(899); +const fsAdapter = __webpack_require__(898); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -106696,7 +105394,7 @@ exports.prepare = prepare; /***/ }), -/* 899 */ +/* 898 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106719,7 +105417,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 900 */ +/* 899 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106771,7 +105469,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 901 */ +/* 900 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106802,7 +105500,7 @@ exports.default = FileSystem; /***/ }), -/* 902 */ +/* 901 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106822,9 +105520,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var readdir = __webpack_require__(879); -var reader_1 = __webpack_require__(892); -var fs_stream_1 = __webpack_require__(896); +var readdir = __webpack_require__(878); +var reader_1 = __webpack_require__(891); +var fs_stream_1 = __webpack_require__(895); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -106892,7 +105590,7 @@ exports.default = ReaderStream; /***/ }), -/* 903 */ +/* 902 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106911,9 +105609,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(879); -var reader_1 = __webpack_require__(892); -var fs_sync_1 = __webpack_require__(904); +var readdir = __webpack_require__(878); +var reader_1 = __webpack_require__(891); +var fs_sync_1 = __webpack_require__(903); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -106973,7 +105671,7 @@ exports.default = ReaderSync; /***/ }), -/* 904 */ +/* 903 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106992,8 +105690,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(897); -var fs_1 = __webpack_require__(901); +var fsStat = __webpack_require__(896); +var fs_1 = __webpack_require__(900); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -107039,7 +105737,7 @@ exports.default = FileSystemSync; /***/ }), -/* 905 */ +/* 904 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107055,13 +105753,13 @@ exports.flatten = flatten; /***/ }), -/* 906 */ +/* 905 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(591); +var merge2 = __webpack_require__(590); /** * Merge multiple streams and propagate their errors into one stream in parallel. */ @@ -107076,13 +105774,13 @@ exports.merge = merge; /***/ }), -/* 907 */ +/* 906 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(908); +const pathType = __webpack_require__(907); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -107148,13 +105846,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 908 */ +/* 907 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const pify = __webpack_require__(909); +const pify = __webpack_require__(908); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -107197,7 +105895,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 909 */ +/* 908 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107288,17 +105986,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 910 */ +/* 909 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(719); -const gitIgnore = __webpack_require__(911); -const pify = __webpack_require__(912); -const slash = __webpack_require__(913); +const fastGlob = __webpack_require__(718); +const gitIgnore = __webpack_require__(910); +const pify = __webpack_require__(911); +const slash = __webpack_require__(912); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -107396,7 +106094,7 @@ module.exports.sync = options => { /***/ }), -/* 911 */ +/* 910 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -107865,7 +106563,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 912 */ +/* 911 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107940,7 +106638,7 @@ module.exports = (input, options) => { /***/ }), -/* 913 */ +/* 912 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107958,17 +106656,17 @@ module.exports = input => { /***/ }), -/* 914 */ +/* 913 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const {constants: fsConstants} = __webpack_require__(23); -const pEvent = __webpack_require__(915); -const CpFileError = __webpack_require__(918); -const fs = __webpack_require__(922); -const ProgressEmitter = __webpack_require__(925); +const pEvent = __webpack_require__(914); +const CpFileError = __webpack_require__(917); +const fs = __webpack_require__(921); +const ProgressEmitter = __webpack_require__(924); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -108082,12 +106780,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 915 */ +/* 914 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(916); +const pTimeout = __webpack_require__(915); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -108378,12 +107076,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 916 */ +/* 915 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(917); +const pFinally = __webpack_require__(916); class TimeoutError extends Error { constructor(message) { @@ -108429,7 +107127,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 917 */ +/* 916 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -108451,12 +107149,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 918 */ +/* 917 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(919); +const NestedError = __webpack_require__(918); class CpFileError extends NestedError { constructor(message, nested) { @@ -108470,10 +107168,10 @@ module.exports = CpFileError; /***/ }), -/* 919 */ +/* 918 */ /***/ (function(module, exports, __webpack_require__) { -var inherits = __webpack_require__(920); +var inherits = __webpack_require__(919); var NestedError = function (message, nested) { this.nested = nested; @@ -108524,7 +107222,7 @@ module.exports = NestedError; /***/ }), -/* 920 */ +/* 919 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -108532,12 +107230,12 @@ try { if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; } catch (e) { - module.exports = __webpack_require__(921); + module.exports = __webpack_require__(920); } /***/ }), -/* 921 */ +/* 920 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -108566,16 +107264,16 @@ if (typeof Object.create === 'function') { /***/ }), -/* 922 */ +/* 921 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const fs = __webpack_require__(22); -const makeDir = __webpack_require__(923); -const pEvent = __webpack_require__(915); -const CpFileError = __webpack_require__(918); +const makeDir = __webpack_require__(922); +const pEvent = __webpack_require__(914); +const CpFileError = __webpack_require__(917); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -108672,7 +107370,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 923 */ +/* 922 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -108680,7 +107378,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const {promisify} = __webpack_require__(29); -const semver = __webpack_require__(924); +const semver = __webpack_require__(923); const defaults = { mode: 0o777 & (~process.umask()), @@ -108829,7 +107527,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 924 */ +/* 923 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -110431,7 +109129,7 @@ function coerce (version, options) { /***/ }), -/* 925 */ +/* 924 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -110472,7 +109170,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 926 */ +/* 925 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -110518,12 +109216,12 @@ exports.default = module.exports; /***/ }), -/* 927 */ +/* 926 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(928); +const NestedError = __webpack_require__(927); class CpyError extends NestedError { constructor(message, nested) { @@ -110537,7 +109235,7 @@ module.exports = CpyError; /***/ }), -/* 928 */ +/* 927 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(29).inherits; @@ -110593,7 +109291,7 @@ module.exports = NestedError; /***/ }), -/* 929 */ +/* 928 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; diff --git a/x-pack/legacy/plugins/beats_management/public/utils/typed_react.ts b/x-pack/legacy/plugins/beats_management/public/utils/typed_react.ts index dbc0894ab8071..89c0d3d2403c5 100644 --- a/x-pack/legacy/plugins/beats_management/public/utils/typed_react.ts +++ b/x-pack/legacy/plugins/beats_management/public/utils/typed_react.ts @@ -4,58 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { omit } from 'lodash'; import React from 'react'; -import { InferableComponentEnhancerWithProps } from 'react-redux'; export type RendererResult = React.ReactElement | null; export type RendererFunction = (args: RenderArgs) => Result; -export type ChildFunctionRendererProps = { - children: RendererFunction; - initializeOnMount?: boolean; - resetOnUnmount?: boolean; -} & RenderArgs; - -interface ChildFunctionRendererOptions { - onInitialize?: (props: RenderArgs) => void; - onCleanup?: (props: RenderArgs) => void; -} - -export const asChildFunctionRenderer = ( - hoc: InferableComponentEnhancerWithProps, - { onInitialize, onCleanup }: ChildFunctionRendererOptions = {} -) => - hoc( - class ChildFunctionRenderer extends React.Component> { - public displayName = 'ChildFunctionRenderer'; - - public componentDidMount() { - if (this.props.initializeOnMount && onInitialize) { - onInitialize(this.getRendererArgs()); - } - } - - public componentWillUnmount() { - if (this.props.resetOnUnmount && onCleanup) { - onCleanup(this.getRendererArgs()); - } - } - - public render() { - return (this.props.children as ChildFunctionRendererProps['children'])( - this.getRendererArgs() - ); - } - - private getRendererArgs = () => - omit(['children', 'initializeOnMount', 'resetOnUnmount'], this.props) as Pick< - ChildFunctionRendererProps, - keyof InjectedProps - >; - } - ); - export type StateUpdater = ( prevState: Readonly, prevProps: Readonly diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx b/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx index e855a381413eb..e8b772e0f2fbd 100644 --- a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx +++ b/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx @@ -12,6 +12,7 @@ import { WorkpadLoadedWithErrorsMetric, } from './workpad_telemetry'; import { METRIC_TYPE } from '../../../lib/ui_metric'; +import { ResolvedArgType } from '../../../../types'; jest.mock('ui/new_platform'); const trackMetric = jest.fn(); @@ -30,15 +31,15 @@ const mockWorkpad = { }; const resolvedArgsMatchWorkpad = { - '1': {}, - '2': {}, - '3': {}, - '4': {}, - '5': {}, + '1': {} as ResolvedArgType, + '2': {} as ResolvedArgType, + '3': {} as ResolvedArgType, + '4': {} as ResolvedArgType, + '5': {} as ResolvedArgType, }; const resolvedArgsNotMatchWorkpad = { - 'non-matching-id': {}, + 'non-matching-id': {} as ResolvedArgType, }; const pendingCounts = { diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx b/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx index 39ff3f45d602a..5f3f114092e61 100644 --- a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx +++ b/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx @@ -5,7 +5,7 @@ */ import React, { useState, useEffect } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; // @ts-ignore: Local Untyped import { trackCanvasUiMetric, METRIC_TYPE } from '../../../lib/ui_metric'; // @ts-ignore: Local Untyped @@ -23,18 +23,6 @@ const mapStateToProps = (state: any) => ({ telemetryResolvedArgs: getArgs(state), }); -/** - Counts of the loading states of workpad elements -*/ -interface ElementCounts { - /** Count of elements in error state */ - error: number; - /** Count of elements in pending state */ - pending: number; - /** Count of elements in ready state */ - ready: number; -} - // TODO: Build out full workpad types /** Individual Page of a Workpad @@ -61,10 +49,8 @@ interface ResolvedArgs { [keys: string]: any; } -interface ElementsLoadedTelemetryProps { - telemetryElementCounts: ElementCounts; +interface ElementsLoadedTelemetryProps extends PropsFromRedux { workpad: Workpad; - telemetryResolvedArgs: {}; } function areAllElementsInResolvedArgs(workpad: Workpad, resolvedArgs: ResolvedArgs): boolean { @@ -77,13 +63,11 @@ function areAllElementsInResolvedArgs(workpad: Workpad, resolvedArgs: ResolvedAr return workpadElements.every(element => resolvedArgsElements.includes(element)); } -export const withUnconnectedElementsLoadedTelemetry = function

( +export const withUnconnectedElementsLoadedTelemetry =

( Component: React.ComponentType

, trackMetric = trackCanvasUiMetric -): React.FC

{ - return function ElementsLoadedTelemetry( - props: P & ElementsLoadedTelemetryProps - ): React.FunctionComponentElement

{ +) => + function ElementsLoadedTelemetry(props: ElementsLoadedTelemetryProps) { const { telemetryElementCounts, workpad, telemetryResolvedArgs, ...other } = props; const [currentWorkpadId, setWorkpadId] = useState(undefined); @@ -127,11 +111,12 @@ export const withUnconnectedElementsLoadedTelemetry = function

return ; }; -}; -export const withElementsLoadedTelemetry =

( - Component: React.ComponentType

-) => { +const connector = connect(mapStateToProps, {}); + +type PropsFromRedux = ConnectedProps; + +export const withElementsLoadedTelemetry =

(Component: React.ComponentType

) => { const telemetry = withUnconnectedElementsLoadedTelemetry(Component); - return connect(mapStateToProps)(telemetry); + return connector(telemetry); }; diff --git a/x-pack/legacy/plugins/canvas/public/components/router/router.js b/x-pack/legacy/plugins/canvas/public/components/router/router.js index b2e4d540b89d8..40c9c469e5505 100644 --- a/x-pack/legacy/plugins/canvas/public/components/router/router.js +++ b/x-pack/legacy/plugins/canvas/public/components/router/router.js @@ -5,7 +5,6 @@ */ import React from 'react'; -import { isClassComponent } from 'recompose'; import PropTypes from 'prop-types'; import { routerProvider } from '../../lib/router_provider'; import { getAppState } from '../../lib/app_state'; @@ -98,9 +97,6 @@ export class Router extends React.PureComponent { return React.createElement(CanvasLoading, { msg: this.props.loadingMessage }); } - // show the activeComponent - return isClassComponent(this.state.activeComponent) - ? React.createElement(this.state.activeComponent, {}) - : this.state.activeComponent({}); + return ; } } diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/index.tsx b/x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/index.tsx index 7532b43a01054..b5e44b4996537 100644 --- a/x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/index.tsx +++ b/x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/index.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ import React from 'react'; -import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { getElementById, getSelectedPage } from '../../../state/selectors/workpad'; import { ElementSettings as Component } from './element_settings'; @@ -33,7 +32,3 @@ const renderIfElement: React.FunctionComponent = props => { export const ElementSettings = connect(mapStateToProps)( renderIfElement ); - -ElementSettings.propTypes = { - selectedElementId: PropTypes.string.isRequired, -}; diff --git a/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.test.tsx b/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.test.tsx index d7cbcf59213be..948f89705a5d5 100644 --- a/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.test.tsx +++ b/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.test.tsx @@ -70,8 +70,9 @@ describe('field_manager', () => { store.dispatch = dispatchSpy; instance = shallow( + // https://github.com/airbnb/enzyme/issues/2176#issuecomment-532361526 - {}} /> + {}} store={store} /> ); @@ -79,6 +80,7 @@ describe('field_manager', () => { instance .find(FieldManager) .dive() + .dive() .dive(); }); diff --git a/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.tsx b/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.tsx index 89b325d737bd5..9bca5b82e58aa 100644 --- a/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.tsx +++ b/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.tsx @@ -18,6 +18,7 @@ import { selectField, deselectField, GraphState, + GraphStore, } from '../../state_management'; import { WorkspaceField } from '../../types'; @@ -35,6 +36,7 @@ export function FieldManagerComponent(props: { deselectField: (fieldName: string) => void; pickerOpen: boolean; setPickerOpen: (open: boolean) => void; + store?: GraphStore; // only for testing purpose }) { return ( diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_time_controls.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_time_controls.tsx index 5095edd4c715c..3653a6d6bbeae 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_time_controls.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_time_controls.tsx @@ -16,7 +16,7 @@ const noop = () => undefined; interface LogTimeControlsProps { currentTime: number | null; startLiveStreaming: () => any; - stopLiveStreaming: () => any; + stopLiveStreaming: () => void; isLiveStreaming: boolean; jumpToTime: (time: number) => any; } diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/waffle_time_controls.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/waffle_time_controls.tsx index 373cfdce5e2a9..4f840336de8c3 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/waffle_time_controls.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/waffle_time_controls.tsx @@ -8,13 +8,14 @@ import { EuiButtonEmpty, EuiDatePicker, EuiFormControlLayout } from '@elastic/eu import { FormattedMessage } from '@kbn/i18n/react'; import moment, { Moment } from 'moment'; import React from 'react'; +import { Action } from 'typescript-fsa'; interface WaffleTimeControlsProps { currentTime: number; isLiveStreaming?: boolean; onChangeTime?: (time: number) => void; - startLiveStreaming?: () => void; - stopLiveStreaming?: () => void; + startLiveStreaming?: (payload: void) => Action; + stopLiveStreaming?: (payload: void) => Action; } export class WaffleTimeControls extends React.Component { diff --git a/x-pack/legacy/plugins/infra/public/utils/redux_context.tsx b/x-pack/legacy/plugins/infra/public/utils/redux_context.tsx index 3bd3d31c745a9..f249d72a6b56f 100644 --- a/x-pack/legacy/plugins/infra/public/utils/redux_context.tsx +++ b/x-pack/legacy/plugins/infra/public/utils/redux_context.tsx @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { connect } from 'react-redux'; +import { useSelector } from 'react-redux'; import React, { createContext } from 'react'; import { State, initialState } from '../store'; export const ReduxStateContext = createContext(initialState); -const withRedux = connect((state: State) => state); -export const ReduxStateContextProvider = withRedux(({ children, ...state }) => { - return {children}; -}); +export const ReduxStateContextProvider = ({ children }: { children: JSX.Element }) => { + const state = useSelector((store: State) => store); + return {children}; +}; diff --git a/x-pack/legacy/plugins/infra/public/utils/typed_react.tsx b/x-pack/legacy/plugins/infra/public/utils/typed_react.tsx index eadf3eb9686b5..d057899ba18be 100644 --- a/x-pack/legacy/plugins/infra/public/utils/typed_react.tsx +++ b/x-pack/legacy/plugins/infra/public/utils/typed_react.tsx @@ -6,7 +6,7 @@ import omit from 'lodash/fp/omit'; import React from 'react'; -import { InferableComponentEnhancerWithProps } from 'react-redux'; +import { InferableComponentEnhancerWithProps, ConnectedComponent } from 'react-redux'; export type RendererResult = React.ReactElement | null; export type RendererFunction = (args: RenderArgs) => Result; @@ -25,7 +25,14 @@ interface ChildFunctionRendererOptions { export const asChildFunctionRenderer = ( hoc: InferableComponentEnhancerWithProps, { onInitialize, onCleanup }: ChildFunctionRendererOptions = {} -) => +): ConnectedComponent< + React.ComponentClass<{}>, + { + children: RendererFunction; + initializeOnMount?: boolean; + resetOnUnmount?: boolean; + } & OwnProps +> => hoc( class ChildFunctionRenderer extends React.Component> { public displayName = 'ChildFunctionRenderer'; @@ -53,7 +60,7 @@ export const asChildFunctionRenderer = ( ChildFunctionRendererProps, keyof InjectedProps >; - } + } as any ); export type StateUpdater = ( diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/index.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/index.js index b3f8ee727dff5..d2b43775c5a49 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/index.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/index.js @@ -52,7 +52,7 @@ function mapDispatchToProps(dispatch) { }; } -const connectedFlyOut = connect(mapStateToProps, mapDispatchToProps, null, { withRef: true })( +const connectedFlyOut = connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })( AddLayerPanel ); export { connectedFlyOut as AddLayerPanel }; diff --git a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/index.js b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/index.js index 9148fbdfd2d1e..a2f121a9377fe 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/index.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/index.js @@ -69,6 +69,6 @@ function mapDispatchToProps(dispatch) { } const connectedMBMapContainer = connect(mapStateToProps, mapDispatchToProps, null, { - withRef: true, + forwardRef: true, })(MBMapContainer); export { connectedMBMapContainer as MBMapContainer }; diff --git a/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/index.js b/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/index.js index 0ae497b480776..1b5bf654822b2 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/index.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/index.js @@ -21,7 +21,7 @@ function mapStateToProps(state = {}) { }; } -const connectedLayerTOC = connect(mapStateToProps, mapDispatchToProps, null, { withRef: true })( +const connectedLayerTOC = connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })( LayerTOC ); export { connectedLayerTOC as LayerTOC }; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_view/metric_selection.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_view/metric_selection.tsx index fe5d3ff0c29fb..70a3d1c7d616c 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_view/metric_selection.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_view/metric_selection.tsx @@ -48,7 +48,10 @@ export const PopulationDetectors: FC = ({ setIsValid }) => { const [chartSettings, setChartSettings] = useState(defaultChartSettings); const [splitField, setSplitField] = useState(jobCreator.splitField); const [fieldValuesPerDetector, setFieldValuesPerDetector] = useState({}); - const [byFieldsUpdated, setByFieldsUpdated] = useReducer<(s: number) => number>(s => s + 1, 0); + const [byFieldsUpdated, setByFieldsUpdated] = useReducer<(s: number, action: any) => number>( + s => s + 1, + 0 + ); const [pageReady, setPageReady] = useState(false); const updateByFields = () => setByFieldsUpdated(0); diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx index b63ada4bb535c..6fe27457428b1 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx @@ -41,13 +41,15 @@ export const Wizard: FC = ({ existingJobsAndGroups, firstWizardStep = WIZARD_STEPS.TIME_RANGE, }) => { - const [jobCreatorUpdated, setJobCreatorUpdate] = useReducer<(s: number) => number>(s => s + 1, 0); - const jobCreatorUpdate = () => setJobCreatorUpdate(jobCreatorUpdated); - - const [jobValidatorUpdated, setJobValidatorUpdate] = useReducer<(s: number) => number>( + const [jobCreatorUpdated, setJobCreatorUpdate] = useReducer<(s: number, action: any) => number>( s => s + 1, 0 ); + const jobCreatorUpdate = () => setJobCreatorUpdate(jobCreatorUpdated); + + const [jobValidatorUpdated, setJobValidatorUpdate] = useReducer< + (s: number, action: any) => number + >(s => s + 1, 0); const jobCreatorContext: JobCreatorContextValue = { jobCreatorUpdated, diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx index f9e6bfcf7c236..72f5a62d0af97 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx @@ -7,7 +7,7 @@ import { defaultTo, noop } from 'lodash/fp'; import React, { useCallback } from 'react'; import { DropResult, DragDropContext } from 'react-beautiful-dnd'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { BeforeCapture } from './drag_drop_context'; @@ -30,7 +30,6 @@ import { interface Props { browserFields: BrowserFields; children: React.ReactNode; - dataProviders?: dragAndDropModel.IdToDataProvider; dispatch: Dispatch; } @@ -59,7 +58,7 @@ const onDragEndHandler = ({ /** * DragDropContextWrapperComponent handles all drag end events */ -export const DragDropContextWrapperComponent = React.memo( +export const DragDropContextWrapperComponent = React.memo( ({ browserFields, children, dataProviders, dispatch }) => { const onDragEnd = useCallback( (result: DropResult) => { @@ -112,7 +111,11 @@ const mapStateToProps = (state: State) => { return { dataProviders }; }; -export const DragDropContextWrapper = connect(mapStateToProps)(DragDropContextWrapperComponent); +const connector = connect(mapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const DragDropContextWrapper = connector(DragDropContextWrapperComponent); DragDropContextWrapper.displayName = 'DragDropContextWrapper'; diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx index 9672097713a9b..cf958bfd75d3b 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx @@ -12,9 +12,8 @@ import { DraggableStateSnapshot, Droppable, } from 'react-beautiful-dnd'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; -import { ActionCreator } from 'typescript-fsa'; import { EuiPortal } from '@elastic/eui'; import { dragAndDropActions } from '../../store/drag_and_drop'; @@ -59,16 +58,7 @@ interface OwnProps { truncate?: boolean; } -interface DispatchProps { - registerProvider?: ActionCreator<{ - provider: DataProvider; - }>; - unRegisterProvider?: ActionCreator<{ - id: string; - }>; -} - -type Props = OwnProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; /** * Wraps a draggable component to handle registration / unregistration of the @@ -141,10 +131,16 @@ const DraggableWrapperComponent = React.memo( DraggableWrapperComponent.displayName = 'DraggableWrapperComponent'; -export const DraggableWrapper = connect(null, { +const mapDispatchToProps = { registerProvider: dragAndDropActions.registerProvider, unRegisterProvider: dragAndDropActions.unRegisterProvider, -})(DraggableWrapperComponent); +}; + +const connector = connect(null, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const DraggableWrapper = connector(DraggableWrapperComponent); DraggableWrapper.displayName = 'DraggableWrapper'; diff --git a/x-pack/legacy/plugins/siem/public/components/error_toast_dispatcher/index.tsx b/x-pack/legacy/plugins/siem/public/components/error_toast_dispatcher/index.tsx index 3628330fbd459..ab9170ce1dd6a 100644 --- a/x-pack/legacy/plugins/siem/public/components/error_toast_dispatcher/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/error_toast_dispatcher/index.tsx @@ -5,10 +5,9 @@ */ import { useEffect } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; -import { appModel, appSelectors, State } from '../../store'; +import { appSelectors, State } from '../../store'; import { appActions } from '../../store/app'; import { useStateToaster } from '../toasters'; @@ -16,15 +15,7 @@ interface OwnProps { toastLifeTimeMs?: number; } -interface ReduxProps { - errors?: appModel.Error[]; -} - -interface DispatchProps { - removeError: ActionCreator<{ id: string }>; -} - -type Props = OwnProps & ReduxProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const ErrorToastDispatcherComponent = ({ toastLifeTimeMs = 5000, @@ -58,6 +49,12 @@ const makeMapStateToProps = () => { return (state: State) => getErrorSelector(state); }; -export const ErrorToastDispatcher = connect(makeMapStateToProps, { +const mapDispatchToProps = { removeError: appActions.removeError, -})(ErrorToastDispatcherComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const ErrorToastDispatcher = connector(ErrorToastDispatcherComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx index c7ccff5bdfcff..1e7c7fc2411bb 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx @@ -6,20 +6,16 @@ import { isEqual } from 'lodash/fp'; import React, { useCallback, useMemo, useEffect } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { inputsModel, inputsSelectors, State, timelineSelectors } from '../../store'; import { inputsActions, timelineActions } from '../../store/actions'; -import { KqlMode, SubsetTimelineModel, TimelineModel } from '../../store/timeline/model'; +import { SubsetTimelineModel, TimelineModel } from '../../store/timeline/model'; import { ColumnHeader } from '../timeline/body/column_headers/column_header'; -import { DataProvider } from '../timeline/data_providers/data_provider'; -import { Sort } from '../timeline/body/sort'; import { OnChangeItemsPerPage } from '../timeline/events'; -import { Filter, Query } from '../../../../../../../src/plugins/data/public'; +import { Filter } from '../../../../../../../src/plugins/data/public'; import { useUiSetting } from '../../lib/kibana'; import { EventsViewer } from './events_viewer'; -import { InputsModelId } from '../../store/inputs/constants'; import { useFetchIndexPatterns } from '../../containers/detection_engine/rules/fetch_index_patterns'; import { TimelineTypeContextProps } from '../timeline/timeline_context'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; @@ -38,51 +34,7 @@ export interface OwnProps { utilityBar?: (refetch: inputsModel.Refetch, totalCount: number) => React.ReactNode; } -interface StateReduxProps { - columns: ColumnHeader[]; - dataProviders?: DataProvider[]; - filters: Filter[]; - isLive: boolean; - itemsPerPage?: number; - itemsPerPageOptions?: number[]; - kqlMode: KqlMode; - deletedEventIds: Readonly; - query: Query; - pageCount?: number; - sort?: Sort; - showCheckboxes: boolean; - showRowRenderers: boolean; -} - -interface DispatchProps { - createTimeline: ActionCreator<{ - id: string; - columns: ColumnHeader[]; - itemsPerPage?: number; - sort?: Sort; - showCheckboxes?: boolean; - showRowRenderers?: boolean; - }>; - deleteEventQuery: ActionCreator<{ - id: string; - inputId: InputsModelId; - }>; - removeColumn: ActionCreator<{ - id: string; - columnId: string; - }>; - updateItemsPerPage: ActionCreator<{ - id: string; - itemsPerPage: number; - }>; - upsertColumn: ActionCreator<{ - column: ColumnHeader; - id: string; - index: number; - }>; -} - -type Props = OwnProps & StateReduxProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const defaultTimelineTypeContext = { loadingText: i18n.LOADING_EVENTS, @@ -224,13 +176,19 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const StatefulEventsViewer = connect(makeMapStateToProps, { +const mapDispatchToProps = { createTimeline: timelineActions.createTimeline, deleteEventQuery: inputsActions.deleteOneQuery, updateItemsPerPage: timelineActions.updateItemsPerPage, removeColumn: timelineActions.removeColumn, upsertColumn: timelineActions.upsertColumn, -})( +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulEventsViewer = connector( React.memo( StatefulEventsViewerComponent, (prevProps, nextProps) => @@ -245,7 +203,6 @@ export const StatefulEventsViewer = connect(makeMapStateToProps, { isEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && prevProps.kqlMode === nextProps.kqlMode && isEqual(prevProps.query, nextProps.query) && - prevProps.pageCount === nextProps.pageCount && isEqual(prevProps.sort, nextProps.sort) && prevProps.start === nextProps.start && isEqual(prevProps.pageFilters, nextProps.pageFilters) && diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx index 24e4cd77b20d3..cf9e4f57d67b7 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx @@ -6,6 +6,7 @@ import { mount } from 'enzyme'; import React from 'react'; +import { ActionCreator } from 'typescript-fsa'; import { mockBrowserFields } from '../../containers/source/mock'; import { TestProviders } from '../../mock'; @@ -13,6 +14,7 @@ import { TestProviders } from '../../mock'; import { FIELD_BROWSER_HEIGHT, FIELD_BROWSER_WIDTH } from './helpers'; import { StatefulFieldsBrowserComponent } from '.'; +import { ColumnHeader } from '../timeline/body/column_headers/column_header'; // Suppress warnings about "react-beautiful-dnd" until we migrate to @testing-library/react /* eslint-disable no-console */ @@ -27,6 +29,17 @@ afterAll(() => { console.warn = originalWarn; }); +const removeColumnMock = (jest.fn() as unknown) as ActionCreator<{ + id: string; + columnId: string; +}>; + +const upsertColumnMock = (jest.fn() as unknown) as ActionCreator<{ + column: ColumnHeader; + id: string; + index: number; +}>; + describe('StatefulFieldsBrowser', () => { const timelineId = 'test'; @@ -41,6 +54,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -65,6 +80,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -83,6 +100,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -111,6 +130,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -142,6 +163,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -180,6 +203,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -206,6 +231,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -232,6 +259,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx index c8cde5fa02a51..b545c6890bd41 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx @@ -7,9 +7,8 @@ import { EuiButtonEmpty, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { noop } from 'lodash/fp'; import React, { useEffect, useRef, useState, useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; -import { ActionCreator } from 'typescript-fsa'; import { BrowserFields } from '../../containers/source'; import { timelineActions } from '../../store/actions'; @@ -31,22 +30,10 @@ const FieldsBrowserButtonContainer = styled.div` FieldsBrowserButtonContainer.displayName = 'FieldsBrowserButtonContainer'; -interface DispatchProps { - removeColumn?: ActionCreator<{ - id: string; - columnId: string; - }>; - upsertColumn?: ActionCreator<{ - column: ColumnHeader; - id: string; - index: number; - }>; -} - /** * Manages the state of the field browser */ -export const StatefulFieldsBrowserComponent = React.memo( +export const StatefulFieldsBrowserComponent = React.memo( ({ columnHeaders, browserFields, @@ -212,7 +199,13 @@ export const StatefulFieldsBrowserComponent = React.memo; + +export const StatefulFieldsBrowser = connector(React.memo(StatefulFieldsBrowserComponent)); diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx index e1075c89ca350..901f7afd1ed48 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx @@ -5,9 +5,8 @@ */ import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; import { isEmpty, get } from 'lodash/fp'; import { History } from '../../../lib/history'; @@ -19,10 +18,9 @@ import { State, timelineSelectors, } from '../../../store'; -import { UpdateNote } from '../../notes/helpers'; import { defaultHeaders } from '../../timeline/body/column_headers/default_headers'; import { Properties } from '../../timeline/properties'; -import { appActions, appModel } from '../../../store/app'; +import { appActions } from '../../../store/app'; import { inputsActions } from '../../../store/inputs'; import { timelineActions } from '../../../store/actions'; import { timelineDefaults, TimelineModel } from '../../../store/timeline/model'; @@ -34,41 +32,7 @@ interface OwnProps { usersViewing: string[]; } -interface StateReduxProps { - description: string; - notesById: appModel.NotesById; - isDataInTimeline: boolean; - isDatepickerLocked: boolean; - isFavorite: boolean; - noteIds: string[]; - title: string; - width: number; -} - -interface DispatchProps { - associateNote: (noteId: string) => void; - applyDeltaToWidth?: ({ - id, - delta, - bodyClientWidthPixels, - maxWidthPercent, - minWidthPixels, - }: { - id: string; - delta: number; - bodyClientWidthPixels: number; - maxWidthPercent: number; - minWidthPixels: number; - }) => void; - createTimeline: ActionCreator<{ id: string; show?: boolean }>; - toggleLock: ActionCreator<{ linkToId: InputsModelId }>; - updateDescription: ActionCreator<{ id: string; description: string }>; - updateIsFavorite: ActionCreator<{ id: string; isFavorite: boolean }>; - updateNote: UpdateNote; - updateTitle: ActionCreator<{ id: string; title: string }>; -} - -type Props = OwnProps & StateReduxProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const StatefulFlyoutHeader = React.memo( ({ @@ -160,9 +124,7 @@ const makeMapStateToProps = () => { }; const mapDispatchToProps = (dispatch: Dispatch, { timelineId }: OwnProps) => ({ - associateNote: (noteId: string) => { - dispatch(timelineActions.addNote({ id: timelineId, noteId })); - }, + associateNote: (noteId: string) => dispatch(timelineActions.addNote({ id: timelineId, noteId })), applyDeltaToWidth: ({ id, delta, @@ -175,7 +137,7 @@ const mapDispatchToProps = (dispatch: Dispatch, { timelineId }: OwnProps) => ({ bodyClientWidthPixels: number; maxWidthPercent: number; minWidthPixels: number; - }) => { + }) => dispatch( timelineActions.applyDeltaToWidth({ id, @@ -184,35 +146,30 @@ const mapDispatchToProps = (dispatch: Dispatch, { timelineId }: OwnProps) => ({ maxWidthPercent, minWidthPixels, }) - ); - }, - createTimeline: ({ id, show }: { id: string; show?: boolean }) => { + ), + createTimeline: ({ id, show }: { id: string; show?: boolean }) => dispatch( timelineActions.createTimeline({ id, columns: defaultHeaders, show, }) - ); - }, - updateDescription: ({ id, description }: { id: string; description: string }) => { - dispatch(timelineActions.updateDescription({ id, description })); - }, - updateIsFavorite: ({ id, isFavorite }: { id: string; isFavorite: boolean }) => { - dispatch(timelineActions.updateIsFavorite({ id, isFavorite })); - }, - updateIsLive: ({ id, isLive }: { id: string; isLive: boolean }) => { - dispatch(timelineActions.updateIsLive({ id, isLive })); - }, - updateNote: (note: Note) => { - dispatch(appActions.updateNote({ note })); - }, - updateTitle: ({ id, title }: { id: string; title: string }) => { - dispatch(timelineActions.updateTitle({ id, title })); - }, - toggleLock: ({ linkToId }: { linkToId: InputsModelId }) => { - dispatch(inputsActions.toggleTimelineLinkTo({ linkToId })); - }, + ), + updateDescription: ({ id, description }: { id: string; description: string }) => + dispatch(timelineActions.updateDescription({ id, description })), + updateIsFavorite: ({ id, isFavorite }: { id: string; isFavorite: boolean }) => + dispatch(timelineActions.updateIsFavorite({ id, isFavorite })), + updateIsLive: ({ id, isLive }: { id: string; isLive: boolean }) => + dispatch(timelineActions.updateIsLive({ id, isLive })), + updateNote: (note: Note) => dispatch(appActions.updateNote({ note })), + updateTitle: ({ id, title }: { id: string; title: string }) => + dispatch(timelineActions.updateTitle({ id, title })), + toggleLock: ({ linkToId }: { linkToId: InputsModelId }) => + dispatch(inputsActions.toggleTimelineLinkTo({ linkToId })), }); -export const FlyoutHeader = connect(makeMapStateToProps, mapDispatchToProps)(StatefulFlyoutHeader); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const FlyoutHeader = connector(StatefulFlyoutHeader); diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx index 9fb59e2034b08..d18c22e44ce94 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx @@ -7,9 +7,8 @@ import { EuiBadge } from '@elastic/eui'; import { defaultTo, getOr } from 'lodash/fp'; import React from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; -import { ActionCreator } from 'typescript-fsa'; import { State, timelineSelectors } from '../../store'; import { DataProvider } from '../timeline/data_providers/data_provider'; @@ -46,30 +45,7 @@ interface OwnProps { usersViewing: string[]; } -interface DispatchProps { - showTimeline: ActionCreator<{ id: string; show: boolean }>; - applyDeltaToWidth?: ({ - id, - delta, - bodyClientWidthPixels, - maxWidthPercent, - minWidthPixels, - }: { - id: string; - delta: number; - bodyClientWidthPixels: number; - maxWidthPercent: number; - minWidthPixels: number; - }) => void; -} - -interface StateReduxProps { - dataProviders?: DataProvider[]; - show: boolean; - width: number; -} - -type Props = OwnProps & DispatchProps & StateReduxProps; +type Props = OwnProps & ProsFromRedux; export const FlyoutComponent = React.memo( ({ @@ -110,15 +86,21 @@ FlyoutComponent.displayName = 'FlyoutComponent'; const mapStateToProps = (state: State, { timelineId }: OwnProps) => { const timelineById = defaultTo({}, timelineSelectors.timelineByIdSelector(state)); - const dataProviders = getOr([], `${timelineId}.dataProviders`, timelineById); - const show = getOr('false', `${timelineId}.show`, timelineById); - const width = getOr(DEFAULT_TIMELINE_WIDTH, `${timelineId}.width`, timelineById); + const dataProviders = getOr([], `${timelineId}.dataProviders`, timelineById) as DataProvider[]; + const show = getOr(false, `${timelineId}.show`, timelineById) as boolean; + const width = getOr(DEFAULT_TIMELINE_WIDTH, `${timelineId}.width`, timelineById) as number; return { dataProviders, show, width }; }; -export const Flyout = connect(mapStateToProps, { +const mapDispatchToProps = { showTimeline: timelineActions.showTimeline, -})(FlyoutComponent); +}; + +const connector = connect(mapStateToProps, mapDispatchToProps); + +type ProsFromRedux = ConnectedProps; + +export const Flyout = connector(FlyoutComponent); Flyout.displayName = 'Flyout'; diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx index 00ac15092a6ec..fb977417ffbbf 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx @@ -6,9 +6,8 @@ import { EuiButtonIcon, EuiFlyout, EuiFlyoutBody, EuiFlyoutHeader, EuiToolTip } from '@elastic/eui'; import React, { useCallback, useState } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; -import { ActionCreator } from 'typescript-fsa'; import { Resizable, ResizeCallback } from 're-resizable'; import { throttle } from 'lodash/fp'; @@ -30,17 +29,7 @@ interface OwnProps { width: number; } -interface DispatchProps { - applyDeltaToWidth: ActionCreator<{ - id: string; - delta: number; - bodyClientWidthPixels: number; - maxWidthPercent: number; - minWidthPixels: number; - }>; -} - -type Props = OwnProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const EuiFlyoutContainer = styled.div<{ headerHeight: number }>` .timeline-flyout { @@ -183,8 +172,14 @@ const FlyoutPaneComponent: React.FC = ({ ); }; -export const Pane = connect(null, { +const mapDispatchToProps = { applyDeltaToWidth: timelineActions.applyDeltaToWidth, -})(React.memo(FlyoutPaneComponent)); +}; + +const connector = connect(null, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const Pane = connector(React.memo(FlyoutPaneComponent)); Pane.displayName = 'Pane'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts b/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts index 432939b0729d7..61c3d9f73e0d0 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts @@ -6,7 +6,7 @@ import ApolloClient from 'apollo-client'; import { getOr, set } from 'lodash/fp'; -import { ActionCreator } from 'typescript-fsa'; +import { Action } from 'typescript-fsa'; import { Dispatch } from 'redux'; import { oneTimelineQuery } from '../../containers/timeline/one/index.gql_query'; @@ -183,7 +183,13 @@ export interface QueryTimelineById { timelineId: string; onOpenTimeline?: (timeline: TimelineModel) => void; openTimeline?: boolean; - updateIsLoading: ActionCreator<{ id: string; isLoading: boolean }>; + updateIsLoading: ({ + id, + isLoading, + }: { + id: string; + isLoading: boolean; + }) => Action<{ id: string; isLoading: boolean }>; updateTimeline: DispatchUpdateTimeline; } diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx index a97cfefaf0393..daa64f9f16c83 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx @@ -6,7 +6,7 @@ import ApolloClient from 'apollo-client'; import React, { useEffect, useState, useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { defaultHeaders } from '../../components/timeline/body/column_headers/default_headers'; @@ -39,8 +39,6 @@ import { OpenTimelineResult, OnToggleShowNotes, OnDeleteOneTimeline, - OpenTimelineDispatchProps, - OpenTimelineReduxProps, } from './types'; import { DEFAULT_SORT_FIELD, DEFAULT_SORT_DIRECTION } from './constants'; @@ -55,8 +53,7 @@ interface OwnProps { export type OpenTimelineOwnProps = OwnProps & Pick & - OpenTimelineDispatchProps & - OpenTimelineReduxProps; + PropsFromRedux; /** Returns a collection of selected timeline ids */ export const getSelectedTimelineIds = (selectedItems: OpenTimelineResult[]): string[] => @@ -346,7 +343,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateTimeline: dispatchUpdateTimeline(dispatch), }); -export const StatefulOpenTimeline = connect( - makeMapStateToProps, - mapDispatchToProps -)(StatefulOpenTimelineComponent); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulOpenTimeline = connector(StatefulOpenTimelineComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts b/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts index e5e85ccf0954a..b14bb1cf86d31 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts @@ -4,11 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ActionCreator } from 'typescript-fsa'; - import { AllTimelinesVariables } from '../../containers/timeline/all'; import { TimelineModel } from '../../store/timeline/model'; -import { ColumnHeader } from '../timeline/body/column_headers/column_header'; import { NoteResult } from '../../graphql/types'; /** The users who added a timeline to favorites */ @@ -163,17 +160,3 @@ export type DispatchUpdateTimeline = ({ timeline, to, }: UpdateTimeline) => () => void; - -export interface OpenTimelineDispatchProps { - updateTimeline: DispatchUpdateTimeline; - createNewTimeline: ActionCreator<{ - id: string; - columns: ColumnHeader[]; - show?: boolean; - }>; - updateIsLoading: ActionCreator<{ id: string; isLoading: boolean }>; -} - -export interface OpenTimelineReduxProps { - timeline: TimelineModel; -} diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx index f5485922647ca..853ba7ae23414 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx @@ -8,8 +8,7 @@ import { has } from 'lodash/fp'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { hostsActions } from '../../../../store/hosts'; import { AuthenticationsEdges } from '../../../../graphql/types'; @@ -40,24 +39,6 @@ interface OwnProps { type: hostsModel.HostsType; } -interface AuthenticationTableReduxProps { - activePage: number; - limit: number; -} - -interface AuthenticationTableDispatchProps { - updateTableActivePage: ActionCreator<{ - activePage: number; - hostsType: hostsModel.HostsType; - tableType: hostsModel.HostsTableType; - }>; - updateTableLimit: ActionCreator<{ - limit: number; - hostsType: hostsModel.HostsType; - tableType: hostsModel.HostsTableType; - }>; -} - export type AuthTableColumns = [ Columns, Columns, @@ -70,9 +51,7 @@ export type AuthTableColumns = [ Columns ]; -type AuthenticationTableProps = OwnProps & - AuthenticationTableReduxProps & - AuthenticationTableDispatchProps; +type AuthenticationTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -154,10 +133,16 @@ const makeMapStateToProps = () => { }; }; -export const AuthenticationTable = connect(makeMapStateToProps, { +const mapDispatchToProps = { updateTableActivePage: hostsActions.updateTableActivePage, updateTableLimit: hostsActions.updateTableLimit, -})(AuthenticationTableComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const AuthenticationTable = connector(AuthenticationTableComponent); const getAuthenticationColumns = (): AuthTableColumns => [ { diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.tsx index 79bdf5c4b8315..0f56ef53ac081 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.tsx @@ -5,8 +5,7 @@ */ import React, { useMemo, useCallback } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { IIndexPattern } from 'src/plugins/data/public'; import { hostsActions } from '../../../../store/actions'; import { @@ -46,30 +45,6 @@ interface OwnProps { type: hostsModel.HostsType; } -interface HostsTableReduxProps { - activePage: number; - direction: Direction; - limit: number; - sortField: HostsFields; -} - -interface HostsTableDispatchProps { - updateHostsSort: ActionCreator<{ - hostsType: hostsModel.HostsType; - sort: HostsSortField; - }>; - updateTableActivePage: ActionCreator<{ - activePage: number; - hostsType: hostsModel.HostsType; - tableType: hostsModel.HostsTableType; - }>; - updateTableLimit: ActionCreator<{ - hostsType: hostsModel.HostsType; - limit: number; - tableType: hostsModel.HostsTableType; - }>; -} - export type HostsTableColumns = [ Columns, Columns, @@ -77,7 +52,7 @@ export type HostsTableColumns = [ Columns ]; -type HostsTableProps = OwnProps & HostsTableReduxProps & HostsTableDispatchProps; +type HostsTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -217,10 +192,16 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const HostsTable = connect(makeMapStateToProps, { +const mapDispatchToProps = { updateHostsSort: hostsActions.updateHostsSort, updateTableActivePage: hostsActions.updateTableActivePage, updateTableLimit: hostsActions.updateTableLimit, -})(HostsTableComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const HostsTable = connector(HostsTableComponent); HostsTable.displayName = 'HostsTable'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx index b4c01053f0e9c..12744ddafa396 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx @@ -7,8 +7,7 @@ /* eslint-disable react/display-name */ import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { hostsActions } from '../../../../store/actions'; import { UncommonProcessesEdges, UncommonProcessItem } from '../../../../graphql/types'; @@ -33,24 +32,6 @@ interface OwnProps { type: hostsModel.HostsType; } -interface UncommonProcessTableReduxProps { - activePage: number; - limit: number; -} - -interface UncommonProcessTableDispatchProps { - updateTableActivePage: ActionCreator<{ - activePage: number; - hostsType: hostsModel.HostsType; - tableType: hostsModel.HostsTableType; - }>; - updateTableLimit: ActionCreator<{ - limit: number; - hostsType: hostsModel.HostsType; - tableType: hostsModel.HostsTableType; - }>; -} - export type UncommonProcessTableColumns = [ Columns, Columns, @@ -60,9 +41,7 @@ export type UncommonProcessTableColumns = [ Columns ]; -type UncommonProcessTableProps = OwnProps & - UncommonProcessTableReduxProps & - UncommonProcessTableDispatchProps; +type UncommonProcessTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -150,10 +129,16 @@ const makeMapStateToProps = () => { return (state: State, { type }: OwnProps) => getUncommonProcessesSelector(state, type); }; -export const UncommonProcessTable = connect(makeMapStateToProps, { +const mapDispatchToProps = { updateTableActivePage: hostsActions.updateTableActivePage, updateTableLimit: hostsActions.updateTableLimit, -})(UncommonProcessTableComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const UncommonProcessTable = connector(UncommonProcessTableComponent); UncommonProcessTable.displayName = 'UncommonProcessTable'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx index e316f951a0363..f3fe98936a55d 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx @@ -6,8 +6,7 @@ import { isEqual } from 'lodash/fp'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { networkActions } from '../../../../store/actions'; import { @@ -37,22 +36,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface NetworkDnsTableReduxProps { - activePage: number; - limit: number; - sort: NetworkDnsSortField; - isPtrIncluded: boolean; -} - -interface NetworkDnsTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.AllNetworkTables; - updates: networkModel.TableUpdates; - }>; -} - -type NetworkDnsTableProps = OwnProps & NetworkDnsTableReduxProps & NetworkDnsTableDispatchProps; +type NetworkDnsTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -172,6 +156,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const NetworkDnsTable = connect(makeMapStateToProps, { +const mapDispatchToProps = { updateNetworkTable: networkActions.updateNetworkTable, -})(NetworkDnsTableComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const NetworkDnsTable = connector(NetworkDnsTableComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap index dfc1b2cf64e38..875a490d86be3 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`NetworkHttp Table Component rendering it renders the default NetworkHttp table 1`] = ` - { ); - expect(wrapper.find('Connect(NetworkHttpTableComponent)')).toMatchSnapshot(); + expect(wrapper.find('Connect(Component)')).toMatchSnapshot(); }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx index 58adc971b0101..87038eb6aaeeb 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx @@ -5,17 +5,10 @@ */ import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { networkActions } from '../../../../store/actions'; -import { - Direction, - NetworkHttpEdges, - NetworkHttpFields, - NetworkHttpSortField, -} from '../../../../graphql/types'; +import { Direction, NetworkHttpEdges, NetworkHttpFields } from '../../../../graphql/types'; import { networkModel, networkSelectors, State } from '../../../../store'; import { Criteria, ItemsPerRow, PaginatedTable } from '../../../paginated_table'; @@ -34,21 +27,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface NetworkHttpTableReduxProps { - activePage: number; - limit: number; - sort: NetworkHttpSortField; -} - -interface NetworkHttpTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.AllNetworkTables; - updates: networkModel.TableUpdates; - }>; -} - -type NetworkHttpTableProps = OwnProps & NetworkHttpTableReduxProps & NetworkHttpTableDispatchProps; +type NetworkHttpTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -61,91 +40,89 @@ const rowItems: ItemsPerRow[] = [ }, ]; -const NetworkHttpTableComponent = React.memo( - ({ - activePage, - data, - fakeTotalCount, - id, - isInspect, - limit, - loading, - loadPage, - showMorePagesIndicator, - sort, - totalCount, - type, - updateNetworkTable, - }) => { - const tableType = - type === networkModel.NetworkType.page - ? networkModel.NetworkTableType.http - : networkModel.IpDetailsTableType.http; - - const updateLimitPagination = useCallback( - newLimit => +const NetworkHttpTableComponent: React.FC = ({ + activePage, + data, + fakeTotalCount, + id, + isInspect, + limit, + loading, + loadPage, + showMorePagesIndicator, + sort, + totalCount, + type, + updateNetworkTable, +}) => { + const tableType = + type === networkModel.NetworkType.page + ? networkModel.NetworkTableType.http + : networkModel.IpDetailsTableType.http; + + const updateLimitPagination = useCallback( + newLimit => + updateNetworkTable({ + networkType: type, + tableType, + updates: { limit: newLimit }, + }), + [type, updateNetworkTable, tableType] + ); + + const updateActivePage = useCallback( + newPage => + updateNetworkTable({ + networkType: type, + tableType, + updates: { activePage: newPage }, + }), + [type, updateNetworkTable, tableType] + ); + + const onChange = useCallback( + (criteria: Criteria) => { + if (criteria.sort != null && criteria.sort.direction !== sort.direction) { updateNetworkTable({ networkType: type, tableType, - updates: { limit: newLimit }, - }), - [type, updateNetworkTable, tableType] - ); - - const updateActivePage = useCallback( - newPage => - updateNetworkTable({ - networkType: type, - tableType, - updates: { activePage: newPage }, - }), - [type, updateNetworkTable, tableType] - ); - - const onChange = useCallback( - (criteria: Criteria) => { - if (criteria.sort != null && criteria.sort.direction !== sort.direction) { - updateNetworkTable({ - networkType: type, - tableType, - updates: { - sort: { - direction: criteria.sort.direction as Direction, - }, + updates: { + sort: { + direction: criteria.sort.direction as Direction, }, - }); - } - }, - [tableType, sort.direction, type, updateNetworkTable] - ); - - const sorting = { field: `node.${NetworkHttpFields.requestCount}`, direction: sort.direction }; - - return ( - - ); - } -); + }, + }); + } + }, + [tableType, sort.direction, type, updateNetworkTable] + ); + + const sorting = { field: `node.${NetworkHttpFields.requestCount}`, direction: sort.direction }; + + return ( + + ); +}; NetworkHttpTableComponent.displayName = 'NetworkHttpTableComponent'; @@ -155,8 +132,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const NetworkHttpTable = compose>( - connect(makeMapStateToProps, { - updateNetworkTable: networkActions.updateNetworkTable, - }) -)(NetworkHttpTableComponent); +const mapDispatchToProps = { + updateNetworkTable: networkActions.updateNetworkTable, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const NetworkHttpTable = connector(React.memo(NetworkHttpTableComponent)); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.tsx index 6d14b52d3586d..37355a37fa6d7 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.tsx @@ -6,9 +6,7 @@ import { isEqual, last } from 'lodash/fp'; import React, { useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { IIndexPattern } from 'src/plugins/data/public'; import { networkActions } from '../../../../store/actions'; @@ -39,23 +37,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface NetworkTopCountriesTableReduxProps { - activePage: number; - limit: number; - sort: NetworkTopTablesSortField; -} - -interface NetworkTopCountriesTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.AllNetworkTables; - updates: networkModel.TableUpdates; - }>; -} - -type NetworkTopCountriesTableProps = OwnProps & - NetworkTopCountriesTableReduxProps & - NetworkTopCountriesTableDispatchProps; +type NetworkTopCountriesTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -197,8 +179,12 @@ const makeMapStateToProps = () => { getTopCountriesSelector(state, type, flowTargeted); }; -export const NetworkTopCountriesTable = compose>( - connect(makeMapStateToProps, { - updateNetworkTable: networkActions.updateNetworkTable, - }) -)(NetworkTopCountriesTableComponent); +const mapDispatchToProps = { + updateNetworkTable: networkActions.updateNetworkTable, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const NetworkTopCountriesTable = connector(NetworkTopCountriesTableComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.tsx index 7c1fcb2681a8c..c4f6dad0a47ed 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.tsx @@ -5,9 +5,7 @@ */ import { isEqual, last } from 'lodash/fp'; import React, { useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { networkActions } from '../../../../store/actions'; import { @@ -36,23 +34,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface NetworkTopNFlowTableReduxProps { - activePage: number; - limit: number; - sort: NetworkTopTablesSortField; -} - -interface NetworkTopNFlowTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.TopNTableType; - updates: networkModel.TableUpdates; - }>; -} - -type NetworkTopNFlowTableProps = OwnProps & - NetworkTopNFlowTableReduxProps & - NetworkTopNFlowTableDispatchProps; +type NetworkTopNFlowTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -180,8 +162,12 @@ const makeMapStateToProps = () => { getTopNFlowSelector(state, type, flowTargeted); }; -export const NetworkTopNFlowTable = compose>( - connect(makeMapStateToProps, { - updateNetworkTable: networkActions.updateNetworkTable, - }) -)(React.memo(NetworkTopNFlowTableComponent)); +const mapDispatchToProps = { + updateNetworkTable: networkActions.updateNetworkTable, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const NetworkTopNFlowTable = connector(React.memo(NetworkTopNFlowTableComponent)); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx index 95c0fff054440..77abae68b76bf 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx @@ -6,9 +6,7 @@ import { isEqual } from 'lodash/fp'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { networkActions } from '../../../../store/network'; import { TlsEdges, TlsSortField, TlsFields, Direction } from '../../../../graphql/types'; @@ -29,21 +27,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface TlsTableReduxProps { - activePage: number; - limit: number; - sort: TlsSortField; -} - -interface TlsTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.AllNetworkTables; - updates: networkModel.TableUpdates; - }>; -} - -type TlsTableProps = OwnProps & TlsTableReduxProps & TlsTableDispatchProps; +type TlsTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -152,11 +136,15 @@ const makeMapStateToProps = () => { return (state: State, { type }: OwnProps) => getTlsSelector(state, type); }; -export const TlsTable = compose>( - connect(makeMapStateToProps, { - updateNetworkTable: networkActions.updateNetworkTable, - }) -)(TlsTableComponent); +const mapDispatchToProps = { + updateNetworkTable: networkActions.updateNetworkTable, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const TlsTable = connector(TlsTableComponent); const getSortField = (sortField: TlsSortField): SortingBasicTable => ({ field: `node.${sortField.field}`, diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.tsx index f4f14c7c009dc..bc7ef2314add4 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.tsx @@ -6,8 +6,7 @@ import { isEqual } from 'lodash/fp'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { networkActions } from '../../../../store/network'; import { @@ -38,21 +37,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface UsersTableReduxProps { - activePage: number; - limit: number; - sort: UsersSortField; -} - -interface UsersTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.AllNetworkTables; - updates: networkModel.TableUpdates; - }>; -} - -type UsersTableProps = OwnProps & UsersTableReduxProps & UsersTableDispatchProps; +type UsersTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -159,9 +144,15 @@ const makeMapStateToProps = () => { }); }; -export const UsersTable = connect(makeMapStateToProps, { +const mapDispatchToProps = { updateNetworkTable: networkActions.updateNetworkTable, -})(UsersTableComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const UsersTable = connector(UsersTableComponent); const getSortField = (sortField: UsersSortField): SortingBasicTable => { switch (sortField.field) { diff --git a/x-pack/legacy/plugins/siem/public/components/recent_timelines/index.tsx b/x-pack/legacy/plugins/siem/public/components/recent_timelines/index.tsx index d5157e81b0fc8..41eb137742963 100644 --- a/x-pack/legacy/plugins/siem/public/components/recent_timelines/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/recent_timelines/index.tsx @@ -7,14 +7,14 @@ import ApolloClient from 'apollo-client'; import { EuiHorizontalRule, EuiLink, EuiText } from '@elastic/eui'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { ActionCreator } from 'typescript-fsa'; import { AllTimelinesQuery } from '../../containers/timeline/all'; import { SortFieldTimeline, Direction } from '../../graphql/types'; import { queryTimelineById, dispatchUpdateTimeline } from '../open_timeline/helpers'; -import { DispatchUpdateTimeline, OnOpenTimeline } from '../open_timeline/types'; +import { OnOpenTimeline } from '../open_timeline/types'; import { LoadingPlaceholders } from '../page/overview/loading_placeholders'; import { updateIsLoading as dispatchUpdateIsLoading } from '../../store/timeline/actions'; @@ -31,12 +31,7 @@ interface OwnProps { filterBy: FilterMode; } -interface DispatchProps { - updateIsLoading: ({ id, isLoading }: { id: string; isLoading: boolean }) => void; - updateTimeline: DispatchUpdateTimeline; -} - -export type Props = OwnProps & DispatchProps; +export type Props = OwnProps & PropsFromRedux; const StatefulRecentTimelinesComponent = React.memo( ({ apolloClient, filterBy, updateIsLoading, updateTimeline }) => { @@ -100,7 +95,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateTimeline: dispatchUpdateTimeline(dispatch), }); -export const StatefulRecentTimelines = connect( - null, - mapDispatchToProps -)(StatefulRecentTimelinesComponent); +const connector = connect(null, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulRecentTimelines = connector(StatefulRecentTimelinesComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx index 2c3f677cc585d..cb5729ad8e26e 100644 --- a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx @@ -6,7 +6,7 @@ import { getOr, isEqual, set } from 'lodash/fp'; import React, { memo, useEffect, useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { Subscription } from 'rxjs'; import styled from 'styled-components'; @@ -34,29 +34,6 @@ import { import { timelineActions, hostsActions, networkActions } from '../../store/actions'; import { useKibana } from '../../lib/kibana'; -interface SiemSearchBarRedux { - end: number; - fromStr: string; - isLoading: boolean; - queries: inputsModel.GlobalGraphqlQuery[]; - filterQuery: Query; - savedQuery?: SavedQuery; - start: number; - toStr: string; -} - -interface SiemSearchBarDispatch { - updateSearch: DispatchUpdateSearch; - setSavedQuery: ({ - id, - savedQuery, - }: { - id: InputsModelId; - savedQuery: SavedQuery | undefined; - }) => void; - setSearchBarFilter: ({ id, filters }: { id: InputsModelId; filters: Filter[] }) => void; -} - interface SiemSearchBarProps { id: InputsModelId; indexPattern: IIndexPattern; @@ -70,7 +47,7 @@ const SearchBarContainer = styled.div` } `; -const SearchBarComponent = memo( +const SearchBarComponent = memo( ({ end, filterQuery, @@ -322,15 +299,7 @@ interface UpdateReduxSearchBar extends OnTimeChangeProps { updateTime: boolean; } -type DispatchUpdateSearch = ({ - end, - id, - isQuickSelection, - start, - timelineId, -}: UpdateReduxSearchBar) => void; - -const dispatchUpdateSearch = (dispatch: Dispatch) => ({ +export const dispatchUpdateSearch = (dispatch: Dispatch) => ({ end, filters, id, @@ -403,4 +372,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ dispatch(inputsActions.setSearchBarFilter({ id, filters })), }); -export const SiemSearchBar = connect(makeMapStateToProps, mapDispatchToProps)(SearchBarComponent); +export const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const SiemSearchBar = connector(SearchBarComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx b/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx index 0877906c721ce..ad38a7d61bcba 100644 --- a/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx @@ -14,7 +14,7 @@ import { } from '@elastic/eui'; import { getOr, take, isEmpty } from 'lodash/fp'; import React, { useState, useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { DEFAULT_TIMEPICKER_QUICK_RANGES } from '../../../common/constants'; @@ -34,7 +34,7 @@ import { queriesSelector, kqlQuerySelector, } from './selectors'; -import { InputsRange, Policy } from '../../store/inputs/model'; +import { InputsRange } from '../../store/inputs/model'; const MAX_RECENTLY_USED_RANGES = 9; @@ -44,19 +44,6 @@ interface Range { display: string; } -interface SuperDatePickerStateRedux { - duration: number; - end: number; - fromStr: string; - isLoading: boolean; - kind: string; - kqlQuery: inputsModel.GlobalKqlQuery; - policy: Policy['kind']; - queries: inputsModel.GlobalGraphqlQuery[]; - start: number; - toStr: string; -} - interface UpdateReduxTime extends OnTimeChangeProps { id: InputsModelId; kql?: inputsModel.GlobalKqlQuery | undefined; @@ -76,22 +63,13 @@ export type DispatchUpdateReduxTime = ({ timelineId, }: UpdateReduxTime) => ReturnUpdateReduxTime; -interface SuperDatePickerDispatchProps { - setDuration: ({ id, duration }: { id: InputsModelId; duration: number }) => void; - startAutoReload: ({ id }: { id: InputsModelId }) => void; - stopAutoReload: ({ id }: { id: InputsModelId }) => void; - updateReduxTime: DispatchUpdateReduxTime; -} - interface OwnProps { disabled?: boolean; id: InputsModelId; timelineId?: string; } -export type SuperDatePickerProps = OwnProps & - SuperDatePickerDispatchProps & - SuperDatePickerStateRedux; +export type SuperDatePickerProps = OwnProps & PropsFromRedux; export const SuperDatePickerComponent = React.memo( ({ @@ -308,9 +286,9 @@ export const makeMapStateToProps = () => { fromStr: getFromStrSelector(inputsRange), isLoading: getIsLoadingSelector(inputsRange), kind: getKindSelector(inputsRange), - kqlQuery: getKqlQuerySelector(inputsRange), + kqlQuery: getKqlQuerySelector(inputsRange) as inputsModel.GlobalKqlQuery, policy: getPolicySelector(inputsRange), - queries: getQueriesSelector(inputsRange), + queries: getQueriesSelector(inputsRange) as inputsModel.GlobalGraphqlQuery[], start: getStartSelector(inputsRange), toStr: getToStrSelector(inputsRange), }; @@ -328,7 +306,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateReduxTime: dispatchUpdateReduxTime(dispatch), }); -export const SuperDatePicker = connect( - makeMapStateToProps, - mapDispatchToProps -)(SuperDatePickerComponent); +export const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const SuperDatePicker = connector(SuperDatePickerComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/auto_save_warning/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/auto_save_warning/index.tsx index c2dfda6a81ce4..90d0738aba72f 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/auto_save_warning/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/auto_save_warning/index.tsx @@ -12,41 +12,17 @@ import { } from '@elastic/eui'; import { getOr } from 'lodash/fp'; import React from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { State, timelineSelectors } from '../../../store'; import { setTimelineRangeDatePicker as dispatchSetTimelineRangeDatePicker } from '../../../store/inputs/actions'; -import { TimelineModel } from '../../../store/timeline/model'; import * as i18n from './translations'; import { timelineActions } from '../../../store/timeline'; import { AutoSavedWarningMsg } from '../../../store/timeline/types'; import { useStateToaster } from '../../toasters'; -interface ReduxProps { - timelineId: string | null; - newTimelineModel: TimelineModel | null; -} - -interface DispatchProps { - setTimelineRangeDatePicker: ActionCreator<{ - from: number; - to: number; - }>; - updateAutoSaveMsg: ActionCreator<{ - timelineId: string | null; - newTimelineModel: TimelineModel | null; - }>; - updateTimeline: ActionCreator<{ - id: string; - timeline: TimelineModel; - }>; -} - -type OwnProps = ReduxProps & DispatchProps; - -const AutoSaveWarningMsgComponent = React.memo( +const AutoSaveWarningMsgComponent = React.memo( ({ newTimelineModel, setTimelineRangeDatePicker, @@ -106,8 +82,14 @@ const mapStateToProps = (state: State) => { }; }; -export const AutoSaveWarningMsg = connect(mapStateToProps, { +const mapDispatchToProps = { setTimelineRangeDatePicker: dispatchSetTimelineRangeDatePicker, updateAutoSaveMsg: timelineActions.updateAutoSaveMsg, updateTimeline: timelineActions.updateTimeline, -})(AutoSaveWarningMsgComponent); +}; + +const connector = connect(mapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const AutoSaveWarningMsg = connector(AutoSaveWarningMsgComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx index 239d8a9d77916..cf35c8e565bbc 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx @@ -66,7 +66,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} @@ -110,7 +109,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} @@ -154,7 +152,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} @@ -200,7 +197,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} @@ -293,7 +289,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} @@ -339,7 +334,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx index f00da48266927..7f689a877c6b7 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx @@ -54,7 +54,6 @@ export interface BodyProps { onUpdateColumns: OnUpdateColumns; onUnPinEvent: OnUnPinEvent; pinnedEventIds: Readonly>; - range: string; rowRenderers: RowRenderer[]; selectedEventIds: Readonly>; showCheckboxes: boolean; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx index edf0613ac2693..ffb5f2a206f4d 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx @@ -7,13 +7,12 @@ import { noop } from 'lodash/fp'; import memoizeOne from 'memoize-one'; import React, { useCallback, useEffect } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { BrowserFields } from '../../../containers/source'; -import { TimelineItem, TimelineNonEcsData } from '../../../graphql/types'; +import { TimelineItem } from '../../../graphql/types'; import { Note } from '../../../lib/note'; -import { appModel, appSelectors, State, timelineSelectors } from '../../../store'; +import { appSelectors, State, timelineSelectors } from '../../../store'; import { AddNoteToEvent, UpdateNote } from '../../notes/helpers'; import { OnColumnRemoved, @@ -46,59 +45,7 @@ interface OwnProps { toggleColumn: (column: ColumnHeader) => void; } -interface ReduxProps { - columnHeaders: ColumnHeader[]; - eventIdToNoteIds: Readonly>; - isSelectAllChecked: boolean; - loadingEventIds: Readonly; - notesById: appModel.NotesById; - pinnedEventIds: Readonly>; - range?: string; - selectedEventIds: Readonly>; - showCheckboxes: boolean; - showRowRenderers: boolean; -} - -interface DispatchProps { - addNoteToEvent?: ActionCreator<{ id: string; noteId: string; eventId: string }>; - applyDeltaToColumnWidth?: ActionCreator<{ - id: string; - columnId: string; - delta: number; - }>; - clearSelected?: ActionCreator<{ - id: string; - }>; - pinEvent?: ActionCreator<{ - id: string; - eventId: string; - }>; - removeColumn?: ActionCreator<{ - id: string; - columnId: string; - }>; - setSelected?: ActionCreator<{ - id: string; - eventIds: Record; - isSelected: boolean; - isSelectAllChecked: boolean; - }>; - unPinEvent?: ActionCreator<{ - id: string; - eventId: string; - }>; - updateColumns?: ActionCreator<{ - id: string; - columns: ColumnHeader[]; - }>; - updateSort?: ActionCreator<{ - id: string; - sort: Sort; - }>; - updateNote?: ActionCreator<{ note: Note }>; -} - -type StatefulBodyComponentProps = OwnProps & ReduxProps & DispatchProps; +type StatefulBodyComponentProps = OwnProps & PropsFromRedux; export const emptyColumnHeaders: ColumnHeader[] = []; @@ -118,7 +65,6 @@ const StatefulBodyComponent = React.memo( notesById, pinEvent, pinnedEventIds, - range, removeColumn, selectedEventIds, setSelected, @@ -234,7 +180,6 @@ const StatefulBodyComponent = React.memo( onUnPinEvent={onUnPinEvent} onUpdateColumns={onUpdateColumns} pinnedEventIds={pinnedEventIds} - range={range!} rowRenderers={showRowRenderers ? rowRenderers : [plainRowRenderer]} selectedEventIds={selectedEventIds} showCheckboxes={showCheckboxes} @@ -260,7 +205,6 @@ const StatefulBodyComponent = React.memo( prevProps.selectedEventIds === nextProps.selectedEventIds && prevProps.showCheckboxes === nextProps.showCheckboxes && prevProps.showRowRenderers === nextProps.showRowRenderers && - prevProps.range === nextProps.range && prevProps.sort === nextProps.sort ); } @@ -307,7 +251,7 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const StatefulBody = connect(makeMapStateToProps, { +const mapDispatchToProps = { addNoteToEvent: timelineActions.addNoteToEvent, applyDeltaToColumnWidth: timelineActions.applyDeltaToColumnWidth, clearSelected: timelineActions.clearSelected, @@ -319,4 +263,10 @@ export const StatefulBody = connect(makeMapStateToProps, { updateColumns: timelineActions.updateColumns, updateNote: appActions.updateNote, updateSort: timelineActions.updateSort, -})(StatefulBodyComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulBody = connector(StatefulBodyComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx index 4b1e723f1bb3a..65c539d77a16b 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx @@ -5,37 +5,21 @@ */ import { memo, useEffect } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { IIndexPattern } from 'src/plugins/data/public'; -import { inputsModel, KueryFilterQuery, timelineSelectors, State } from '../../store'; +import { timelineSelectors, State } from '../../store'; import { inputsActions } from '../../store/actions'; import { InputsModelId } from '../../store/inputs/constants'; import { useUpdateKql } from '../../utils/kql/use_update_kql'; -interface TimelineKqlFetchRedux { - kueryFilterQuery: KueryFilterQuery | null; - kueryFilterQueryDraft: KueryFilterQuery | null; -} - -interface TimelineKqlFetchDispatch { - setTimelineQuery: ActionCreator<{ - id: string; - inputId: InputsModelId; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch | inputsModel.RefetchKql | null; - }>; -} - export interface TimelineKqlFetchProps { id: string; indexPattern: IIndexPattern; inputId: InputsModelId; } -type OwnProps = TimelineKqlFetchProps & TimelineKqlFetchRedux & TimelineKqlFetchDispatch; +type OwnProps = TimelineKqlFetchProps & PropsFromRedux; const TimelineKqlFetchComponent = memo( ({ id, indexPattern, inputId, kueryFilterQuery, kueryFilterQueryDraft, setTimelineQuery }) => { @@ -70,6 +54,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const TimelineKqlFetch = connect(makeMapStateToProps, { +const mapDispatchToProps = { setTimelineQuery: inputsActions.setQuery, -})(TimelineKqlFetchComponent); +}; + +export const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const TimelineKqlFetch = connector(TimelineKqlFetchComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx index b6a57ebacb11c..34f760e411ed4 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx @@ -6,21 +6,16 @@ import { isEqual } from 'lodash/fp'; import React, { useEffect, useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; - -import { Filter } from '../../../../../../../src/plugins/data/public'; +import { connect, ConnectedProps } from 'react-redux'; import { WithSource } from '../../containers/source'; import { inputsModel, inputsSelectors, State, timelineSelectors } from '../../store'; import { timelineActions } from '../../store/actions'; -import { EventType, KqlMode, timelineDefaults, TimelineModel } from '../../store/timeline/model'; +import { timelineDefaults, TimelineModel } from '../../store/timeline/model'; import { useSignalIndex } from '../../containers/detection_engine/signals/use_signal_index'; import { ColumnHeader } from './body/column_headers/column_header'; -import { DataProvider, QueryOperator } from './data_providers/data_provider'; import { defaultHeaders } from './body/column_headers/default_headers'; -import { Sort } from './body/sort'; import { OnChangeDataProviderKqlQuery, OnChangeDroppableAndProvider, @@ -38,103 +33,7 @@ export interface OwnProps { flyoutHeight: number; } -interface StateReduxProps { - activePage?: number; - columns: ColumnHeader[]; - dataProviders?: DataProvider[]; - eventType: EventType; - end: number; - filters: Filter[]; - isLive: boolean; - itemsPerPage?: number; - itemsPerPageOptions?: number[]; - kqlMode: KqlMode; - kqlQueryExpression: string; - pageCount?: number; - sort?: Sort; - start: number; - show?: boolean; - showCallOutUnauthorizedMsg: boolean; -} - -interface DispatchProps { - createTimeline?: ActionCreator<{ - id: string; - columns: ColumnHeader[]; - show?: boolean; - }>; - addProvider?: ActionCreator<{ - id: string; - provider: DataProvider; - }>; - onDataProviderEdited?: ActionCreator<{ - andProviderId?: string; - excluded: boolean; - field: string; - id: string; - operator: QueryOperator; - providerId: string; - value: string | number; - }>; - updateColumns?: ActionCreator<{ - id: string; - category: string; - columns: ColumnHeader[]; - }>; - updateProviders?: ActionCreator<{ - id: string; - providers: DataProvider[]; - }>; - removeColumn?: ActionCreator<{ - id: string; - columnId: string; - }>; - removeProvider?: ActionCreator<{ - id: string; - providerId: string; - andProviderId?: string; - }>; - updateDataProviderEnabled?: ActionCreator<{ - id: string; - providerId: string; - enabled: boolean; - andProviderId?: string; - }>; - updateDataProviderExcluded?: ActionCreator<{ - id: string; - excluded: boolean; - providerId: string; - andProviderId?: string; - }>; - updateDataProviderKqlQuery?: ActionCreator<{ - id: string; - kqlQuery: string; - providerId: string; - }>; - updateItemsPerPage?: ActionCreator<{ - id: string; - itemsPerPage: number; - }>; - updateItemsPerPageOptions?: ActionCreator<{ - id: string; - itemsPerPageOptions: number[]; - }>; - updatePageIndex?: ActionCreator<{ - id: string; - activePage: number; - }>; - updateHighlightedDropAndProviderId?: ActionCreator<{ - id: string; - providerId: string; - }>; - upsertColumn?: ActionCreator<{ - column: ColumnHeader; - id: string; - index: number; - }>; -} - -type Props = OwnProps & StateReduxProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const StatefulTimelineComponent = React.memo( ({ @@ -169,7 +68,12 @@ const StatefulTimelineComponent = React.memo( const { loading, signalIndexExists, signalIndexName } = useSignalIndex(); const indexToAdd = useMemo(() => { - if (signalIndexExists && signalIndexName != null && ['signal', 'all'].includes(eventType)) { + if ( + eventType && + signalIndexExists && + signalIndexName != null && + ['signal', 'all'].includes(eventType) + ) { return [signalIndexName]; } return []; @@ -300,7 +204,6 @@ const StatefulTimelineComponent = React.memo( }, (prevProps, nextProps) => { return ( - prevProps.activePage === nextProps.activePage && prevProps.eventType === nextProps.eventType && prevProps.end === nextProps.end && prevProps.flyoutHeaderHeight === nextProps.flyoutHeaderHeight && @@ -310,7 +213,6 @@ const StatefulTimelineComponent = React.memo( prevProps.itemsPerPage === nextProps.itemsPerPage && prevProps.kqlMode === nextProps.kqlMode && prevProps.kqlQueryExpression === nextProps.kqlQueryExpression && - prevProps.pageCount === nextProps.pageCount && prevProps.show === nextProps.show && prevProps.showCallOutUnauthorizedMsg === nextProps.showCallOutUnauthorizedMsg && prevProps.start === nextProps.start && @@ -344,7 +246,7 @@ const makeMapStateToProps = () => { show, sort, } = timeline; - const kqlQueryExpression = getKqlQueryTimeline(state, id); + const kqlQueryExpression = getKqlQueryTimeline(state, id)!; const timelineFilter = kqlMode === 'filter' ? filters || [] : []; @@ -369,7 +271,7 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const StatefulTimeline = connect(makeMapStateToProps, { +const mapDispatchToProps = { addProvider: timelineActions.addProvider, createTimeline: timelineActions.createTimeline, onDataProviderEdited: timelineActions.dataProviderEdited, @@ -384,4 +286,10 @@ export const StatefulTimeline = connect(makeMapStateToProps, { updateItemsPerPageOptions: timelineActions.updateItemsPerPageOptions, updateSort: timelineActions.updateSort, upsertColumn: timelineActions.upsertColumn, -})(StatefulTimelineComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulTimeline = connector(StatefulTimelineComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/refetch_timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/refetch_timeline.tsx index c804ccf658296..3d2ec0683f091 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/refetch_timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/refetch_timeline.tsx @@ -5,33 +5,21 @@ */ import React, { useEffect } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { inputsModel } from '../../store'; import { inputsActions } from '../../store/actions'; import { InputsModelId } from '../../store/inputs/constants'; -interface TimelineRefetchDispatch { - setTimelineQuery: ActionCreator<{ - id: string; - inputId: InputsModelId; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch | inputsModel.RefetchKql | null; - }>; -} - export interface TimelineRefetchProps { id: string; inputId: InputsModelId; inspect: inputsModel.InspectQuery | null; loading: boolean; - refetch: inputsModel.Refetch | null; + refetch: inputsModel.Refetch; } -type OwnProps = TimelineRefetchProps & TimelineRefetchDispatch; +type OwnProps = TimelineRefetchProps & PropsFromRedux; const TimelineRefetchComponent: React.FC = ({ id, @@ -48,8 +36,12 @@ const TimelineRefetchComponent: React.FC = ({ return null; }; -export const TimelineRefetch = compose>( - connect(null, { - setTimelineQuery: inputsActions.setQuery, - }) -)(React.memo(TimelineRefetchComponent)); +const mapDispatchToProps = { + setTimelineQuery: inputsActions.setQuery, +}; + +const connector = connect(null, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const TimelineRefetch = connector(React.memo(TimelineRefetchComponent)); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx index 3c47823fbbc3b..2b139d3948fe1 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx @@ -6,7 +6,7 @@ import { getOr, isEqual } from 'lodash/fp'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { Filter, IIndexPattern } from '../../../../../../../../src/plugins/data/public'; @@ -22,8 +22,7 @@ import { } from '../../../store'; import { timelineActions } from '../../../store/actions'; import { KqlMode, timelineDefaults, TimelineModel, EventType } from '../../../store/timeline/model'; -import { DispatchUpdateReduxTime, dispatchUpdateReduxTime } from '../../super_date_picker'; -import { DataProvider } from '../data_providers/data_provider'; +import { dispatchUpdateReduxTime } from '../../super_date_picker'; import { SearchOrFilter } from './search_or_filter'; interface OwnProps { @@ -32,45 +31,7 @@ interface OwnProps { timelineId: string; } -interface StateReduxProps { - dataProviders: DataProvider[]; - eventType: EventType; - filters: Filter[]; - filterQuery: KueryFilterQuery; - filterQueryDraft: KueryFilterQuery; - from: number; - fromStr: string; - isRefreshPaused: boolean; - kqlMode: KqlMode; - refreshInterval: number; - savedQueryId: string | null; - to: number; - toStr: string; -} - -interface DispatchProps { - applyKqlFilterQuery: ({ - id, - filterQuery, - }: { - id: string; - filterQuery: SerializedFilterQuery; - }) => void; - updateEventType: ({ id, eventType }: { id: string; eventType: EventType }) => void; - updateKqlMode: ({ id, kqlMode }: { id: string; kqlMode: KqlMode }) => void; - setKqlFilterQueryDraft: ({ - id, - filterQueryDraft, - }: { - id: string; - filterQueryDraft: KueryFilterQuery; - }) => void; - setSavedQueryId: ({ id, savedQueryId }: { id: string; savedQueryId: string | null }) => void; - setFilters: ({ id, filters }: { id: string; filters: Filter[] }) => void; - updateReduxTime: DispatchUpdateReduxTime; -} - -type Props = OwnProps & StateReduxProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const StatefulSearchOrFilterComponent = React.memo( ({ @@ -217,17 +178,17 @@ const makeMapStateToProps = () => { return { dataProviders: timeline.dataProviders, eventType: timeline.eventType ?? 'raw', - filterQuery: getKqlFilterQuery(state, timelineId), - filterQueryDraft: getKqlFilterQueryDraft(state, timelineId), - filters: timeline.filters, + filterQuery: getKqlFilterQuery(state, timelineId)!, + filterQueryDraft: getKqlFilterQueryDraft(state, timelineId)!, + filters: timeline.filters!, from: input.timerange.from, - fromStr: input.timerange.fromStr, + fromStr: input.timerange.fromStr!, isRefreshPaused: policy.kind === 'manual', kqlMode: getOr('filter', 'kqlMode', timeline), refreshInterval: policy.duration, savedQueryId: getOr(null, 'savedQueryId', timeline), to: input.timerange.to, - toStr: input.timerange.toStr, + toStr: input.timerange.toStr!, }; }; return mapStateToProps; @@ -265,7 +226,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateReduxTime: dispatchUpdateReduxTime(dispatch), }); -export const StatefulSearchOrFilter = connect( - makeMapStateToProps, - mapDispatchToProps -)(StatefulSearchOrFilterComponent); +export const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulSearchOrFilter = connector(StatefulSearchOrFilterComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx index 9d70b69124f30..09457c8f0285a 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx @@ -60,7 +60,7 @@ interface Props { columns: ColumnHeader[]; dataProviders: DataProvider[]; end: number; - eventType: EventType; + eventType?: EventType; filters: Filter[]; flyoutHeaderHeight: number; flyoutHeight: number; diff --git a/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx b/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx index d77e0215f8353..caf597d02c835 100644 --- a/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx @@ -5,12 +5,10 @@ */ import React, { useState, useEffect } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { inputsModel, inputsSelectors, State } from '../../store'; import { inputsActions } from '../../store/actions'; -import { InputsModelId } from '../../store/inputs/constants'; interface SetQuery { id: string; @@ -19,10 +17,6 @@ interface SetQuery { refetch: inputsModel.Refetch | inputsModel.RefetchKql; } -interface GlobalQuery extends SetQuery { - inputId: InputsModelId; -} - export interface GlobalTimeArgs { from: number; to: number; @@ -31,21 +25,11 @@ export interface GlobalTimeArgs { isInitializing: boolean; } -interface GlobalTimeDispatch { - setGlobalQuery: ActionCreator; - deleteAllQuery: ActionCreator<{ id: InputsModelId }>; - deleteOneQuery: ActionCreator<{ inputId: InputsModelId; id: string }>; -} - -interface GlobalTimeReduxState { - from: number; - to: number; -} interface OwnProps { children: (args: GlobalTimeArgs) => React.ReactNode; } -type GlobalTimeProps = OwnProps & GlobalTimeReduxState & GlobalTimeDispatch; +type GlobalTimeProps = OwnProps & PropsFromRedux; export const GlobalTimeComponent: React.FC = ({ children, @@ -88,8 +72,14 @@ const mapStateToProps = (state: State) => { }; }; -export const GlobalTime = connect(mapStateToProps, { +const mapDispatchToProps = { deleteAllQuery: inputsActions.deleteAllQuery, deleteOneQuery: inputsActions.deleteOneQuery, setGlobalQuery: inputsActions.setQuery, -})(React.memo(GlobalTimeComponent)); +}; + +export const connector = connect(mapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const GlobalTime = connector(React.memo(GlobalTimeComponent)); diff --git a/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx b/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx index 9576c66c4c9a5..ade94c430c6ef 100644 --- a/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetIpOverviewQuery, IpOverviewData } from '../../graphql/types'; @@ -28,17 +28,13 @@ export interface IpOverviewArgs { refetch: inputsModel.Refetch; } -export interface IpOverviewReduxProps { - isInspected: boolean; -} - export interface IpOverviewProps extends QueryTemplateProps { children: (args: IpOverviewArgs) => React.ReactNode; type: networkModel.NetworkType; ip: string; } -const IpOverviewComponentQuery = React.memo( +const IpOverviewComponentQuery = React.memo( ({ id = ID, isInspected, children, filterQuery, skip, sourceId, ip }) => ( query={ipOverviewQuery} @@ -81,4 +77,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const IpOverviewQuery = connect(makeMapStateToProps)(IpOverviewComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const IpOverviewQuery = connector(IpOverviewComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx b/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx index 501bc8472b5e2..de9d54b1a185c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { KpiHostDetailsData, GetKpiHostDetailsQuery } from '../../graphql/types'; @@ -32,11 +32,7 @@ export interface QueryKpiHostDetailsProps extends QueryTemplateProps { children: (args: KpiHostDetailsArgs) => React.ReactNode; } -export interface KpiHostDetailsReducer { - isInspected: boolean; -} - -const KpiHostDetailsComponentQuery = React.memo( +const KpiHostDetailsComponentQuery = React.memo( ({ id = ID, children, endDate, filterQuery, isInspected, skip, sourceId, startDate }) => ( query={kpiHostDetailsQuery} @@ -82,4 +78,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const KpiHostDetailsQuery = connect(makeMapStateToProps)(KpiHostDetailsComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const KpiHostDetailsQuery = connector(KpiHostDetailsComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx b/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx index 32472ba6deedf..5be2423e8a162 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetKpiHostsQuery, KpiHostsData } from '../../graphql/types'; @@ -28,15 +28,11 @@ export interface KpiHostsArgs { refetch: inputsModel.Refetch; } -export interface KpiHostsReducer { - isInspected: boolean; -} - export interface KpiHostsProps extends QueryTemplateProps { children: (args: KpiHostsArgs) => React.ReactNode; } -const KpiHostsComponentQuery = React.memo( +const KpiHostsComponentQuery = React.memo( ({ id = ID, children, endDate, filterQuery, isInspected, skip, sourceId, startDate }) => ( query={kpiHostsQuery} @@ -82,4 +78,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const KpiHostsQuery = connect(makeMapStateToProps)(KpiHostsComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const KpiHostsQuery = connector(KpiHostsComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx b/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx index 52b8814958ba0..338cdc39b178c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetKpiNetworkQuery, KpiNetworkData } from '../../graphql/types'; @@ -28,15 +28,11 @@ export interface KpiNetworkArgs { refetch: inputsModel.Refetch; } -export interface KpiNetworkReducer { - isInspected: boolean; -} - export interface KpiNetworkProps extends QueryTemplateProps { children: (args: KpiNetworkArgs) => React.ReactNode; } -const KpiNetworkComponentQuery = React.memo( +const KpiNetworkComponentQuery = React.memo( ({ id = ID, children, filterQuery, isInspected, skip, sourceId, startDate, endDate }) => ( query={kpiNetworkQuery} @@ -82,4 +78,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const KpiNetworkQuery = connect(makeMapStateToProps)(KpiNetworkComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const KpiNetworkQuery = connector(KpiNetworkComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx b/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx index 8c40c4044a746..2dd9ccf24d802 100644 --- a/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { GetOverviewHostQuery, OverviewHostData } from '../../../graphql/types'; @@ -29,10 +29,6 @@ export interface OverviewHostArgs { refetch: inputsModel.Refetch; } -export interface OverviewHostReducer { - isInspected: boolean; -} - export interface OverviewHostProps extends QueryTemplateProps { children: (args: OverviewHostArgs) => React.ReactNode; sourceId: string; @@ -40,7 +36,7 @@ export interface OverviewHostProps extends QueryTemplateProps { startDate: number; } -const OverviewHostComponentQuery = React.memo( +const OverviewHostComponentQuery = React.memo( ({ id = ID, children, filterQuery, isInspected, sourceId, startDate, endDate }) => { return ( @@ -86,4 +82,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const OverviewHostQuery = connect(makeMapStateToProps)(OverviewHostComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const OverviewHostQuery = connector(OverviewHostComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx b/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx index 9e7d59de0e546..d0acd41c224a5 100644 --- a/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { GetOverviewNetworkQuery, OverviewNetworkData } from '../../../graphql/types'; @@ -29,10 +29,6 @@ export interface OverviewNetworkArgs { refetch: inputsModel.Refetch; } -export interface OverviewNetworkReducer { - isInspected: boolean; -} - export interface OverviewNetworkProps extends QueryTemplateProps { children: (args: OverviewNetworkArgs) => React.ReactNode; sourceId: string; @@ -40,37 +36,37 @@ export interface OverviewNetworkProps extends QueryTemplateProps { startDate: number; } -export const OverviewNetworkComponentQuery = React.memo< - OverviewNetworkProps & OverviewNetworkReducer ->(({ id = ID, children, filterQuery, isInspected, sourceId, startDate, endDate }) => ( - - query={overviewNetworkQuery} - fetchPolicy={getDefaultFetchPolicy()} - notifyOnNetworkStatusChange - variables={{ - sourceId, - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - filterQuery: createFilter(filterQuery), - defaultIndex: useUiSetting(DEFAULT_INDEX_KEY), - inspect: isInspected, - }} - > - {({ data, loading, refetch }) => { - const overviewNetwork = getOr({}, `source.OverviewNetwork`, data); - return children({ - id, - inspect: getOr(null, 'source.OverviewNetwork.inspect', data), - overviewNetwork, - loading, - refetch, - }); - }} - -)); +export const OverviewNetworkComponentQuery = React.memo( + ({ id = ID, children, filterQuery, isInspected, sourceId, startDate, endDate }) => ( + + query={overviewNetworkQuery} + fetchPolicy={getDefaultFetchPolicy()} + notifyOnNetworkStatusChange + variables={{ + sourceId, + timerange: { + interval: '12h', + from: startDate, + to: endDate, + }, + filterQuery: createFilter(filterQuery), + defaultIndex: useUiSetting(DEFAULT_INDEX_KEY), + inspect: isInspected, + }} + > + {({ data, loading, refetch }) => { + const overviewNetwork = getOr({}, `source.OverviewNetwork`, data); + return children({ + id, + inspect: getOr(null, 'source.OverviewNetwork.inspect', data), + overviewNetwork, + loading, + refetch, + }); + }} + + ) +); OverviewNetworkComponentQuery.displayName = 'OverviewNetworkComponentQuery'; @@ -85,4 +81,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const OverviewNetworkQuery = connect(makeMapStateToProps)(OverviewNetworkComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const OverviewNetworkQuery = connector(OverviewNetworkComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx b/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx index f4eb088b6ad94..68d87ef565fb7 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx @@ -9,7 +9,7 @@ import memoizeOne from 'memoize-one'; import React from 'react'; import { Query } from 'react-apollo'; import { compose } from 'redux'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { IIndexPattern } from '../../../../../../../src/plugins/data/common/index_patterns'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; @@ -39,10 +39,6 @@ export interface TimelineArgs { getUpdatedAt: () => number; } -export interface TimelineQueryReduxProps { - isInspected: boolean; -} - export interface OwnProps extends QueryTemplateProps { children?: (args: TimelineArgs) => React.ReactNode; eventType?: EventType; @@ -53,7 +49,8 @@ export interface OwnProps extends QueryTemplateProps { sortField: SortField; fields: string[]; } -type TimelineQueryProps = OwnProps & TimelineQueryReduxProps & WithKibanaProps; + +type TimelineQueryProps = OwnProps & PropsFromRedux & WithKibanaProps; class TimelineQueryComponent extends QueryTemplate< TimelineQueryProps, @@ -171,7 +168,11 @@ const makeMapStateToProps = () => { return mapStateToProps; }; +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + export const TimelineQuery = compose>( - connect(makeMapStateToProps), + connector, withKibana )(TimelineQueryComponent); diff --git a/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx b/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx index 520ade954eb5c..0a2ce67d9be80 100644 --- a/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { compose } from 'redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; @@ -43,13 +43,7 @@ export interface OwnProps extends QueryTemplatePaginatedProps { type: hostsModel.HostsType; } -export interface UncommonProcessesComponentReduxProps { - activePage: number; - isInspected: boolean; - limit: number; -} - -type UncommonProcessesProps = OwnProps & UncommonProcessesComponentReduxProps & WithKibanaProps; +type UncommonProcessesProps = OwnProps & PropsFromRedux & WithKibanaProps; class UncommonProcessesComponentQuery extends QueryTemplatePaginated< UncommonProcessesProps, @@ -144,7 +138,11 @@ const makeMapStateToProps = () => { return mapStateToProps; }; +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + export const UncommonProcessesQuery = compose>( - connect(makeMapStateToProps), + connector, withKibana )(UncommonProcessesComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/users/index.tsx b/x-pack/legacy/plugins/siem/public/containers/users/index.tsx index ece73b7b10ff0..5f71449c52460 100644 --- a/x-pack/legacy/plugins/siem/public/containers/users/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/users/index.tsx @@ -7,17 +7,11 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { compose } from 'redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; -import { - GetUsersQuery, - FlowTarget, - PageInfoPaginated, - UsersEdges, - UsersSortField, -} from '../../graphql/types'; +import { GetUsersQuery, FlowTarget, PageInfoPaginated, UsersEdges } from '../../graphql/types'; import { inputsModel, networkModel, networkSelectors, State, inputsSelectors } from '../../store'; import { withKibana, WithKibanaProps } from '../../lib/kibana'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; @@ -47,14 +41,7 @@ export interface OwnProps extends QueryTemplatePaginatedProps { type: networkModel.NetworkType; } -export interface UsersComponentReduxProps { - activePage: number; - isInspected: boolean; - limit: number; - sort: UsersSortField; -} - -type UsersProps = OwnProps & UsersComponentReduxProps & WithKibanaProps; +type UsersProps = OwnProps & PropsFromRedux & WithKibanaProps; class UsersComponentQuery extends QueryTemplatePaginated< UsersProps, @@ -156,7 +143,11 @@ const makeMapStateToProps = () => { return mapStateToProps; }; +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + export const UsersQuery = compose>( - connect(makeMapStateToProps), + connector, withKibana )(UsersComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx index 8108e24cfa2c3..aacc6d951f4c9 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx @@ -7,17 +7,14 @@ import { EuiPanel, EuiLoadingContent } from '@elastic/eui'; import { isEmpty } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; -import { Filter, esQuery, Query } from '../../../../../../../../../src/plugins/data/public'; +import { Filter, esQuery } from '../../../../../../../../../src/plugins/data/public'; import { useFetchIndexPatterns } from '../../../../containers/detection_engine/rules/fetch_index_patterns'; import { StatefulEventsViewer } from '../../../../components/events_viewer'; import { HeaderSection } from '../../../../components/header_section'; -import { DispatchUpdateTimeline } from '../../../../components/open_timeline/types'; import { combineQueries } from '../../../../components/timeline/helpers'; -import { TimelineNonEcsData } from '../../../../graphql/types'; import { useKibana } from '../../../../lib/kibana'; import { inputsSelectors, State, inputsModel } from '../../../../store'; import { timelineActions, timelineSelectors } from '../../../../store/timeline'; @@ -51,33 +48,6 @@ import { dispatchUpdateTimeline } from '../../../../components/open_timeline/hel const SIGNALS_PAGE_TIMELINE_ID = 'signals-page'; -interface ReduxProps { - globalQuery: Query; - globalFilters: Filter[]; - deletedEventIds: string[]; - isSelectAllChecked: boolean; - loadingEventIds: string[]; - selectedEventIds: Readonly>; -} - -interface DispatchProps { - clearEventsDeleted?: ActionCreator<{ id: string }>; - clearEventsLoading?: ActionCreator<{ id: string }>; - clearSelected?: ActionCreator<{ id: string }>; - setEventsDeleted?: ActionCreator<{ - id: string; - eventIds: string[]; - isDeleted: boolean; - }>; - setEventsLoading?: ActionCreator<{ - id: string; - eventIds: string[]; - isLoading: boolean; - }>; - updateTimelineIsLoading: ActionCreator<{ id: string; isLoading: boolean }>; - updateTimeline: DispatchUpdateTimeline; -} - interface OwnProps { canUserCRUD: boolean; defaultFilters?: Filter[]; @@ -88,7 +58,7 @@ interface OwnProps { to: number; } -type SignalsTableComponentProps = OwnProps & ReduxProps & DispatchProps; +type SignalsTableComponentProps = OwnProps & PropsFromRedux; const SignalsTableComponent: React.FC = ({ canUserCRUD, @@ -390,7 +360,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateTimeline: dispatchUpdateTimeline(dispatch), }); -export const SignalsTable = connect( - makeMapStateToProps, - mapDispatchToProps -)(React.memo(SignalsTableComponent)); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const SignalsTable = connector(React.memo(SignalsTableComponent)); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx index 8cfcac8fc862b..c3fb907ae83e1 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx @@ -8,11 +8,7 @@ import { EuiButton, EuiSpacer } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import { useParams } from 'react-router-dom'; import { StickyContainer } from 'react-sticky'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; - -import { Query } from '../../../../../../../src/plugins/data/common/query'; -import { Filter } from '../../../../../../../src/plugins/data/common/es_query'; +import { connect, ConnectedProps } from 'react-redux'; import { GlobalTime } from '../../containers/global_time'; import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; @@ -30,7 +26,6 @@ import { State } from '../../store'; import { inputsSelectors } from '../../store/inputs'; import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from '../../store/inputs/actions'; import { SpyRoute } from '../../utils/route/spy_routes'; -import { InputsModelId } from '../../store/inputs/constants'; import { InputsRange } from '../../store/inputs/model'; import { AlertsByCategory } from '../overview/alerts_by_category'; import { useSignalInfo } from './components/signals_info'; @@ -47,21 +42,6 @@ import { DetectionEngineUserUnauthenticated } from './detection_engine_user_unau import * as i18n from './translations'; import { DetectionEngineTab } from './types'; -interface ReduxProps { - filters: Filter[]; - query: Query; -} - -export interface DispatchProps { - setAbsoluteRangeDatePicker: ActionCreator<{ - id: InputsModelId; - from: number; - to: number; - }>; -} - -type DetectionEnginePageComponentProps = ReduxProps & DispatchProps; - const detectionsTabs: Record = { [DetectionEngineTab.signals]: { id: DetectionEngineTab.signals, @@ -79,7 +59,7 @@ const detectionsTabs: Record = { }, }; -const DetectionEnginePageComponent: React.FC = ({ +const DetectionEnginePageComponent: React.FC = ({ filters, query, setAbsoluteRangeDatePicker, @@ -234,7 +214,8 @@ const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, }; -export const DetectionEnginePage = connect( - makeMapStateToProps, - mapDispatchToProps -)(React.memo(DetectionEnginePageComponent)); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const DetectionEnginePage = connector(React.memo(DetectionEnginePageComponent)); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx index dc1ebd6052538..83dd18f0f14b7 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx @@ -19,9 +19,8 @@ import { FormattedMessage } from '@kbn/i18n/react'; import React, { FC, memo, useCallback, useMemo, useState } from 'react'; import { Redirect, useParams } from 'react-router-dom'; import { StickyContainer } from 'react-sticky'; +import { connect, ConnectedProps } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; -import { connect } from 'react-redux'; import { FiltersGlobal } from '../../../../components/filters_global'; import { FormattedDate } from '../../../../components/formatted_date'; import { @@ -59,9 +58,6 @@ import * as ruleI18n from '../translations'; import * as i18n from './translations'; import { GlobalTime } from '../../../../containers/global_time'; import { signalsHistogramOptions } from '../../components/signals_histogram_panel/config'; -import { InputsModelId } from '../../../../store/inputs/constants'; -import { Filter } from '../../../../../../../../../src/plugins/data/common/es_query'; -import { Query } from '../../../../../../../../../src/plugins/data/common/query'; import { inputsSelectors } from '../../../../store/inputs'; import { State } from '../../../../store'; import { InputsRange } from '../../../../store/inputs/model'; @@ -71,19 +67,6 @@ import { RuleStatusFailedCallOut } from './status_failed_callout'; import { FailureHistory } from './failure_history'; import { RuleStatus } from '../components/rule_status'; -interface ReduxProps { - filters: Filter[]; - query: Query; -} - -export interface DispatchProps { - setAbsoluteRangeDatePicker: ActionCreator<{ - id: InputsModelId; - from: number; - to: number; - }>; -} - enum RuleDetailTabs { signals = 'signals', failures = 'failures', @@ -102,9 +85,7 @@ const ruleDetailTabs = [ }, ]; -type RuleDetailsComponentProps = ReduxProps & DispatchProps; - -const RuleDetailsPageComponent: FC = ({ +const RuleDetailsPageComponent: FC = ({ filters, query, setAbsoluteRangeDatePicker, @@ -417,7 +398,8 @@ const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, }; -export const RuleDetailsPage = connect( - makeMapStateToProps, - mapDispatchToProps -)(memo(RuleDetailsPageComponent)); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const RuleDetailsPage = connector(memo(RuleDetailsPageComponent)); 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 9ee103f88793d..1dce26b7c5d3a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx @@ -104,9 +104,7 @@ export const HomePage: React.FC = () => ( /> ( - - )} + render={({ match }) => } /> ( +export const HostDetailsTabs = React.memo( ({ pageFilters, deleteQuery, @@ -105,5 +105,3 @@ const HostDetailsTabs = React.memo( ); HostDetailsTabs.displayName = 'HostDetailsTabs'; - -export { HostDetailsTabs }; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx index a02e2b4aed22e..8af4731e4dda4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx @@ -6,9 +6,8 @@ import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; import React, { useContext, useEffect, useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; -import { compose } from 'redux'; import { FiltersGlobal } from '../../../components/filters_global'; import { HeaderPage } from '../../../components/header_page'; @@ -39,14 +38,14 @@ import { esQuery, Filter } from '../../../../../../../../src/plugins/data/public import { HostsEmptyPage } from '../hosts_empty_page'; import { HostDetailsTabs } from './details_tabs'; import { navTabsHostDetails } from './nav_tabs'; -import { HostDetailsComponentProps, HostDetailsProps } from './types'; +import { HostDetailsProps } from './types'; import { type } from './utils'; import { getHostDetailsPageFilters } from './helpers'; const HostOverviewManage = manageQuery(HostOverview); const KpiHostDetailsManage = manageQuery(KpiHostsComponent); -const HostDetailsComponent = React.memo( +const HostDetailsComponent = React.memo( ({ filters, from, @@ -61,7 +60,7 @@ const HostDetailsComponent = React.memo( hostDetailsPagePath, }) => { useEffect(() => { - setHostDetailsTablesActivePageToZero(null); + setHostDetailsTablesActivePageToZero(); }, [setHostDetailsTablesActivePageToZero, detailName]); const capabilities = useContext(MlCapabilitiesContext); const kibana = useKibana(); @@ -218,9 +217,13 @@ export const makeMapStateToProps = () => { }); }; -export const HostDetails = compose>( - connect(makeMapStateToProps, { - setAbsoluteRangeDatePicker: dispatchAbsoluteRangeDatePicker, - setHostDetailsTablesActivePageToZero: dispatchHostDetailsTablesActivePageToZero, - }) -)(HostDetailsComponent); +const mapDispatchToProps = { + setAbsoluteRangeDatePicker: dispatchAbsoluteRangeDatePicker, + setHostDetailsTablesActivePageToZero: dispatchHostDetailsTablesActivePageToZero, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const HostDetails = connector(HostDetailsComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx index 71dc3aac756ba..99cf767c65e08 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx @@ -9,14 +9,12 @@ import { cloneDeep } from 'lodash/fp'; import React from 'react'; import { Router } from 'react-router-dom'; import { MockedProvider } from 'react-apollo/test-utils'; -import { ActionCreator } from 'typescript-fsa'; import { Filter } from '../../../../../../../src/plugins/data/common/es_query'; import '../../mock/match_media'; import { mocksSource } from '../../containers/source/mock'; import { wait } from '../../lib/helpers'; import { apolloClientObservable, TestProviders, mockGlobalState } from '../../mock'; -import { InputsModelId } from '../../store/inputs/constants'; import { SiemNavigation } from '../../components/navigation'; import { inputsActions } from '../../store/inputs'; import { State, createStore } from '../../store'; @@ -77,13 +75,6 @@ describe('Hosts - rendering', () => { to, setQuery: jest.fn(), isInitializing: false, - setAbsoluteRangeDatePicker: (jest.fn() as unknown) as ActionCreator<{ - from: number; - id: InputsModelId; - to: number; - }>, - query: { query: '', language: 'kuery' }, - filters: [], hostsPagePath: '', }; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx index 06dffcdb220a9..a7aa9920b7d08 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx @@ -6,9 +6,8 @@ import { EuiSpacer } from '@elastic/eui'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; -import { compose } from 'redux'; import { useParams } from 'react-router-dom'; import { FiltersGlobal } from '../../components/filters_global'; @@ -21,7 +20,6 @@ import { KpiHostsComponent } from '../../components/page/hosts'; import { manageQuery } from '../../components/page/manage_query'; import { SiemSearchBar } from '../../components/search_bar'; import { WrapperPage } from '../../components/wrapper_page'; -import { GlobalTimeArgs } from '../../containers/global_time'; import { KpiHostsQuery } from '../../containers/kpi_hosts'; import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; import { LastEventIndexKey } from '../../graphql/types'; @@ -36,13 +34,13 @@ import { HostsEmptyPage } from './hosts_empty_page'; import { HostsTabs } from './hosts_tabs'; import { navTabsHosts } from './nav_tabs'; import * as i18n from './translations'; -import { HostsComponentProps, HostsComponentReduxProps } from './types'; +import { HostsComponentProps } from './types'; import { filterHostData } from './navigation'; import { HostsTableType } from '../../store/hosts/model'; const KpiHostsComponentManage = manageQuery(KpiHostsComponent); -export const HostsComponent = React.memo( +export const HostsComponent = React.memo( ({ deleteQuery, isInitializing, @@ -161,7 +159,7 @@ HostsComponent.displayName = 'HostsComponent'; const makeMapStateToProps = () => { const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); - const mapStateToProps = (state: State): HostsComponentReduxProps => ({ + const mapStateToProps = (state: State) => ({ query: getGlobalQuerySelector(state), filters: getGlobalFiltersQuerySelector(state), }); @@ -169,13 +167,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -interface HostsProps extends GlobalTimeArgs { - hostsPagePath: string; -} +const mapDispatchToProps = { + setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const Hosts = compose>( - connect(makeMapStateToProps, { - setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, - }) -)(HostsComponent); +export const Hosts = connector(HostsComponent); 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 fff5c5218c003..699b1441905c3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx @@ -56,10 +56,14 @@ export const HostsContainer = React.memo(({ url }) => ( ( + render={({ + match: { + params: { detailName }, + }, + }) => ( ; - hostsPagePath: string; -} - -export type HostsTabsProps = HostsComponentDispatchProps & - HostsQueryProps & { - filterQuery: string; - type: hostsModel.HostsType; - indexPattern: IIndexPattern; - }; +}; export type HostsQueryProps = GlobalTimeArgs; -export type HostsComponentProps = HostsComponentReduxProps & - HostsComponentDispatchProps & - HostsQueryProps; +export type HostsComponentProps = HostsQueryProps & { hostsPagePath: string }; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx index 9a9d1cf085eb9..02132d790796c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx @@ -92,7 +92,7 @@ const getMockProps = (ip: string) => ({ from: number; to: number; }>, - setIpDetailsTablesActivePageToZero: (jest.fn() as unknown) as ActionCreator, + setIpDetailsTablesActivePageToZero: (jest.fn() as unknown) as ActionCreator, }); describe('Ip Details', () => { 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 index 2e8044d2c2fe8..e796eaca0cd28 100644 --- 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 @@ -6,7 +6,7 @@ import { EuiHorizontalRule, EuiSpacer, EuiFlexItem } from '@elastic/eui'; import React, { useCallback, useEffect } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; import { FiltersGlobal } from '../../../components/filters_global'; @@ -46,7 +46,7 @@ export { getBreadcrumbs } from './utils'; const IpOverviewManage = manageQuery(IpOverview); -export const IPDetailsComponent = ({ +export const IPDetailsComponent: React.FC = ({ detailName, filters, flowTarget, @@ -57,7 +57,7 @@ export const IPDetailsComponent = ({ setIpDetailsTablesActivePageToZero, setQuery, to, -}: IPDetailsComponentProps) => { +}) => { const type = networkModel.NetworkType.details; const narrowDateRange = useCallback( (score, interval) => { @@ -73,7 +73,7 @@ export const IPDetailsComponent = ({ const kibana = useKibana(); useEffect(() => { - setIpDetailsTablesActivePageToZero(null); + setIpDetailsTablesActivePageToZero(); }, [detailName, setIpDetailsTablesActivePageToZero]); return ( @@ -279,13 +279,20 @@ IPDetailsComponent.displayName = 'IPDetailsComponent'; const makeMapStateToProps = () => { const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); + return (state: State) => ({ query: getGlobalQuerySelector(state), filters: getGlobalFiltersQuerySelector(state), }); }; -export const IPDetails = connect(makeMapStateToProps, { +const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchAbsoluteRangeDatePicker, setIpDetailsTablesActivePageToZero: dispatchIpDetailsTablesActivePageToZero, -})(React.memo(IPDetailsComponent)); +}; + +export const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const IPDetails = connector(React.memo(IPDetailsComponent)); 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 index b53d58e6664af..ef989fb64eabe 100644 --- 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 @@ -4,38 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ActionCreator } from 'typescript-fsa'; -import { IIndexPattern, Query, Filter } from 'src/plugins/data/public'; +import { IIndexPattern } from 'src/plugins/data/public'; 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[]; +export type IPDetailsComponentProps = GlobalTimeArgs & { + detailName: string; flowTarget: FlowTarget; - query: Query; -} - -interface IPDetailsComponentDispatchProps { - setAbsoluteRangeDatePicker: SetAbsoluteRangeDatePicker; - setIpDetailsTablesActivePageToZero: ActionCreator; -} - -export type IPDetailsComponentProps = IPDetailsComponentReduxProps & - IPDetailsComponentDispatchProps & - GlobalTimeArgs & { detailName: string }; +}; export interface OwnProps { type: NetworkType; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/network.tsx b/x-pack/legacy/plugins/siem/public/pages/network/network.tsx index 0f9eaaef48aa7..9b1ee76e1d376 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/network.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/network.tsx @@ -6,7 +6,7 @@ import { EuiSpacer } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { useParams } from 'react-router-dom'; import { StickyContainer } from 'react-sticky'; @@ -38,7 +38,7 @@ import { NetworkRouteType } from './navigation/types'; const KpiNetworkComponentManage = manageQuery(KpiNetworkComponent); const sourceId = 'default'; -const NetworkComponent = React.memo( +const NetworkComponent = React.memo( ({ filters, query, @@ -183,6 +183,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const Network = connect(makeMapStateToProps, { +const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, -})(NetworkComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const Network = connector(NetworkComponent); 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 8a9914133c9af..01d3fb6b48c63 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/network/types.ts @@ -6,9 +6,8 @@ import { RouteComponentProps } from 'react-router-dom'; import { ActionCreator } from 'typescript-fsa'; -import { GlobalTimeArgs } from '../../containers/global_time'; import { InputsModelId } from '../../store/inputs/constants'; -import { Query, Filter } from '../../../../../../../src/plugins/data/public'; +import { GlobalTimeArgs } from '../../containers/global_time'; export type SetAbsoluteRangeDatePicker = ActionCreator<{ id: InputsModelId; @@ -16,15 +15,8 @@ export type SetAbsoluteRangeDatePicker = ActionCreator<{ to: number; }>; -interface NetworkComponentReduxProps { - filters: Filter[]; - query: Query; - setAbsoluteRangeDatePicker: SetAbsoluteRangeDatePicker; -} - -export type NetworkComponentProps = NetworkComponentReduxProps & - GlobalTimeArgs & - Partial> & { +export type NetworkComponentProps = Partial> & + GlobalTimeArgs & { networkPagePath: string; hasMlUserPermissions: boolean; capabilitiesFetched: boolean; diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx index 8505b91fe1ff5..2db49e60193fc 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx @@ -6,9 +6,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import React from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; -import { compose } from 'redux'; import { Query, Filter } from 'src/plugins/data/public'; import styled from 'styled-components'; @@ -20,7 +19,6 @@ import { GlobalTime } from '../../containers/global_time'; import { WithSource, indicesExistOrDataTemporarilyUnavailable } from '../../containers/source'; import { EventsByDataset } from './events_by_dataset'; import { EventCounts } from './event_counts'; -import { SetAbsoluteRangeDatePicker } from '../network/types'; import { OverviewEmpty } from './overview_empty'; import { StatefulSidebar } from './sidebar'; import { SignalsByCategory } from './signals_by_category'; @@ -35,13 +33,7 @@ const SidebarFlexItem = styled(EuiFlexItem)` margin-right: 24px; `; -interface OverviewComponentReduxProps { - query?: Query; - filters?: Filter[]; - setAbsoluteRangeDatePicker?: SetAbsoluteRangeDatePicker; -} - -const OverviewComponent: React.FC = ({ +const OverviewComponent: React.FC = ({ filters = NO_FILTERS, query = DEFAULT_QUERY, setAbsoluteRangeDatePicker, @@ -133,7 +125,7 @@ const makeMapStateToProps = () => { const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); - const mapStateToProps = (state: State): OverviewComponentReduxProps => ({ + const mapStateToProps = (state: State) => ({ query: getGlobalQuerySelector(state), filters: getGlobalFiltersQuerySelector(state), }); @@ -143,6 +135,8 @@ const makeMapStateToProps = () => { const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker }; -export const StatefulOverview = compose>( - connect(makeMapStateToProps, mapDispatchToProps) -)(React.memo(OverviewComponent)); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulOverview = connector(React.memo(OverviewComponent)); diff --git a/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts b/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts index 8255ba41d2bb1..f9da0e558c655 100644 --- a/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts +++ b/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts @@ -7,7 +7,7 @@ import actionCreatorFactory from 'typescript-fsa'; import { SavedQuery } from 'src/legacy/core_plugins/data/public'; -import { InspectQuery, Refetch } from './model'; +import { InspectQuery, Refetch, RefetchKql } from './model'; import { InputsModelId } from './constants'; import { Filter } from '../../../../../../../src/plugins/data/public'; @@ -42,7 +42,7 @@ export const setQuery = actionCreator<{ inputId: InputsModelId; id: string; loading: boolean; - refetch: Refetch; + refetch: Refetch | RefetchKql; inspect: InspectQuery | null; }>('SET_QUERY'); diff --git a/x-pack/legacy/plugins/siem/public/store/inputs/helpers.ts b/x-pack/legacy/plugins/siem/public/store/inputs/helpers.ts index 194d2e8cd35c3..4a3c17a6234e7 100644 --- a/x-pack/legacy/plugins/siem/public/store/inputs/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/store/inputs/helpers.ts @@ -6,7 +6,7 @@ import { get } from 'lodash/fp'; -import { InputsModel, TimeRange, Refetch, InspectQuery } from './model'; +import { InputsModel, TimeRange, Refetch, RefetchKql, InspectQuery } from './model'; import { InputsModelId } from './constants'; export const updateInputTimerange = ( @@ -59,7 +59,7 @@ export interface UpdateQueryParams { inputId: InputsModelId; inspect: InspectQuery | null; loading: boolean; - refetch: Refetch; + refetch: Refetch | RefetchKql; state: InputsModel; } diff --git a/x-pack/legacy/plugins/siem/public/store/network/selectors.ts b/x-pack/legacy/plugins/siem/public/store/network/selectors.ts index 64a325b6e1ca4..273eaf7c0ee7f 100644 --- a/x-pack/legacy/plugins/siem/public/store/network/selectors.ts +++ b/x-pack/legacy/plugins/siem/public/store/network/selectors.ts @@ -16,6 +16,9 @@ import { NetworkPageModel, NetworkTableType, NetworkType, + TopCountriesQuery, + TlsQuery, + HttpQuery, } from './model'; const selectNetworkPage = (state: State): NetworkPageModel => state.network.page; @@ -41,7 +44,7 @@ const selectTopNFlowByType = ( export const topNFlowSelector = () => createSelector(selectTopNFlowByType, topNFlowQueries => topNFlowQueries); -const selectTlsByType = (state: State, networkType: NetworkType) => { +const selectTlsByType = (state: State, networkType: NetworkType): TlsQuery => { const tlsType = networkType === NetworkType.page ? NetworkTableType.tls : IpDetailsTableType.tls; return ( get([networkType, 'queries', tlsType], state.network) || @@ -55,7 +58,7 @@ const selectTopCountriesByType = ( state: State, networkType: NetworkType, flowTarget: FlowTargetSourceDest -) => { +): TopCountriesQuery => { const ft = flowTarget === FlowTargetSourceDest.source ? 'topCountriesSource' : 'topCountriesDestination'; const nFlowType = @@ -70,7 +73,7 @@ const selectTopCountriesByType = ( export const topCountriesSelector = () => createSelector(selectTopCountriesByType, topCountriesQueries => topCountriesQueries); -const selectHttpByType = (state: State, networkType: NetworkType) => { +const selectHttpByType = (state: State, networkType: NetworkType): HttpQuery => { const httpType = networkType === NetworkType.page ? NetworkTableType.http : IpDetailsTableType.http; return ( diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx index 744c82a9983c8..b4989282f854c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx @@ -31,7 +31,7 @@ export interface PingHistogramComponentProps { */ height?: string; - data?: HistogramResult; + data: HistogramResult | null; loading?: boolean; } diff --git a/x-pack/legacy/plugins/uptime/public/contexts/uptime_refresh_context.tsx b/x-pack/legacy/plugins/uptime/public/contexts/uptime_refresh_context.tsx index 4516289bd51d6..8e406f621f648 100644 --- a/x-pack/legacy/plugins/uptime/public/contexts/uptime_refresh_context.tsx +++ b/x-pack/legacy/plugins/uptime/public/contexts/uptime_refresh_context.tsx @@ -28,6 +28,7 @@ export const UptimeRefreshContextProvider: React.FC = ({ children }) => { const refreshApp = () => { const refreshTime = Date.now(); setLastRefresh(refreshTime); + // @ts-ignore store.dispatch(triggerAppRefresh(refreshTime)); }; diff --git a/x-pack/legacy/plugins/uptime/public/uptime_app.tsx b/x-pack/legacy/plugins/uptime/public/uptime_app.tsx index db34566d6c148..66ff5ba7a58ee 100644 --- a/x-pack/legacy/plugins/uptime/public/uptime_app.tsx +++ b/x-pack/legacy/plugins/uptime/public/uptime_app.tsx @@ -85,6 +85,7 @@ const Application = (props: UptimeAppProps) => { ); }, [canSave, renderGlobalHelpControls, setBadge]); + // @ts-ignore store.dispatch(setBasePath(basePath)); return ( diff --git a/x-pack/package.json b/x-pack/package.json index e3bc8aa36373d..37791c255aee9 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -65,7 +65,7 @@ "@types/graphql": "^0.13.2", "@types/gulp": "^4.0.6", "@types/hapi__wreck": "^15.0.1", - "@types/hoist-non-react-statics": "^3.3.0", + "@types/hoist-non-react-statics": "^3.3.1", "@types/history": "^4.7.3", "@types/jest": "24.0.19", "@types/joi": "^13.4.2", @@ -88,14 +88,14 @@ "@types/prop-types": "^15.5.3", "@types/proper-lockfile": "^3.0.1", "@types/puppeteer": "^1.20.1", - "@types/react": "^16.9.11", - "@types/react-dom": "^16.9.4", - "@types/react-redux": "^6.0.6", + "@types/react": "^16.9.19", + "@types/react-dom": "^16.9.5", + "@types/react-redux": "^7.1.7", "@types/react-router-dom": "^5.1.3", "@types/react-sticky": "^6.0.3", "@types/react-test-renderer": "^16.9.1", "@types/recompose": "^0.30.6", - "@types/reduce-reducers": "^0.3.0", + "@types/reduce-reducers": "^1.0.0", "@types/redux-actions": "^2.6.1", "@types/sinon": "^7.0.13", "@types/styled-components": "^4.4.2", @@ -118,10 +118,10 @@ "copy-webpack-plugin": "^5.0.4", "cypress": "^3.6.1", "cypress-multi-reporters": "^1.2.3", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.15.1", - "enzyme-adapter-utils": "^1.12.1", - "enzyme-to-json": "^3.4.3", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.2", + "enzyme-adapter-utils": "^1.13.0", + "enzyme-to-json": "^3.4.4", "execa": "^3.2.0", "fancy-log": "^1.3.2", "fetch-mock": "^7.3.9", @@ -134,6 +134,7 @@ "graphql-codegen-typescript-server": "^0.18.2", "gulp": "4.0.2", "hapi": "^17.5.3", + "hoist-non-react-statics": "^3.3.2", "jest": "^24.9.0", "jest-cli": "^24.9.0", "jest-styled-components": "^7.0.0", @@ -305,7 +306,7 @@ "react-markdown": "^3.4.1", "react-moment-proptypes": "^1.7.0", "react-portal": "^3.2.0", - "react-redux": "^5.1.2", + "react-redux": "^7.1.3", "react-reverse-portal": "^1.0.4", "react-router-dom": "^5.1.2", "react-shortcuts": "^2.0.0", @@ -316,15 +317,15 @@ "react-vis": "^1.8.1", "react-visibility-sensor": "^5.1.1", "recompose": "^0.26.0", - "reduce-reducers": "^0.4.3", - "redux": "4.0.0", - "redux-actions": "2.6.5", - "redux-observable": "^1.0.0", + "reduce-reducers": "^1.0.4", + "redux": "^4.0.5", + "redux-actions": "^2.6.5", + "redux-observable": "^1.2.0", "redux-saga": "^0.16.0", - "redux-thunk": "2.3.0", + "redux-thunk": "^2.3.0", "redux-thunks": "^1.0.0", "request": "^2.88.0", - "reselect": "3.0.1", + "reselect": "^4.0.0", "resize-observer-polyfill": "^1.5.0", "rison-node": "0.3.1", "rxjs": "^6.5.3", @@ -339,8 +340,8 @@ "topojson-client": "3.0.0", "tslib": "^1.9.3", "turf": "3.0.14", - "typescript-fsa": "^2.5.0", - "typescript-fsa-reducers": "^0.4.5", + "typescript-fsa": "^3.0.0", + "typescript-fsa-reducers": "^1.2.1", "ui-select": "0.19.8", "unstated": "^2.1.1", "uuid": "3.3.2", diff --git a/yarn.lock b/yarn.lock index 33cb366e72f00..27967aefa20c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4391,7 +4391,7 @@ resolved "https://registry.yarnpkg.com/@types/elasticsearch/-/elasticsearch-5.0.33.tgz#b0fd37dc674f498223b6d68c313bdfd71f4d812b" integrity sha512-n/g9pqJEpE4fyUE8VvHNGtl7E2Wv8TCroNwfgAeJKRV4ghDENahtrAo1KMsFNIejBD2gDAlEUa4CM4oEEd8p9Q== -"@types/enzyme@^3.1.13", "@types/enzyme@^3.9.0": +"@types/enzyme@^3.1.13", "@types/enzyme@^3.10.5": version "3.10.5" resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.5.tgz#fe7eeba3550369eed20e7fb565bfb74eec44f1f0" integrity sha512-R+phe509UuUYy9Tk0YlSbipRpfVtIzb/9BHn5pTEtjJTF5LXvUjrIQcZvNyANNEyFrd2YGs196PniNT1fgvOQA== @@ -4580,7 +4580,7 @@ resolved "https://registry.yarnpkg.com/@types/hoek/-/hoek-4.1.3.tgz#d1982d48fb0d2a0e5d7e9d91838264d8e428d337" integrity sha1-0ZgtSPsNKg5dfp2Rg4Jk2OQo0zc= -"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0": +"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1": version "3.3.1" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== @@ -4998,13 +4998,20 @@ dependencies: "@types/react" "*" -"@types/react-dom@*", "@types/react-dom@^16.9.4": +"@types/react-dom@*": version "16.9.4" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.4.tgz#0b58df09a60961dcb77f62d4f1832427513420df" integrity sha512-fya9xteU/n90tda0s+FtN5Ym4tbgxpq/hb/Af24dvs6uYnYn+fspaxw5USlw0R8apDNwxsqumdRoCoKitckQqw== dependencies: "@types/react" "*" +"@types/react-dom@^16.9.5": + version "16.9.5" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.5.tgz#5de610b04a35d07ffd8f44edad93a71032d9aaa7" + integrity sha512-BX6RQ8s9D+2/gDhxrj8OW+YD4R+8hj7FEM/OJHGNR0KipE1h1mSsf39YeyC81qafkq+N3rU3h3RFbLSwE5VqUg== + dependencies: + "@types/react" "*" + "@types/react-grid-layout@^0.16.7": version "0.16.7" resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-0.16.7.tgz#53d5f5034deb0c60e25a0fa578141e9a0982011f" @@ -5025,14 +5032,6 @@ "@types/prop-types" "*" "@types/react" "*" -"@types/react-redux@^6.0.6": - version "6.0.6" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-6.0.6.tgz#87f1d0a6ea901b93fcaf95fa57641ff64079d277" - integrity sha512-sD/QEn45h+CH0OAhCn6/9COlihZ94bzpP58QzYYCL3tOFta/WBhuvMoyLP8khJLfwQBx1PT70HP/1GnDws9YXQ== - dependencies: - "@types/react" "*" - redux "^4.0.0" - "@types/react-redux@^7.1.0": version "7.1.5" resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.5.tgz#c7a528d538969250347aa53c52241051cf886bd3" @@ -5043,6 +5042,16 @@ hoist-non-react-statics "^3.3.0" redux "^4.0.0" +"@types/react-redux@^7.1.7": + version "7.1.7" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.7.tgz#12a0c529aba660696947384a059c5c6e08185c7a" + integrity sha512-U+WrzeFfI83+evZE2dkZ/oF/1vjIYgqrb5dGgedkqVV8HEfDFujNgWCwHL89TDuWKb47U0nTBT6PLGq4IIogWg== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + "@types/react-resize-detector@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/react-resize-detector/-/react-resize-detector-4.0.1.tgz#cc8f012f5957e4826e69b8d2afd59baadcac556c" @@ -5103,10 +5112,10 @@ "@types/prop-types" "*" "@types/react" "*" -"@types/react@*", "@types/react@^16.8.23", "@types/react@^16.9.11", "@types/react@^16.9.13": - version "16.9.15" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.15.tgz#aeabb7a50f96c9e31a16079ada20ede9ed602977" - integrity sha512-WsmM1b6xQn1tG3X2Hx4F3bZwc2E82pJXt5OPs2YJgg71IzvUoKOSSSYOvLXYCg1ttipM+UuA4Lj3sfvqjVxyZw== +"@types/react@*", "@types/react@^16.8.23", "@types/react@^16.9.19": + version "16.9.19" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.19.tgz#c842aa83ea490007d29938146ff2e4d9e4360c40" + integrity sha512-LJV97//H+zqKWMms0kvxaKYJDG05U2TtQB3chRLF8MPNs+MQh/H1aGlyDUxjaHvu08EAGerdX2z4LTBc7ns77A== dependencies: "@types/prop-types" "*" csstype "^2.2.0" @@ -5125,23 +5134,18 @@ dependencies: "@types/react" "*" -"@types/reduce-reducers@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@types/reduce-reducers/-/reduce-reducers-0.3.0.tgz#d86d88049c38bebbafa5baf121282d765fabbebf" - integrity sha512-S9Vi74p0UOlqf9dqiurBwNBp+ABAGZ7nJAZteFS6LS8y9u2fkGfvNk1gtauKoDG+BuB4vjp1+P/R0/r5rFxYDQ== +"@types/reduce-reducers@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/reduce-reducers/-/reduce-reducers-1.0.0.tgz#033120b109159f4b344210ee75310d1ec3fcc8ef" + integrity sha512-MWKF9QDH/HaMQZvGyQlrut1ttyrFVIrGZqhCXPBcl5LelhnfC7dIE2jK2qZjxFHUCeXgjKCk5hN+/GzA7GgqjQ== dependencies: - redux "^4.0.0" + reduce-reducers "*" "@types/redux-actions@^2.6.1": version "2.6.1" resolved "https://registry.yarnpkg.com/@types/redux-actions/-/redux-actions-2.6.1.tgz#0940e97fa35ad3004316bddb391d8e01d2efa605" integrity sha512-zKgK+ATp3sswXs6sOYo1tk8xdXTy4CTaeeYrVQlClCjeOpag5vzPo0ASWiiBJ7vsiQRAdb3VkuFLnDoBimF67g== -"@types/redux@^3.6.31": - version "3.6.31" - resolved "https://registry.yarnpkg.com/@types/redux/-/redux-3.6.31.tgz#40eafa7575db36b912ce0059b85de98c205b0708" - integrity sha1-QOr6dXXbNrkSzgBZuF3pjCBbBwg= - "@types/request@^2.48.2": version "2.48.2" resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.2.tgz#936374cbe1179d7ed529fc02543deb4597450fed" @@ -6807,14 +6811,13 @@ array.prototype.find@^2.1.0: define-properties "^1.1.3" es-abstract "^1.13.0" -array.prototype.flat@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz#812db8f02cad24d3fab65dd67eabe3b8903494a4" - integrity sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw== +array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" + integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== dependencies: - define-properties "^1.1.2" - es-abstract "^1.10.0" - function-bind "^1.1.1" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" array.prototype.flatmap@^1.2.1: version "1.2.1" @@ -8967,7 +8970,7 @@ cheerio@0.22.0: lodash.reject "^4.4.0" lodash.some "^4.4.0" -cheerio@^1.0.0-rc.2: +cheerio@^1.0.0-rc.3: version "1.0.0-rc.3" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6" integrity sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA== @@ -12218,74 +12221,76 @@ env-variable@0.0.x: resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.5.tgz#913dd830bef11e96a039c038d4130604eba37f88" integrity sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA== -enzyme-adapter-react-16@^1.15.1: - version "1.15.1" - resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.1.tgz#8ad55332be7091dc53a25d7d38b3485fc2ba50d5" - integrity sha512-yMPxrP3vjJP+4wL/qqfkT6JAIctcwKF+zXO6utlGPgUJT2l4tzrdjMDWGd/Pp1BjHBcljhN24OzNEGRteibJhA== +enzyme-adapter-react-16@^1.15.2: + version "1.15.2" + resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.2.tgz#b16db2f0ea424d58a808f9df86ab6212895a4501" + integrity sha512-SkvDrb8xU3lSxID8Qic9rB8pvevDbLybxPK6D/vW7PrT0s2Cl/zJYuXvsd1EBTz0q4o3iqG3FJhpYz3nUNpM2Q== dependencies: - enzyme-adapter-utils "^1.12.1" - enzyme-shallow-equal "^1.0.0" + enzyme-adapter-utils "^1.13.0" + enzyme-shallow-equal "^1.0.1" has "^1.0.3" object.assign "^4.1.0" - object.values "^1.1.0" + object.values "^1.1.1" prop-types "^15.7.2" - react-is "^16.10.2" + react-is "^16.12.0" react-test-renderer "^16.0.0-0" semver "^5.7.0" -enzyme-adapter-utils@^1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.1.tgz#e828e0d038e2b1efa4b9619ce896226f85c9dd88" - integrity sha512-KWiHzSjZaLEoDCOxY8Z1RAbUResbqKN5bZvenPbfKtWorJFVETUw754ebkuCQ3JKm0adx1kF8JaiR+PHPiP47g== +enzyme-adapter-utils@^1.13.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.13.0.tgz#01c885dde2114b4690bf741f8dc94cee3060eb78" + integrity sha512-YuEtfQp76Lj5TG1NvtP2eGJnFKogk/zT70fyYHXK2j3v6CtuHqc8YmgH/vaiBfL8K1SgVVbQXtTcgQZFwzTVyQ== dependencies: airbnb-prop-types "^2.15.0" - function.prototype.name "^1.1.1" + function.prototype.name "^1.1.2" object.assign "^4.1.0" - object.fromentries "^2.0.1" + object.fromentries "^2.0.2" prop-types "^15.7.2" - semver "^5.7.0" + semver "^5.7.1" -enzyme-shallow-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.0.tgz#d8e4603495e6ea279038eef05a4bf4887b55dc69" - integrity sha512-VUf+q5o1EIv2ZaloNQQtWCJM9gpeux6vudGVH6vLmfPXFLRuxl5+Aq3U260wof9nn0b0i+P5OEUXm1vnxkRpXQ== +enzyme-shallow-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.1.tgz#7afe03db3801c9b76de8440694096412a8d9d49e" + integrity sha512-hGA3i1so8OrYOZSM9whlkNmVHOicJpsjgTzC+wn2JMJXhq1oO4kA4bJ5MsfzSIcC71aLDKzJ6gZpIxrqt3QTAQ== dependencies: has "^1.0.3" - object-is "^1.0.1" + object-is "^1.0.2" -enzyme-to-json@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.4.3.tgz#ed4386f48768ed29e2d1a2910893542c34e7e0af" - integrity sha512-jqNEZlHqLdz7OTpXSzzghArSS3vigj67IU/fWkPyl1c0TCj9P5s6Ze0kRkYZWNEoCqCR79xlQbigYlMx5erh8A== +enzyme-to-json@^3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.4.4.tgz#b30726c59091d273521b6568c859e8831e94d00e" + integrity sha512-50LELP/SCPJJGic5rAARvU7pgE3m1YaNj7JLM+Qkhl5t7PAs6fiyc8xzc50RnkKPFQCv0EeFVjEWdIFRGPWMsA== dependencies: lodash "^4.17.15" + react-is "^16.12.0" -enzyme@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.10.0.tgz#7218e347c4a7746e133f8e964aada4a3523452f6" - integrity sha512-p2yy9Y7t/PFbPoTvrWde7JIYB2ZyGC+NgTNbVEGvZ5/EyoYSr9aG/2rSbVvyNvMHEhw9/dmGUJHWtfQIEiX9pg== +enzyme@^3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.11.0.tgz#71d680c580fe9349f6f5ac6c775bc3e6b7a79c28" + integrity sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw== dependencies: - array.prototype.flat "^1.2.1" - cheerio "^1.0.0-rc.2" - function.prototype.name "^1.1.0" + array.prototype.flat "^1.2.3" + cheerio "^1.0.0-rc.3" + enzyme-shallow-equal "^1.0.1" + function.prototype.name "^1.1.2" has "^1.0.3" - html-element-map "^1.0.0" - is-boolean-object "^1.0.0" - is-callable "^1.1.4" - is-number-object "^1.0.3" - is-regex "^1.0.4" - is-string "^1.0.4" + html-element-map "^1.2.0" + is-boolean-object "^1.0.1" + is-callable "^1.1.5" + is-number-object "^1.0.4" + is-regex "^1.0.5" + is-string "^1.0.5" is-subset "^0.1.1" lodash.escape "^4.0.1" lodash.isequal "^4.5.0" - object-inspect "^1.6.0" - object-is "^1.0.1" + object-inspect "^1.7.0" + object-is "^1.0.2" object.assign "^4.1.0" - object.entries "^1.0.4" - object.values "^1.0.4" - raf "^3.4.0" + object.entries "^1.1.1" + object.values "^1.1.1" + raf "^3.4.1" rst-selector-parser "^2.2.3" - string.prototype.trim "^1.1.2" + string.prototype.trim "^1.2.1" errlop@^1.1.2: version "1.1.2" @@ -12335,26 +12340,44 @@ error@^7.0.0, error@^7.0.2: string-template "~0.2.1" xtend "~4.0.0" -es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.14.2, es-abstract@^1.15.0, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0, es-abstract@^1.9.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" - integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== +es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.13.0, es-abstract@^1.14.2, es-abstract@^1.17.0-next.1, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0, es-abstract@^1.9.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0.tgz#f42a517d0036a5591dbb2c463591dc8bb50309b1" + integrity sha512-yYkE07YF+6SIBmg1MsJ9dlub5L48Ek7X0qz+c/CPCHS9EBXfESorzng4cJQjJW5/pB6vDF41u7F8vUhLVDqIug== dependencies: - es-to-primitive "^1.2.0" + es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.0" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.6.0" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== +es-abstract@^1.15.0: + version "1.17.4" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" + integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -14417,31 +14440,21 @@ function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -function.prototype.name@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327" - integrity sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - is-callable "^1.1.3" - -function.prototype.name@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.1.tgz#6d252350803085abc2ad423d4fe3be2f9cbda392" - integrity sha512-e1NzkiJuw6xqVH7YSdiW/qDHebcmMhPNe6w+4ZYYEg0VA+LaLzx37RimbPLuonHhYGFGPx1ME2nSi74JiaCr/Q== +function.prototype.name@^1.1.0, function.prototype.name@^1.1.1, function.prototype.name@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.2.tgz#5cdf79d7c05db401591dfde83e3b70c5123e9a45" + integrity sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg== dependencies: define-properties "^1.1.3" - function-bind "^1.1.1" - functions-have-names "^1.1.1" - is-callable "^1.1.4" + es-abstract "^1.17.0-next.1" + functions-have-names "^1.2.0" functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -functions-have-names@^1.1.1: +functions-have-names@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.0.tgz#83da7583e4ea0c9ac5ff530f73394b033e0bf77d" integrity sha512-zKXyzksTeaCSw5wIX79iCA40YAa6CJMJgNg9wdkU/ERBrIdPSimPICYiLp65lRbSBqtiHql/HZfS2DyI/AH6tQ== @@ -15876,10 +15889,10 @@ has-symbol-support-x@^1.4.1: resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= +has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== has-to-string-tag-x@^1.2.0: version "1.4.1" @@ -16110,22 +16123,10 @@ hoek@6.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.0.3.tgz#7884360426d927865a0a1251fc9c59313af5b798" integrity sha512-TU6RyZ/XaQCTWRLrdqZZtZqwxUVr6PDMfi6MlWNURZ7A6czanQqX4pFE1mdOUQR9FdPCsZ0UzL8jI/izZ+eBSQ== -hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0, hoist-non-react-statics@^2.5.5: - version "2.5.5" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" - integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== - -hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#101685d3aff3b23ea213163f6e8e12f4f111e19f" - integrity sha512-wbg3bpgA/ZqWrZuMOeJi8+SKMhr7X9TesL/rXMjTzh0p0JUBo3II8DHboYbuIXWRlttrUFxwcu/5kygrCw8fJw== - dependencies: - react-is "^16.7.0" - -hoist-non-react-statics@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" - integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA== +hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0, hoist-non-react-statics@^2.5.5, hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== dependencies: react-is "^16.7.0" @@ -16156,10 +16157,10 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -html-element-map@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.0.1.tgz#3c4fcb4874ebddfe4283b51c8994e7713782b592" - integrity sha512-BZSfdEm6n706/lBfXKWa4frZRZcT5k1cOusw95ijZsHlI+GdgY0v95h6IzO3iIDf2ROwq570YTwqNPqHcNMozw== +html-element-map@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.2.0.tgz#dfbb09efe882806af63d990cf6db37993f099f22" + integrity sha512-0uXq8HsuG1v2TmQ8QkIhzbrqeskE4kn52Q18QJ9iAA/SnHoEKXWiUxHQtclRsCFWEUD2So34X+0+pZZu862nnw== dependencies: array-filter "^1.0.0" @@ -16967,7 +16968,7 @@ invariant@2.2.4, invariant@^2.1.0, invariant@^2.1.1, invariant@^2.2.3, invariant dependencies: loose-envify "^1.0.0" -invariant@^2.0.0, invariant@^2.2.1, invariant@^2.2.2: +invariant@^2.2.1, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" integrity sha1-nh9WrArNtr8wMwbzOL47IErmA2A= @@ -17099,10 +17100,10 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" - integrity sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M= +is-boolean-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e" + integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ== is-buffer@^1.0.2, is-buffer@^1.1.4, is-buffer@^1.1.5, is-buffer@~1.1.1: version "1.1.6" @@ -17121,10 +17122,10 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" -is-callable@^1.1.3, is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== is-ci@1.2.1: version "1.2.1" @@ -17374,10 +17375,10 @@ is-npm@^1.0.0: resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= -is-number-object@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799" - integrity sha1-8mWrian0RQNO9q/xWo8AsA9VF5k= +is-number-object@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" + integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== is-number@^0.1.1: version "0.1.1" @@ -17514,12 +17515,12 @@ is-redirect@^1.0.0: resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= -is-regex@^1.0.3, is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= +is-regex@^1.0.3, is-regex@^1.0.4, is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== dependencies: - has "^1.0.1" + has "^1.0.3" is-regexp@^1.0.0: version "1.0.0" @@ -17587,10 +17588,10 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== -is-string@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64" - integrity sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ= +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== is-subset@^0.1.1: version "0.1.1" @@ -17655,12 +17656,7 @@ is-whitespace-character@^1.0.0: resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz#9ae0176f3282b65457a1992cdb084f8a5f833e3b" integrity sha1-muAXbzKCtlRXoZks2whPil+DPjs= -is-windows@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" - integrity sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk= - -is-windows@^1.0.2: +is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== @@ -19478,7 +19474,7 @@ locutus@^2.0.5: resolved "https://registry.yarnpkg.com/locutus/-/locutus-2.0.10.tgz#f903619466a98a4ab76e8b87a5854b55a743b917" integrity sha512-AZg2kCqrquMJ5FehDsBidV0qHl98NrsYtseUClzjAQ3HFnsDBJTCwGVplSQ82t9/QfgahqvTjaKcZqZkHmS0wQ== -lodash-es@^4.17.11, lodash-es@^4.17.5, lodash-es@^4.2.1: +lodash-es@^4.17.11, lodash-es@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== @@ -21844,7 +21840,7 @@ object-identity-map@^1.0.2: dependencies: object.entries "^1.1.0" -object-inspect@^1.6.0: +object-inspect@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== @@ -21859,10 +21855,10 @@ object-inspect@~1.6.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== -object-is@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" - integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= +object-is@^1.0.1, object-is@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" + integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ== object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.0.9, object-keys@^1.1.1: version "1.1.1" @@ -21908,13 +21904,13 @@ object.defaults@^1.0.0, object.defaults@^1.1.0: for-own "^1.0.0" isobject "^3.0.0" -object.entries@^1.0.4, object.entries@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519" - integrity sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA== +object.entries@^1.0.4, object.entries@^1.1.0, object.entries@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b" + integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" @@ -21938,6 +21934,16 @@ object.fromentries@^2.0.1: function-bind "^1.1.1" has "^1.0.3" +object.fromentries@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" + integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + object.getownpropertydescriptors@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" @@ -21969,13 +21975,13 @@ object.reduce@^1.0.0: for-own "^1.0.0" make-iterator "^1.0.0" -object.values@^1.0.4, object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== +object.values@^1.0.4, object.values@^1.1.0, object.values@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" @@ -23935,14 +23941,7 @@ raf-schd@^4.0.2: resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0" integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ== -raf@^3.1.0, raf@^3.3.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" - integrity sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw== - dependencies: - performance-now "^2.1.0" - -raf@^3.4.0: +raf@^3.1.0, raf@^3.3.0, raf@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== @@ -24442,11 +24441,6 @@ react-intl@^2.8.0: intl-relativeformat "^2.1.0" invariant "^2.1.1" -react-is@^16.10.2, react-is@^16.9.0: - version "16.11.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.11.0.tgz#b85dfecd48ad1ce469ff558a882ca8e8313928fa" - integrity sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw== - react-is@^16.12.0, react-is@^16.3.1: version "16.12.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" @@ -24467,6 +24461,11 @@ react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.5.tgz#c54ac229dd66b5afe0de5acbe47647c3da692ff8" integrity sha512-sudt2uq5P/2TznPV4Wtdi+Lnq3yaYW8LfvPKLM9BKD8jJNBkxMVyB0C9/GmVhLw7Jbdmndk/73n7XQGeN9A3QQ== +react-is@^16.9.0: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.11.0.tgz#b85dfecd48ad1ce469ff558a882ca8e8313928fa" + integrity sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw== + react-is@~16.3.0: version "16.3.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.3.2.tgz#f4d3d0e2f5fbb6ac46450641eb2e25bf05d36b22" @@ -24625,19 +24624,7 @@ react-reconciler@^0.22.1: prop-types "^15.6.2" scheduler "^0.16.2" -react-redux@^5.0.7: - version "5.0.7" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" - integrity sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg== - dependencies: - hoist-non-react-statics "^2.5.0" - invariant "^2.0.0" - lodash "^4.17.5" - lodash-es "^4.17.5" - loose-envify "^1.1.0" - prop-types "^15.6.0" - -react-redux@^5.1.2: +react-redux@^5.0.7, react-redux@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.2.tgz#b19cf9e21d694422727bf798e934a916c4080f57" integrity sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q== @@ -24650,7 +24637,7 @@ react-redux@^5.1.2: react-is "^16.6.0" react-lifecycles-compat "^3.0.0" -react-redux@^7.1.0, react-redux@^7.1.1: +react-redux@^7.1.0, react-redux@^7.1.1, react-redux@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.1.3.tgz#717a3d7bbe3a1b2d535c94885ce04cdc5a33fc79" integrity sha512-uI1wca+ECG9RoVkWQFF4jDMqmaw0/qnvaSvOoL/GA4dNxf6LoV8sUAcNDvE5NWKs4hFpn0t6wswNQnY3f7HT3w== @@ -25281,12 +25268,17 @@ redeyed@~2.1.0: dependencies: esprima "~4.0.0" +reduce-reducers@*, reduce-reducers@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-1.0.4.tgz#fb77e751a9eb0201760ac5a605ca8c9c2d0537f8" + integrity sha512-Mb2WZ2bJF597exiqX7owBzrqJ74DHLK3yOQjCyPAaNifRncE8OD0wFIuoMhXxTnHK07+8zZ2SJEKy/qtiyR7vw== + reduce-reducers@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-0.4.3.tgz#8e052618801cd8fc2714b4915adaa8937eb6d66c" integrity sha512-+CNMnI8QhgVMtAt54uQs3kUxC3Sybpa7Y63HR14uGLgI9/QR5ggHvpxwhGGe3wmx5V91YwqQIblN9k5lspAmGw== -redux-actions@2.6.5: +redux-actions@^2.6.5: version "2.6.5" resolved "https://registry.yarnpkg.com/redux-actions/-/redux-actions-2.6.5.tgz#bdca548768ee99832a63910c276def85e821a27e" integrity sha512-pFhEcWFTYNk7DhQgxMGnbsB1H2glqhQJRQrtPb96kD3hWiZRzXHwwmFPswg6V2MjraXRXWNmuP9P84tvdLAJmw== @@ -25302,10 +25294,10 @@ redux-devtools-extension@^2.13.8: resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz#37b982688626e5e4993ff87220c9bbb7cd2d96e1" integrity sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg== -redux-observable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redux-observable/-/redux-observable-1.0.0.tgz#780ff2455493eedcef806616fe286b454fd15d91" - integrity sha512-6bXnpqWTBeLaLQjXHyN1giXq4nLxCmv+SUkdmiwBgvmVxvDbdmydvL1Z7DGo0WItyzI/kqXQKiucUuTxnrPRkA== +redux-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/redux-observable/-/redux-observable-1.2.0.tgz#ff51b6c6be2598e9b5e89fc36639186bb0e669c7" + integrity sha512-yeR90RP2WzZzCxxnQPlh2uFzyfFLsfXu8ROh53jGDPXVqj71uNDMmvi/YKQkd9ofiVoO4OYb1snbowO49tCEMg== redux-saga@^0.16.0: version "0.16.2" @@ -25317,7 +25309,7 @@ redux-thunk@2.2.0: resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" integrity sha1-5hWhbha0ehmlFXZhM9Hj6Zt4UuU= -redux-thunk@2.3.0: +redux-thunk@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== @@ -25337,7 +25329,7 @@ redux@3.7.2: loose-envify "^1.1.0" symbol-observable "^1.0.3" -redux@4.0.0, redux@^4.0.0: +redux@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.0.tgz#aa698a92b729315d22b34a0553d7e6533555cc03" integrity sha512-NnnHF0h0WVE/hXyrB6OlX67LYRuaf/rJcbWvnHHEPCF/Xa/AZpwhs/20WyqzQae5x4SD2F9nPObgBh2rxAgLiA== @@ -25361,6 +25353,14 @@ redux@^4.0.4: loose-envify "^1.4.0" symbol-observable "^1.2.0" +redux@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" + integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== + dependencies: + loose-envify "^1.4.0" + symbol-observable "^1.2.0" + reflect.ownkeys@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" @@ -25916,11 +25916,6 @@ requires-regex@^0.3.3: resolved "https://registry.yarnpkg.com/requires-regex/-/requires-regex-0.3.3.tgz#60309eaabbfd5ca8259e090b8b5a94b2144eb0dd" integrity sha1-YDCeqrv9XKglngkLi1qUshROsN0= -reselect@3.0.1, reselect@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147" - integrity sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc= - reselect@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" @@ -26671,17 +26666,17 @@ semver-truncate@^1.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto= -"semver@2 || 3 || 4 || 5", semver@^5.3.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== +"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@5.5.0, semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.5.0: +semver@5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@5.7.0, semver@^5.4.1, semver@^5.6.0, semver@^5.7.0: +semver@5.7.0: version "5.7.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== @@ -27907,13 +27902,13 @@ string.prototype.padstart@^3.0.0: es-abstract "^1.4.3" function-bind "^1.0.2" -string.prototype.trim@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz#75a729b10cfc1be439543dae442129459ce61e3d" - integrity sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg== +string.prototype.trim@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz#141233dff32c82bfad80684d7e5f0869ee0fb782" + integrity sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw== dependencies: define-properties "^1.1.3" - es-abstract "^1.13.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" string.prototype.trim@~1.1.2: @@ -27925,18 +27920,18 @@ string.prototype.trim@~1.1.2: es-abstract "^1.5.0" function-bind "^1.0.2" -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== +string.prototype.trimleft@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" + integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== dependencies: define-properties "^1.1.3" function-bind "^1.1.1" -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== +string.prototype.trimright@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" + integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== dependencies: define-properties "^1.1.3" function-bind "^1.1.1" @@ -29863,17 +29858,15 @@ typedarray@^0.0.6, typedarray@~0.0.5: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-fsa-reducers@^0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/typescript-fsa-reducers/-/typescript-fsa-reducers-0.4.5.tgz#58fffb2f6eeca6817c2f656b7e7df2cb1c9d1f84" - integrity sha512-mBIpU4je365qpqp2XWKtNW3rGO/hA4OI+l8vkkXdHLUYukrp3wNeL+e3roUq1F6wa6Kcr0WaMblEQDsIdWHTEQ== - dependencies: - typescript-fsa "^2.0.0" +typescript-fsa-reducers@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/typescript-fsa-reducers/-/typescript-fsa-reducers-1.2.1.tgz#2af1a85f7b88fb0dfb9fa59d5da51a5d7ac6543f" + integrity sha512-Qgn7zEnAU5n3YEWEL5ooEmIWZl9B4QyXD4Y/0DqpUzF0YuTrcsLa7Lht0gFXZ+xqLJXQwo3fEiTfQTDF1fBnMg== -typescript-fsa@^2.0.0, typescript-fsa@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/typescript-fsa/-/typescript-fsa-2.5.0.tgz#1baec01b5e8f5f34c322679d1327016e9e294faf" - integrity sha1-G67AG16PXzTDImedEycBbp4pT68= +typescript-fsa@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/typescript-fsa/-/typescript-fsa-3.0.0.tgz#3ad1cb915a67338e013fc21f67c9b3e0e110c912" + integrity sha512-xiXAib35i0QHl/+wMobzPibjAH5TJLDj+qGq5jwVLG9qR4FUswZURBw2qihBm0m06tHoyb3FzpnJs1GRhRwVag== typescript@3.5.3, typescript@3.7.2, typescript@^3.0.1, typescript@^3.0.3, typescript@^3.2.2, typescript@^3.3.3333, typescript@^3.4.5, typescript@~3.7.2: version "3.7.2" From 84be2620751dce74f6272d6783a3a0d85e78d6ae Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Mon, 17 Feb 2020 10:59:07 +0100 Subject: [PATCH 30/32] [ML] New Platform server shim: update indices routes (#57685) * [ML] NP indices routes * [ML] fix error function * [ML] fix createAndOpenUrl function --- .../components/anomalies_table/links_menu.js | 70 +++++++++---------- .../plugins/ml/server/routes/apidoc.json | 4 +- .../plugins/ml/server/routes/indices.js | 28 -------- .../plugins/ml/server/routes/indices.ts | 49 +++++++++++++ 4 files changed, 87 insertions(+), 64 deletions(-) delete mode 100644 x-pack/legacy/plugins/ml/server/routes/indices.js create mode 100644 x-pack/legacy/plugins/ml/server/routes/indices.ts diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js index c16dc37097b13..f161e37efa8d8 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js +++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js @@ -236,26 +236,26 @@ class LinksMenuUI extends Component { let i = 0; findFieldType(datafeedIndices[i]); - function findFieldType(index) { - getFieldTypeFromMapping(index, categorizationFieldName) - .then(resp => { - if (resp !== '') { - createAndOpenUrl(index, resp); - } else { - i++; - if (i < datafeedIndices.length) { - findFieldType(datafeedIndices[i]); - } else { - error(); - } - } + const error = () => { + console.log( + `viewExamples(): error finding type of field ${categorizationFieldName} in indices:`, + datafeedIndices + ); + const { toasts } = this.props.kibana.services.notifications; + toasts.addDanger( + i18n.translate('xpack.ml.anomaliesTable.linksMenu.noMappingCouldBeFoundErrorMessage', { + defaultMessage: + 'Unable to view examples of documents with mlcategory {categoryId} ' + + 'as no mapping could be found for the categorization field {categorizationFieldName}', + values: { + categoryId, + categorizationFieldName, + }, }) - .catch(() => { - error(); - }); - } + ); + }; - function createAndOpenUrl(index, categorizationFieldType) { + const createAndOpenUrl = (index, categorizationFieldType) => { // Find the ID of the index pattern with a title attribute which matches the // index configured in the datafeed. If a Kibana index pattern has not been created // for this index, then the user will see a warning message on the Discover tab advising @@ -340,25 +340,25 @@ class LinksMenuUI extends Component { }) ); }); - } + }; - function error() { - console.log( - `viewExamples(): error finding type of field ${categorizationFieldName} in indices:`, - datafeedIndices - ); - const { toasts } = this.props.kibana.services.notifications; - toasts.addDanger( - i18n.translate('xpack.ml.anomaliesTable.linksMenu.noMappingCouldBeFoundErrorMessage', { - defaultMessage: - 'Unable to view examples of documents with mlcategory {categoryId} ' + - 'as no mapping could be found for the categorization field {categorizationFieldName}', - values: { - categoryId, - categorizationFieldName, - }, + function findFieldType(index) { + getFieldTypeFromMapping(index, categorizationFieldName) + .then(resp => { + if (resp !== '') { + createAndOpenUrl(index, resp); + } else { + i++; + if (i < datafeedIndices.length) { + findFieldType(datafeedIndices[i]); + } else { + error(); + } + } }) - ); + .catch(() => { + error(); + }); } }; diff --git a/x-pack/legacy/plugins/ml/server/routes/apidoc.json b/x-pack/legacy/plugins/ml/server/routes/apidoc.json index be1554bf55f78..35215f8008ec3 100644 --- a/x-pack/legacy/plugins/ml/server/routes/apidoc.json +++ b/x-pack/legacy/plugins/ml/server/routes/apidoc.json @@ -76,6 +76,8 @@ "CreateFilter", "UpdateFilter", "DeleteFilter", - "GetFiltersStats" + "GetFiltersStats", + "Indices", + "FieldCaps" ] } diff --git a/x-pack/legacy/plugins/ml/server/routes/indices.js b/x-pack/legacy/plugins/ml/server/routes/indices.js deleted file mode 100644 index 309b41e53eef5..0000000000000 --- a/x-pack/legacy/plugins/ml/server/routes/indices.js +++ /dev/null @@ -1,28 +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 { callWithRequestFactory } from '../client/call_with_request_factory'; -import { wrapError } from '../client/errors'; - -export function indicesRoutes({ commonRouteConfig, elasticsearchPlugin, route }) { - route({ - method: 'POST', - path: '/api/ml/indices/field_caps', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - const index = request.payload.index; - let fields = '*'; - if (request.payload.fields !== undefined && Array.isArray(request.payload.fields)) { - fields = request.payload.fields.join(','); - } - - return callWithRequest('fieldCaps', { index, fields }).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); -} diff --git a/x-pack/legacy/plugins/ml/server/routes/indices.ts b/x-pack/legacy/plugins/ml/server/routes/indices.ts new file mode 100644 index 0000000000000..0ee15f1321e9c --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/routes/indices.ts @@ -0,0 +1,49 @@ +/* + * 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 { schema } from '@kbn/config-schema'; +import { wrapError } from '../client/error_wrapper'; +import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { RouteInitialization } from '../new_platform/plugin'; + +/** + * Indices routes. + */ +export function indicesRoutes({ xpackMainPlugin, router }: RouteInitialization) { + /** + * @apiGroup Indices + * + * @api {post} /api/ml/indices/field_caps + * @apiName FieldCaps + * @apiDescription Retrieves the capabilities of fields among multiple indices. + */ + router.post( + { + path: '/api/ml/indices/field_caps', + validate: { + body: schema.object({ + index: schema.maybe(schema.string()), + fields: schema.maybe(schema.arrayOf(schema.string())), + }), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const { + body: { index, fields: requestFields }, + } = request; + const fields = + requestFields !== undefined && Array.isArray(requestFields) + ? requestFields.join(',') + : '*'; + const result = await context.ml!.mlClient.callAsCurrentUser('fieldCaps', { index, fields }); + return response.ok({ body: result }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); +} From 26fdc4a6b373dac5ec110a34ef0472046dc438b7 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 17 Feb 2020 11:03:57 +0100 Subject: [PATCH 31/32] [Upgrade Assistant] Fix filter deprecations search filter (#57541) * Made eui search field not a controlled component Added validateRegExpString util * Update error message display. Use EuiCallOut and i18n to replicate other search filter behaviour, e.g. index management. * Remove unused variable * Update Jest snapshot * Updated layout for callout The previous callout layout looked off-center next to the controls in the table. * Update copy and remove intl Update "Filter Invalid:" to sentence case Remove inject intl wrapper from CheckupControls component Remove unnecessary grow={true} * Updated Jest component snapshot Co-authored-by: Elastic Machine --- .../__snapshots__/checkup_tab.test.tsx.snap | 3 +- .../components/tabs/checkup/checkup_tab.tsx | 3 +- .../components/tabs/checkup/controls.tsx | 121 ++++++++++++------ .../public/np_ready/application/utils.test.ts | 20 +++ .../public/np_ready/application/utils.ts | 19 +++ 5 files changed, 121 insertions(+), 45 deletions(-) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.test.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap index eb76498b55f4c..da1760d3773d4 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap @@ -57,7 +57,7 @@ exports[`CheckupTab render with deprecations 1`] = ` - @@ -143,7 +143,6 @@ export class CheckupTab extends UpgradeAssistantTabComponent void; currentFilter: LevelFilterOption; onFilterChange: (filter: LevelFilterOption) => void; - search: string; onSearchChange: (filter: string) => void; availableGroupByOptions: GroupByOption[]; currentGroupBy: GroupByOption; onGroupByChange: (groupBy: GroupByOption) => void; } -export const CheckupControlsUI: FunctionComponent = ({ +export const CheckupControls: FunctionComponent = ({ allDeprecations, loadingState, loadData, currentFilter, onFilterChange, - search, onSearchChange, availableGroupByOptions, currentGroupBy, onGroupByChange, - intl, -}) => ( - - - onSearchChange(e.target.value)} - /> - - - {/* These two components provide their own EuiFlexItem wrappers */} - - +}) => { + const [searchTermError, setSearchTermError] = useState(null); + const filterInvalid = Boolean(searchTermError); + return ( + + + + + { + const string = e.target.value; + const errorMessage = validateRegExpString(string); + if (errorMessage) { + // Emit an empty search term to listeners if search term is invalid. + onSearchChange(''); + setSearchTermError(errorMessage); + } else { + onSearchChange(e.target.value); + if (searchTermError) { + setSearchTermError(null); + } + } + }} + /> + - - - - - - -); + {/* These two components provide their own EuiFlexItem wrappers */} + + -export const CheckupControls = injectI18n(CheckupControlsUI); + + + + + + + + {filterInvalid && ( + + + + )} + + ); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.test.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.test.ts new file mode 100644 index 0000000000000..067f11798e151 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.test.ts @@ -0,0 +1,20 @@ +/* + * 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 { validateRegExpString } from './utils'; + +describe('validRegExpString', () => { + it('correctly returns false for invalid strings', () => { + expect(validateRegExpString('?asd')).toContain(`Invalid regular expression`); + expect(validateRegExpString('*asd')).toContain(`Invalid regular expression`); + expect(validateRegExpString('(')).toContain(`Invalid regular expression`); + }); + + it('correctly returns true for valid strings', () => { + expect(validateRegExpString('asd')).toBe(''); + expect(validateRegExpString('.*asd')).toBe(''); + expect(validateRegExpString('')).toBe(''); + }); +}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.ts new file mode 100644 index 0000000000000..6a1f32fe8f20b --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.ts @@ -0,0 +1,19 @@ +/* + * 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 { pipe } from 'fp-ts/lib/pipeable'; +import { tryCatch, fold } from 'fp-ts/lib/Either'; + +export const validateRegExpString = (s: string) => + pipe( + tryCatch( + () => new RegExp(s), + e => (e as Error).message + ), + fold( + (errorMessage: string) => errorMessage, + () => '' + ) + ); From 3d7bae4ed24b8b5777ee217f304a1203e5753880 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 17 Feb 2020 11:06:20 +0100 Subject: [PATCH 32/32] Move Ace XJSON lexer-rules, worker and utils to es_ui_shared (#57563) * Move mode and lexer rules to shared space * Update searchprofiler mode rules * Moved x-json worker out of searchprofiler and into es_ui_shared (for use in Watcher) Renamed ace/mode -> ace/modes * Moved collapse and expand literal string functions to es_ui_shared * Fix some imports Enable Watcher editor to parse XJson using XJsonMode * Fix imports Import JSON highlight rules in XJSONHighlight rules * Move console_lang, fix Jest tests Exporting console_lang through the es_ui_shared/public barrel caused the XJsonMode to imported to a index_management too and any other plugin that may import something from that directory. console_lang was moved to it's own top level directory es_ui_shared/console_lang. We also included a mock for tests using XJsonMode to import from console_lang. * Fixed OSS Jest tests Console Jest tests were still failing because they did not mock out the raw-loader imported worker file * Expand triple quotes in editor Upon entering the advanced watcher creation view, the JSON should be scanned for triple quote expansion * Bring all editors themes in line Editors had github theme, which diverged from the textmate theme used in Console and SearchProfiler * Added XJSON mode to simulate alternative input editor Slight refactor to the logic for using XJSON mode. Created an adhoc hook for wrapping the logic of useState and moved lanugage util imports there too to reduce the number of imports in both the watcher form and simulate tabs in advanced creation. * Moved x-json worker to x-pack x-json worker is currently only used inside of x-pack. Also testing for if this will fix the CI/prod build Co-authored-by: Elastic Machine --- .../legacy/console_editor/editor_output.tsx | 4 +- .../send_request_to_es.ts | 9 +- .../models/legacy_core_editor/mode/input.js | 2 +- .../mode/input_highlight_rules.js | 4 +- .../mode/output_highlight_rules.js | 4 +- .../models/legacy_core_editor/mode/script.js | 19 +- .../legacy_core_editor/mode/worker/index.d.ts | 20 ++ .../__tests__/sense_editor.test.js | 4 +- .../models/sense_editor/sense_editor.ts | 6 +- .../ace_token_provider/token_provider.test.ts | 1 - .../public/lib/autocomplete/autocomplete.ts | 2 +- .../public/lib/utils/__tests__/utils.test.js | 179 +++++++----------- .../public/lib/utils/{utils.ts => index.ts} | 57 +----- .../console_lang/ace/modes/index.d.ts | 32 ++++ .../console_lang/ace/modes/index.js | 27 +++ .../elasticsearch_sql_highlight_rules.ts | 0 .../ace/modes/lexer_rules/index.js | 22 +++ .../lexer_rules}/script_highlight_rules.js | 0 .../lexer_rules}/x_json_highlight_rules.js | 31 ++- .../console_lang/ace/modes/x_json/index.ts | 20 ++ .../ace/modes/x_json/x_json_mode.ts | 40 ++++ .../es_ui_shared/console_lang/index.ts | 29 +++ .../es_ui_shared/console_lang/lib/index.ts | 20 ++ .../json_xjson_translation_tools.test.ts | 65 +++++++ .../__tests__/utils_string_collapsing.txt | 0 .../__tests__/utils_string_expanding.txt | 0 .../lib/json_xjson_translation_tools/index.ts | 71 +++++++ src/plugins/es_ui_shared/public/index.ts | 2 +- .../console_lang/ace/modes/index.ts | 7 + .../console_lang/ace/modes/x_json/index.ts | 7 + .../ace/modes/x_json}/worker/index.ts | 0 .../ace/modes/x_json}/worker/worker.d.ts | 0 .../ace/modes/x_json}/worker/worker.js | 0 .../console_lang/ace/modes/x_json/x_json.ts | 34 ++++ .../es_ui_shared/console_lang/index.ts | 7 + .../es_ui_shared/console_lang/mocks.ts | 9 + .../application/containers/main/main.tsx | 1 - .../public/application/editor/editor.test.tsx | 4 +- .../public/application/editor/init_editor.ts | 2 +- .../editor/x_json_highlight_rules.ts | 139 -------------- .../public/application/editor/x_json_mode.ts | 54 ------ .../utils/check_for_json_errors.ts | 7 +- .../watch_create_json.test.ts | 2 + .../watch_create_threshold.test.tsx | 3 + .../client_integration/watch_edit.test.ts | 2 + .../client_integration/watch_list.test.ts | 1 + .../client_integration/watch_status.test.ts | 2 + .../json_watch_edit/json_watch_edit_form.tsx | 16 +- .../json_watch_edit_simulate.tsx | 15 +- .../json_watch_edit/use_x_json_mode.ts | 24 +++ .../action_fields/webhook_action_fields.tsx | 2 +- 51 files changed, 591 insertions(+), 417 deletions(-) create mode 100644 src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.ts rename src/plugins/console/public/lib/utils/{utils.ts => index.ts} (59%) create mode 100644 src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts create mode 100644 src/plugins/es_ui_shared/console_lang/ace/modes/index.js rename src/plugins/{console/public/application/models/legacy_core_editor/mode => es_ui_shared/console_lang/ace/modes/lexer_rules}/elasticsearch_sql_highlight_rules.ts (100%) create mode 100644 src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/index.js rename src/plugins/{console/public/application/models/legacy_core_editor/mode => es_ui_shared/console_lang/ace/modes/lexer_rules}/script_highlight_rules.js (100%) rename src/plugins/{console/public/application/models/legacy_core_editor/mode => es_ui_shared/console_lang/ace/modes/lexer_rules}/x_json_highlight_rules.js (85%) create mode 100644 src/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts create mode 100644 src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.ts create mode 100644 src/plugins/es_ui_shared/console_lang/index.ts create mode 100644 src/plugins/es_ui_shared/console_lang/lib/index.ts create mode 100644 src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts rename src/plugins/{console/public/lib/utils => es_ui_shared/console_lang/lib/json_xjson_translation_tools}/__tests__/utils_string_collapsing.txt (100%) rename src/plugins/{console/public/lib/utils => es_ui_shared/console_lang/lib/json_xjson_translation_tools}/__tests__/utils_string_expanding.txt (100%) create mode 100644 src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/index.ts create mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/index.ts create mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts rename x-pack/plugins/{searchprofiler/public/application/editor => es_ui_shared/console_lang/ace/modes/x_json}/worker/index.ts (100%) rename x-pack/plugins/{searchprofiler/public/application/editor => es_ui_shared/console_lang/ace/modes/x_json}/worker/worker.d.ts (100%) rename x-pack/plugins/{searchprofiler/public/application/editor => es_ui_shared/console_lang/ace/modes/x_json}/worker/worker.js (100%) create mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts create mode 100644 x-pack/plugins/es_ui_shared/console_lang/index.ts create mode 100644 x-pack/plugins/es_ui_shared/console_lang/mocks.ts delete mode 100644 x-pack/plugins/searchprofiler/public/application/editor/x_json_highlight_rules.ts delete mode 100644 x-pack/plugins/searchprofiler/public/application/editor/x_json_mode.ts create mode 100644 x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx index e232e41902cbb..ca468f85275a8 100644 --- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx +++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx @@ -26,7 +26,7 @@ import { useRequestReadContext, } from '../../../../contexts'; -import * as utils from '../../../../../lib/utils/utils'; +import { expandLiteralStrings } from '../../../../../../../es_ui_shared/console_lang/lib'; import { subscribeResizeChecker } from '../subscribe_console_resize_checker'; import { applyCurrentSettings } from './apply_editor_settings'; @@ -67,7 +67,7 @@ function EditorOutputUI() { editor.update( data .map(d => d.response.value as string) - .map(readOnlySettings.tripleQuotes ? utils.expandLiteralStrings : a => a) + .map(readOnlySettings.tripleQuotes ? expandLiteralStrings : a => a) .join('\n') ); } else if (error) { diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts b/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts index 35d9865ee4ccb..102f90a9feb6f 100644 --- a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts +++ b/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts @@ -17,10 +17,11 @@ * under the License. */ -import * as utils from '../../../lib/utils/utils'; +import { extractDeprecationMessages } from '../../../lib/utils'; +import { collapseLiteralStrings } from '../../../../../es_ui_shared/console_lang/lib'; // @ts-ignore import * as es from '../../../lib/es/es'; -import { BaseResponseType } from '../../../types/common'; +import { BaseResponseType } from '../../../types'; export interface EsRequestArgs { requests: any; @@ -73,7 +74,7 @@ export function sendRequestToES(args: EsRequestArgs): Promise const req = requests.shift(); const esPath = req.url; const esMethod = req.method; - let esData = utils.collapseLiteralStrings(req.data.join('\n')); + let esData = collapseLiteralStrings(req.data.join('\n')); if (esData) { esData += '\n'; } // append a new line for bulk requests. @@ -97,7 +98,7 @@ export function sendRequestToES(args: EsRequestArgs): Promise const warnings = xhr.getResponseHeader('warning'); if (warnings) { - const deprecationMessages = utils.extractDeprecationMessages(warnings); + const deprecationMessages = extractDeprecationMessages(warnings); value = deprecationMessages.join('\n') + '\n' + value; } diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js index da101b61f8035..d763db7ae5d79 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js @@ -18,6 +18,7 @@ */ import ace from 'brace'; +import { workerModule } from './worker'; const oop = ace.acequire('ace/lib/oop'); const TextMode = ace.acequire('ace/mode/text').Mode; @@ -29,7 +30,6 @@ const WorkerClient = ace.acequire('ace/worker/worker_client').WorkerClient; const AceTokenizer = ace.acequire('ace/tokenizer').Tokenizer; const HighlightRules = require('./input_highlight_rules').InputHighlightRules; -import { workerModule } from './worker'; export function Mode() { this.$tokenizer = new AceTokenizer(new HighlightRules().getRules()); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js index 842736428e8bb..2c1b30f806f95 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js @@ -18,7 +18,7 @@ */ const ace = require('brace'); -import { addToRules } from './x_json_highlight_rules'; +import { addXJsonToRules } from '../../../../../../es_ui_shared/console_lang'; export function addEOL(tokens, reg, nextIfEOL, normalNext) { if (typeof reg === 'object') { @@ -101,7 +101,7 @@ export function InputHighlightRules() { ), }; - addToRules(this); + addXJsonToRules(this); if (this.constructor === InputHighlightRules) { this.normalizeRules(); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js index 920bdff1798db..e27222ebd65e9 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js @@ -19,7 +19,7 @@ const ace = require('brace'); import 'brace/mode/json'; -import { addToRules } from './x_json_highlight_rules'; +import { addXJsonToRules } from '../../../../../../es_ui_shared/console_lang'; const oop = ace.acequire('ace/lib/oop'); const JsonHighlightRules = ace.acequire('ace/mode/json_highlight_rules').JsonHighlightRules; @@ -27,7 +27,7 @@ const JsonHighlightRules = ace.acequire('ace/mode/json_highlight_rules').JsonHig export function OutputJsonHighlightRules() { this.$rules = {}; - addToRules(this, 'start'); + addXJsonToRules(this, 'start'); this.$rules.start.unshift( { diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js index b6b74c6377233..13ae329380221 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js @@ -18,17 +18,15 @@ */ import ace from 'brace'; +import { ScriptHighlightRules } from '../../../../../../es_ui_shared/console_lang'; const oop = ace.acequire('ace/lib/oop'); const TextMode = ace.acequire('ace/mode/text').Mode; const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent; const CstyleBehaviour = ace.acequire('ace/mode/behaviour/cstyle').CstyleBehaviour; const CStyleFoldMode = ace.acequire('ace/mode/folding/cstyle').FoldMode; -//const WorkerClient = ace.acequire('ace/worker/worker_client').WorkerClient; ace.acequire('ace/tokenizer'); -const ScriptHighlightRules = require('./script_highlight_rules').ScriptHighlightRules; - export function ScriptMode() { this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CstyleBehaviour(); @@ -57,19 +55,4 @@ oop.inherits(ScriptMode, TextMode); this.autoOutdent = function(state, doc, row) { this.$outdent.autoOutdent(doc, row); }; - - // this.createWorker = function (session) { - // const worker = new WorkerClient(['ace', 'sense_editor'], 'sense_editor/mode/worker', 'SenseWorker', 'sense_editor/mode/worker'); - // worker.attachToDocument(session.getDocument()); - - // worker.on('error', function (e) { - // session.setAnnotations([e.data]); - // }); - - // worker.on('ok', function (anno) { - // session.setAnnotations(anno.data); - // }); - - // return worker; - // }; }.call(ScriptMode.prototype)); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.ts b/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.ts new file mode 100644 index 0000000000000..c7ceb6a95b896 --- /dev/null +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.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 declare const workerModule: { id: string; src: string }; diff --git a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js index a66bc20685df7..63f97345bc9ff 100644 --- a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js +++ b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js @@ -22,8 +22,8 @@ import $ from 'jquery'; import _ from 'lodash'; import { create } from '../create'; +import { collapseLiteralStrings } from '../../../../../../es_ui_shared/console_lang/lib'; const editorInput1 = require('./editor_input1.txt'); -const utils = require('../../../../lib/utils/utils'); describe('Editor', () => { let input; @@ -331,7 +331,7 @@ describe('Editor', () => { const expected = { method: 'POST', url: '_search', - data: [utils.collapseLiteralStrings(simpleRequest.data)], + data: [collapseLiteralStrings(simpleRequest.data)], }; compareRequest(request, expected); diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts index 1271f167c6cc1..f559f5dfcd707 100644 --- a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts +++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts @@ -19,7 +19,9 @@ import _ from 'lodash'; import RowParser from '../../../lib/row_parser'; -import * as utils from '../../../lib/utils/utils'; +import { collapseLiteralStrings } from '../../../../../es_ui_shared/console_lang/lib'; +import * as utils from '../../../lib/utils'; + // @ts-ignore import * as es from '../../../lib/es/es'; @@ -480,7 +482,7 @@ export class SenseEditor { let ret = 'curl -X' + esMethod + ' "' + url + '"'; if (esData && esData.length) { ret += " -H 'Content-Type: application/json' -d'\n"; - const dataAsString = utils.collapseLiteralStrings(esData.join('\n')); + const dataAsString = collapseLiteralStrings(esData.join('\n')); // since Sense doesn't allow single quote json string any single qoute is within a string. ret += dataAsString.replace(/'/g, '\\"'); if (esData.length > 1) { diff --git a/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts b/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts index 00bfe32c85906..d5465ebe96514 100644 --- a/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts +++ b/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import '../../application/models/sense_editor/sense_editor.test.mocks'; import $ from 'jquery'; diff --git a/src/plugins/console/public/lib/autocomplete/autocomplete.ts b/src/plugins/console/public/lib/autocomplete/autocomplete.ts index ac8fa1ea48caa..e09024ccfc859 100644 --- a/src/plugins/console/public/lib/autocomplete/autocomplete.ts +++ b/src/plugins/console/public/lib/autocomplete/autocomplete.ts @@ -29,7 +29,7 @@ import { // @ts-ignore } from '../kb/kb'; -import * as utils from '../utils/utils'; +import * as utils from '../utils'; // @ts-ignore import { populateContext } from './engine'; diff --git a/src/plugins/console/public/lib/utils/__tests__/utils.test.js b/src/plugins/console/public/lib/utils/__tests__/utils.test.js index f6828f354a1bc..6115be3c84ed9 100644 --- a/src/plugins/console/public/lib/utils/__tests__/utils.test.js +++ b/src/plugins/console/public/lib/utils/__tests__/utils.test.js @@ -17,125 +17,80 @@ * under the License. */ -const _ = require('lodash'); -const utils = require('../utils'); -const collapsingTests = require('./utils_string_collapsing.txt'); -const expandingTests = require('./utils_string_expanding.txt'); +const utils = require('../'); describe('Utils class', () => { - describe('collapseLiteralStrings', () => { - it('will collapse multiline strings', () => { - const multiline = '{ "foo": """bar\nbaz""" }'; - expect(utils.collapseLiteralStrings(multiline)).toEqual('{ "foo": "bar\\nbaz" }'); - }); + test('extract deprecation messages', function() { + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT"' + ) + ).toEqual(['#! Deprecation: this is a warning']); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning"' + ) + ).toEqual(['#! Deprecation: this is a warning']); - it('will collapse multiline strings with CRLF endings', () => { - const multiline = '{ "foo": """bar\r\nbaz""" }'; - expect(utils.collapseLiteralStrings(multiline)).toEqual('{ "foo": "bar\\r\\nbaz" }'); - }); - }); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT", 299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a second warning" "Mon, 27 Feb 2017 14:52:14 GMT"' + ) + ).toEqual(['#! Deprecation: this is a warning', '#! Deprecation: this is a second warning']); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning", 299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a second warning"' + ) + ).toEqual(['#! Deprecation: this is a warning', '#! Deprecation: this is a second warning']); - _.each(collapsingTests.split(/^=+$/m), function(fixture) { - if (fixture.trim() === '') { - return; - } - fixture = fixture.split(/^-+$/m); - const name = fixture[0].trim(); - const expanded = fixture[1].trim(); - const collapsed = fixture[2].trim(); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes a comma" "Mon, 27 Feb 2017 14:52:14 GMT"' + ) + ).toEqual(['#! Deprecation: this is a warning, and it includes a comma']); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes a comma"' + ) + ).toEqual(['#! Deprecation: this is a warning, and it includes a comma']); - test('Literal collapse - ' + name, function() { - expect(utils.collapseLiteralStrings(expanded)).toEqual(collapsed); - }); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes an escaped backslash \\\\ and a pair of \\"escaped quotes\\"" "Mon, 27 Feb 2017 14:52:14 GMT"' + ) + ).toEqual([ + '#! Deprecation: this is a warning, and it includes an escaped backslash \\ and a pair of "escaped quotes"', + ]); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes an escaped backslash \\\\ and a pair of \\"escaped quotes\\""' + ) + ).toEqual([ + '#! Deprecation: this is a warning, and it includes an escaped backslash \\ and a pair of "escaped quotes"', + ]); }); - _.each(expandingTests.split(/^=+$/m), function(fixture) { - if (fixture.trim() === '') { - return; - } - fixture = fixture.split(/^-+$/m); - const name = fixture[0].trim(); - const collapsed = fixture[1].trim(); - const expanded = fixture[2].trim(); - - test('Literal expand - ' + name, function() { - expect(utils.expandLiteralStrings(collapsed)).toEqual(expanded); - }); - - test('extract deprecation messages', function() { - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT"' - ) - ).toEqual(['#! Deprecation: this is a warning']); - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning"' - ) - ).toEqual(['#! Deprecation: this is a warning']); - - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT", 299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a second warning" "Mon, 27 Feb 2017 14:52:14 GMT"' - ) - ).toEqual(['#! Deprecation: this is a warning', '#! Deprecation: this is a second warning']); - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning", 299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a second warning"' - ) - ).toEqual(['#! Deprecation: this is a warning', '#! Deprecation: this is a second warning']); - - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes a comma" "Mon, 27 Feb 2017 14:52:14 GMT"' - ) - ).toEqual(['#! Deprecation: this is a warning, and it includes a comma']); - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes a comma"' - ) - ).toEqual(['#! Deprecation: this is a warning, and it includes a comma']); - - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes an escaped backslash \\\\ and a pair of \\"escaped quotes\\"" "Mon, 27 Feb 2017 14:52:14 GMT"' - ) - ).toEqual([ - '#! Deprecation: this is a warning, and it includes an escaped backslash \\ and a pair of "escaped quotes"', - ]); - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes an escaped backslash \\\\ and a pair of \\"escaped quotes\\""' - ) - ).toEqual([ - '#! Deprecation: this is a warning, and it includes an escaped backslash \\ and a pair of "escaped quotes"', - ]); - }); - - test('unescape', function() { - expect(utils.unescape('escaped backslash \\\\')).toEqual('escaped backslash \\'); - expect(utils.unescape('a pair of \\"escaped quotes\\"')).toEqual( - 'a pair of "escaped quotes"' - ); - expect(utils.unescape('escaped quotes do not have to come in pairs: \\"')).toEqual( - 'escaped quotes do not have to come in pairs: "' - ); - }); + test('unescape', function() { + expect(utils.unescape('escaped backslash \\\\')).toEqual('escaped backslash \\'); + expect(utils.unescape('a pair of \\"escaped quotes\\"')).toEqual('a pair of "escaped quotes"'); + expect(utils.unescape('escaped quotes do not have to come in pairs: \\"')).toEqual( + 'escaped quotes do not have to come in pairs: "' + ); + }); - test('split on unquoted comma followed by space', function() { - expect(utils.splitOnUnquotedCommaSpace('a, b')).toEqual(['a', 'b']); - expect(utils.splitOnUnquotedCommaSpace('a,b, c')).toEqual(['a,b', 'c']); - expect(utils.splitOnUnquotedCommaSpace('"a, b"')).toEqual(['"a, b"']); - expect(utils.splitOnUnquotedCommaSpace('"a, b", c')).toEqual(['"a, b"', 'c']); - expect(utils.splitOnUnquotedCommaSpace('"a, b\\", c"')).toEqual(['"a, b\\", c"']); - expect(utils.splitOnUnquotedCommaSpace(', a, b')).toEqual(['', 'a', 'b']); - expect(utils.splitOnUnquotedCommaSpace('a, b, ')).toEqual(['a', 'b', '']); - expect(utils.splitOnUnquotedCommaSpace('\\"a, b", "c, d\\", e", f"')).toEqual([ - '\\"a', - 'b", "c', - 'd\\"', - 'e", f"', - ]); - }); + test('split on unquoted comma followed by space', function() { + expect(utils.splitOnUnquotedCommaSpace('a, b')).toEqual(['a', 'b']); + expect(utils.splitOnUnquotedCommaSpace('a,b, c')).toEqual(['a,b', 'c']); + expect(utils.splitOnUnquotedCommaSpace('"a, b"')).toEqual(['"a, b"']); + expect(utils.splitOnUnquotedCommaSpace('"a, b", c')).toEqual(['"a, b"', 'c']); + expect(utils.splitOnUnquotedCommaSpace('"a, b\\", c"')).toEqual(['"a, b\\", c"']); + expect(utils.splitOnUnquotedCommaSpace(', a, b')).toEqual(['', 'a', 'b']); + expect(utils.splitOnUnquotedCommaSpace('a, b, ')).toEqual(['a', 'b', '']); + expect(utils.splitOnUnquotedCommaSpace('\\"a, b", "c, d\\", e", f"')).toEqual([ + '\\"a', + 'b", "c', + 'd\\"', + 'e", f"', + ]); }); }); diff --git a/src/plugins/console/public/lib/utils/utils.ts b/src/plugins/console/public/lib/utils/index.ts similarity index 59% rename from src/plugins/console/public/lib/utils/utils.ts rename to src/plugins/console/public/lib/utils/index.ts index 0b10938abe704..f66c952dd3af7 100644 --- a/src/plugins/console/public/lib/utils/utils.ts +++ b/src/plugins/console/public/lib/utils/index.ts @@ -18,6 +18,10 @@ */ import _ from 'lodash'; +import { + expandLiteralStrings, + collapseLiteralStrings, +} from '../../../../es_ui_shared/console_lang/lib'; export function textFromRequest(request: any) { let data = request.data; @@ -56,59 +60,6 @@ export function formatRequestBodyDoc(data: string[], indent: boolean) { }; } -export function collapseLiteralStrings(data: any) { - const splitData = data.split(`"""`); - for (let idx = 1; idx < splitData.length - 1; idx += 2) { - splitData[idx] = JSON.stringify(splitData[idx]); - } - return splitData.join(''); -} - -/* - The following regex describes global match on: - 1. one colon followed by any number of space characters - 2. one double quote (not escaped, special case for JSON in JSON). - 3. greedily match any non double quote and non newline char OR any escaped double quote char (non-capturing). - 4. handle a special case where an escaped slash may be the last character - 5. one double quote - - For instance: `: "some characters \" here"` - Will match and be expanded to: `"""some characters " here"""` - - */ - -const LITERAL_STRING_CANDIDATES = /((:[\s\r\n]*)([^\\])"(\\"|[^"\n])*\\?")/g; - -export function expandLiteralStrings(data: string) { - return data.replace(LITERAL_STRING_CANDIDATES, (match, string) => { - // Expand to triple quotes if there are _any_ slashes - if (string.match(/\\./)) { - const firstDoubleQuoteIdx = string.indexOf('"'); - const lastDoubleQuoteIdx = string.lastIndexOf('"'); - - // Handle a special case where we may have a value like "\"test\"". We don't - // want to expand this to """"test"""" - so we terminate before processing the string - // further if we detect this either at the start or end of the double quote section. - - if (string[firstDoubleQuoteIdx + 1] === '\\' && string[firstDoubleQuoteIdx + 2] === '"') { - return string; - } - - if (string[lastDoubleQuoteIdx - 1] === '"' && string[lastDoubleQuoteIdx - 2] === '\\') { - return string; - } - - const colonAndAnySpacing = string.slice(0, firstDoubleQuoteIdx); - const rawStringifiedValue = string.slice(firstDoubleQuoteIdx, string.length); - // Remove one level of JSON stringification - const jsonValue = JSON.parse(rawStringifiedValue); - return `${colonAndAnySpacing}"""${jsonValue}"""`; - } else { - return string; - } - }); -} - export function extractDeprecationMessages(warnings: string) { // pattern for valid warning header const re = /\d{3} [0-9a-zA-Z!#$%&'*+-.^_`|~]+ \"((?:\t| |!|[\x23-\x5b]|[\x5d-\x7e]|[\x80-\xff]|\\\\|\\")*)\"(?: \"[^"]*\")?/; diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts b/src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts new file mode 100644 index 0000000000000..06c9f9a51ea68 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts @@ -0,0 +1,32 @@ +/* + * 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 { Editor } from 'brace'; + +export declare const ElasticsearchSqlHighlightRules: FunctionConstructor; +export declare const ScriptHighlightRules: FunctionConstructor; +export declare const XJsonHighlightRules: FunctionConstructor; + +export declare const XJsonMode: FunctionConstructor; + +/** + * @param otherRules Another Ace ruleset + * @param embedUnder The state name under which the rules will be embedded. Defaults to "json". + */ +export declare const addXJsonToRules: (otherRules: any, embedUnder?: string) => void; diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/index.js b/src/plugins/es_ui_shared/console_lang/ace/modes/index.js new file mode 100644 index 0000000000000..955f23116f659 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/index.js @@ -0,0 +1,27 @@ +/* + * 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 { + ElasticsearchSqlHighlightRules, + ScriptHighlightRules, + XJsonHighlightRules, + addXJsonToRules, +} from './lexer_rules'; + +export { XJsonMode, installXJsonMode } from './x_json'; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/elasticsearch_sql_highlight_rules.ts b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts similarity index 100% rename from src/plugins/console/public/application/models/legacy_core_editor/mode/elasticsearch_sql_highlight_rules.ts rename to src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/index.js b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/index.js new file mode 100644 index 0000000000000..be11fd726b7f2 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/index.js @@ -0,0 +1,22 @@ +/* + * 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 { ElasticsearchSqlHighlightRules } from './elasticsearch_sql_highlight_rules'; +export { ScriptHighlightRules } from './script_highlight_rules'; +export { XJsonHighlightRules, addToRules as addXJsonToRules } from './x_json_highlight_rules'; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/script_highlight_rules.js b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/script_highlight_rules.js similarity index 100% rename from src/plugins/console/public/application/models/legacy_core_editor/mode/script_highlight_rules.js rename to src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/script_highlight_rules.js diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/x_json_highlight_rules.js b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.js similarity index 85% rename from src/plugins/console/public/application/models/legacy_core_editor/mode/x_json_highlight_rules.js rename to src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.js index d0a79e84e809d..14323b9320330 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/x_json_highlight_rules.js +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.js @@ -17,11 +17,16 @@ * under the License. */ -const _ = require('lodash'); +import * as _ from 'lodash'; +import ace from 'brace'; +import 'brace/mode/json'; import { ElasticsearchSqlHighlightRules } from './elasticsearch_sql_highlight_rules'; const { ScriptHighlightRules } = require('./script_highlight_rules'); +const { JsonHighlightRules } = ace.acequire('ace/mode/json_highlight_rules'); +const oop = ace.acequire('ace/lib/oop'); + const jsonRules = function(root) { root = root ? root : 'json'; const rules = {}; @@ -146,6 +151,30 @@ const jsonRules = function(root) { return rules; }; +export function XJsonHighlightRules() { + this.$rules = { + ...jsonRules('start'), + }; + + this.embedRules(ScriptHighlightRules, 'script-', [ + { + token: 'punctuation.end_triple_quote', + regex: '"""', + next: 'pop', + }, + ]); + + this.embedRules(ElasticsearchSqlHighlightRules, 'sql-', [ + { + token: 'punctuation.end_triple_quote', + regex: '"""', + next: 'pop', + }, + ]); +} + +oop.inherits(XJsonHighlightRules, JsonHighlightRules); + export function addToRules(otherRules, embedUnder) { otherRules.$rules = _.defaultsDeep(otherRules.$rules, jsonRules(embedUnder)); otherRules.embedRules(ScriptHighlightRules, 'script-', [ diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts b/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts new file mode 100644 index 0000000000000..caa7b518b8b66 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/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 { XJsonMode } from './x_json_mode'; diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.ts b/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.ts new file mode 100644 index 0000000000000..9f804c29a5d27 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.ts @@ -0,0 +1,40 @@ +/* + * 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 ace from 'brace'; + +import { XJsonHighlightRules } from '../index'; + +const oop = ace.acequire('ace/lib/oop'); +const { Mode: JSONMode } = ace.acequire('ace/mode/json'); +const { Tokenizer: AceTokenizer } = ace.acequire('ace/tokenizer'); +const { MatchingBraceOutdent } = ace.acequire('ace/mode/matching_brace_outdent'); +const { CstyleBehaviour } = ace.acequire('ace/mode/behaviour/cstyle'); +const { FoldMode: CStyleFoldMode } = ace.acequire('ace/mode/folding/cstyle'); + +export function XJsonMode(this: any) { + const ruleset: any = new XJsonHighlightRules(); + ruleset.normalizeRules(); + this.$tokenizer = new AceTokenizer(ruleset.getRules()); + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +} + +oop.inherits(XJsonMode, JSONMode); diff --git a/src/plugins/es_ui_shared/console_lang/index.ts b/src/plugins/es_ui_shared/console_lang/index.ts new file mode 100644 index 0000000000000..a4958911af412 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +// Lib is intentionally not included in this barrel export file to separate worker logic +// from being imported with pure functions + +export { + ElasticsearchSqlHighlightRules, + ScriptHighlightRules, + XJsonHighlightRules, + addXJsonToRules, + XJsonMode, +} from './ace/modes'; diff --git a/src/plugins/es_ui_shared/console_lang/lib/index.ts b/src/plugins/es_ui_shared/console_lang/lib/index.ts new file mode 100644 index 0000000000000..bf7f0290d4158 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/lib/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 { collapseLiteralStrings, expandLiteralStrings } from './json_xjson_translation_tools'; diff --git a/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts new file mode 100644 index 0000000000000..92c14ade791cd --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts @@ -0,0 +1,65 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import _ from 'lodash'; +// @ts-ignore +import collapsingTests from './utils_string_collapsing.txt'; +// @ts-ignore +import expandingTests from './utils_string_expanding.txt'; + +import * as utils from '../index'; + +describe('JSON to XJSON conversion tools', () => { + it('will collapse multiline strings', () => { + const multiline = '{ "foo": """bar\nbaz""" }'; + expect(utils.collapseLiteralStrings(multiline)).toEqual('{ "foo": "bar\\nbaz" }'); + }); + + it('will collapse multiline strings with CRLF endings', () => { + const multiline = '{ "foo": """bar\r\nbaz""" }'; + expect(utils.collapseLiteralStrings(multiline)).toEqual('{ "foo": "bar\\r\\nbaz" }'); + }); +}); + +_.each(collapsingTests.split(/^=+$/m), function(fixture) { + if (fixture.trim() === '') { + return; + } + fixture = fixture.split(/^-+$/m); + const name = fixture[0].trim(); + const expanded = fixture[1].trim(); + const collapsed = fixture[2].trim(); + + test('Literal collapse - ' + name, function() { + expect(utils.collapseLiteralStrings(expanded)).toEqual(collapsed); + }); +}); + +_.each(expandingTests.split(/^=+$/m), function(fixture) { + if (fixture.trim() === '') { + return; + } + fixture = fixture.split(/^-+$/m); + const name = fixture[0].trim(); + const collapsed = fixture[1].trim(); + const expanded = fixture[2].trim(); + + test('Literal expand - ' + name, function() { + expect(utils.expandLiteralStrings(collapsed)).toEqual(expanded); + }); +}); diff --git a/src/plugins/console/public/lib/utils/__tests__/utils_string_collapsing.txt b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt similarity index 100% rename from src/plugins/console/public/lib/utils/__tests__/utils_string_collapsing.txt rename to src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt diff --git a/src/plugins/console/public/lib/utils/__tests__/utils_string_expanding.txt b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt similarity index 100% rename from src/plugins/console/public/lib/utils/__tests__/utils_string_expanding.txt rename to src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt diff --git a/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/index.ts b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/index.ts new file mode 100644 index 0000000000000..28f1aca95efab --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/index.ts @@ -0,0 +1,71 @@ +/* + * 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 function collapseLiteralStrings(data: string) { + const splitData = data.split(`"""`); + for (let idx = 1; idx < splitData.length - 1; idx += 2) { + splitData[idx] = JSON.stringify(splitData[idx]); + } + return splitData.join(''); +} + +/* + The following regex describes global match on: + 1. one colon followed by any number of space characters + 2. one double quote (not escaped, special case for JSON in JSON). + 3. greedily match any non double quote and non newline char OR any escaped double quote char (non-capturing). + 4. handle a special case where an escaped slash may be the last character + 5. one double quote + + For instance: `: "some characters \" here"` + Will match and be expanded to: `"""some characters " here"""` + + */ + +const LITERAL_STRING_CANDIDATES = /((:[\s\r\n]*)([^\\])"(\\"|[^"\n])*\\?")/g; + +export function expandLiteralStrings(data: string) { + return data.replace(LITERAL_STRING_CANDIDATES, (match, string) => { + // Expand to triple quotes if there are _any_ slashes + if (string.match(/\\./)) { + const firstDoubleQuoteIdx = string.indexOf('"'); + const lastDoubleQuoteIdx = string.lastIndexOf('"'); + + // Handle a special case where we may have a value like "\"test\"". We don't + // want to expand this to """"test"""" - so we terminate before processing the string + // further if we detect this either at the start or end of the double quote section. + + if (string[firstDoubleQuoteIdx + 1] === '\\' && string[firstDoubleQuoteIdx + 2] === '"') { + return string; + } + + if (string[lastDoubleQuoteIdx - 1] === '"' && string[lastDoubleQuoteIdx - 2] === '\\') { + return string; + } + + const colonAndAnySpacing = string.slice(0, firstDoubleQuoteIdx); + const rawStringifiedValue = string.slice(firstDoubleQuoteIdx, string.length); + // Remove one level of JSON stringification + const jsonValue = JSON.parse(rawStringifiedValue); + return `${colonAndAnySpacing}"""${jsonValue}"""`; + } else { + return string; + } + }); +} diff --git a/src/plugins/es_ui_shared/public/index.ts b/src/plugins/es_ui_shared/public/index.ts index a12c951ad13a8..67e3617a85115 100644 --- a/src/plugins/es_ui_shared/public/index.ts +++ b/src/plugins/es_ui_shared/public/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export * from './components/json_editor'; +export { JsonEditor, OnJsonEditorUpdateHandler } from './components/json_editor'; diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/index.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/index.ts new file mode 100644 index 0000000000000..ae3c9962ecadb --- /dev/null +++ b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/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 { installXJsonMode, XJsonMode } from './x_json'; diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts new file mode 100644 index 0000000000000..ae3c9962ecadb --- /dev/null +++ b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/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 { installXJsonMode, XJsonMode } from './x_json'; diff --git a/x-pack/plugins/searchprofiler/public/application/editor/worker/index.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/index.ts similarity index 100% rename from x-pack/plugins/searchprofiler/public/application/editor/worker/index.ts rename to x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/index.ts diff --git a/x-pack/plugins/searchprofiler/public/application/editor/worker/worker.d.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.d.ts similarity index 100% rename from x-pack/plugins/searchprofiler/public/application/editor/worker/worker.d.ts rename to x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.d.ts diff --git a/x-pack/plugins/searchprofiler/public/application/editor/worker/worker.js b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.js similarity index 100% rename from x-pack/plugins/searchprofiler/public/application/editor/worker/worker.js rename to x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.js diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts new file mode 100644 index 0000000000000..bfeca045bea02 --- /dev/null +++ b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts @@ -0,0 +1,34 @@ +/* + * 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 ace from 'brace'; +import { XJsonMode } from '../../../../../../../src/plugins/es_ui_shared/console_lang'; +import { workerModule } from './worker'; +const { WorkerClient } = ace.acequire('ace/worker/worker_client'); + +// Then clobber `createWorker` method to install our worker source. Per ace's wiki: https://github.com/ajaxorg/ace/wiki/Syntax-validation +(XJsonMode.prototype as any).createWorker = function(session: ace.IEditSession) { + const xJsonWorker = new WorkerClient(['ace'], workerModule, 'JsonWorker'); + + xJsonWorker.attachToDocument(session.getDocument()); + + xJsonWorker.on('annotate', function(e: { data: any }) { + session.setAnnotations(e.data); + }); + + xJsonWorker.on('terminate', function() { + session.clearAnnotations(); + }); + + return xJsonWorker; +}; + +export { XJsonMode }; + +export function installXJsonMode(editor: ace.Editor) { + const session = editor.getSession(); + session.setMode(new (XJsonMode as any)()); +} diff --git a/x-pack/plugins/es_ui_shared/console_lang/index.ts b/x-pack/plugins/es_ui_shared/console_lang/index.ts new file mode 100644 index 0000000000000..b5fe3a554e34d --- /dev/null +++ b/x-pack/plugins/es_ui_shared/console_lang/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 { XJsonMode, installXJsonMode } from './ace/modes'; diff --git a/x-pack/plugins/es_ui_shared/console_lang/mocks.ts b/x-pack/plugins/es_ui_shared/console_lang/mocks.ts new file mode 100644 index 0000000000000..68480282ddc03 --- /dev/null +++ b/x-pack/plugins/es_ui_shared/console_lang/mocks.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +jest.mock('./ace/modes/x_json/worker', () => ({ + workerModule: { id: 'ace/mode/json_worker', src: '' }, +})); diff --git a/x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx b/x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx index 90617ba1c5167..aa6c20aa6a7f3 100644 --- a/x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx +++ b/x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx @@ -5,7 +5,6 @@ */ import React, { useCallback } from 'react'; -import _ from 'lodash'; import { EuiPage, diff --git a/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx b/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx index a70d70f117edb..ad56b3957eb74 100644 --- a/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx +++ b/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx @@ -6,9 +6,7 @@ import 'brace'; import 'brace/mode/json'; -jest.mock('./worker', () => { - return { workerModule: { id: 'ace/mode/json_worker', src: '' } }; -}); +import '../../../../es_ui_shared/console_lang/mocks'; import { registerTestBed } from '../../../../../test_utils'; import { Editor, Props } from '.'; diff --git a/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts b/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts index e5aad16bc4af2..6f19ce12eb639 100644 --- a/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts +++ b/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts @@ -5,7 +5,7 @@ */ import ace from 'brace'; -import { installXJsonMode } from './x_json_mode'; +import { installXJsonMode } from '../../../../es_ui_shared/console_lang'; export function initializeEditor({ el, diff --git a/x-pack/plugins/searchprofiler/public/application/editor/x_json_highlight_rules.ts b/x-pack/plugins/searchprofiler/public/application/editor/x_json_highlight_rules.ts deleted file mode 100644 index 1e6e774db2e52..0000000000000 --- a/x-pack/plugins/searchprofiler/public/application/editor/x_json_highlight_rules.ts +++ /dev/null @@ -1,139 +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 ace from 'brace'; -const oop = ace.acequire('ace/lib/oop'); -const { JsonHighlightRules } = ace.acequire('ace/mode/json_highlight_rules'); -const { TextHighlightRules } = ace.acequire('ace/mode/text_highlight_rules'); - -/* - * The rules below were copied from ./src/legacy/core_plugins/console/public/src/sense_editor/mode/x_json_highlight_rules.js - * - * It is very likely that this code will move (or be removed) in future but for now - * it enables syntax highlight for extended json. - */ - -const xJsonRules = { - start: [ - { - token: [ - 'variable', - 'whitespace', - 'ace.punctuation.colon', - 'whitespace', - 'punctuation.start_triple_quote', - ], - regex: '("(?:[^"]*_)?script"|"inline"|"source")(\\s*?)(:)(\\s*?)(""")', - next: 'script-start', - merge: false, - push: true, - }, - { - token: 'variable', // single line - regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)', - }, - { - token: 'punctuation.start_triple_quote', - regex: '"""', - next: 'string_literal', - merge: false, - push: true, - }, - { - token: 'string', // single line - regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]', - }, - { - token: 'constant.numeric', // hex - regex: '0[xX][0-9a-fA-F]+\\b', - }, - { - token: 'constant.numeric', // float - regex: '[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b', - }, - { - token: 'constant.language.boolean', - regex: '(?:true|false)\\b', - }, - { - token: 'invalid.illegal', // single quoted strings are not allowed - regex: "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']", - }, - { - token: 'invalid.illegal', // comments are not allowed - regex: '\\/\\/.*$', - }, - { - token: 'paren.lparen', - merge: false, - regex: '{', - next: 'start', - push: true, - }, - { - token: 'paren.lparen', - merge: false, - regex: '[[(]', - }, - { - token: 'paren.rparen', - merge: false, - regex: '[\\])]', - }, - { - token: 'paren.rparen', - regex: '}', - merge: false, - next: 'pop', - }, - { - token: 'punctuation.comma', - regex: ',', - }, - { - token: 'punctuation.colon', - regex: ':', - }, - { - token: 'whitespace', - regex: '\\s+', - }, - { - token: 'text', - regex: '.+?', - }, - ], - string_literal: [ - { - token: 'punctuation.end_triple_quote', - regex: '"""', - next: 'pop', - }, - { - token: 'multi_string', - regex: '.', - }, - ], -}; - -function XJsonHighlightRules(this: any) { - this.$rules = xJsonRules; -} - -oop.inherits(XJsonHighlightRules, JsonHighlightRules); - -export function getRules() { - const ruleset: any = new (XJsonHighlightRules as any)(); - ruleset.embedRules(TextHighlightRules, 'text-', [ - { - token: 'punctuation.end_triple_quote', - regex: '"""', - next: 'pop', - }, - ]); - ruleset.normalizeRules(); - return ruleset.getRules(); -} diff --git a/x-pack/plugins/searchprofiler/public/application/editor/x_json_mode.ts b/x-pack/plugins/searchprofiler/public/application/editor/x_json_mode.ts deleted file mode 100644 index 7ac1e6105d97f..0000000000000 --- a/x-pack/plugins/searchprofiler/public/application/editor/x_json_mode.ts +++ /dev/null @@ -1,54 +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. - */ - -// Copied and modified from src/legacy/core_plugins/console/public/src/sense_editor/mode/input.js - -import ace from 'brace'; - -import * as xJsonRules from './x_json_highlight_rules'; -import { workerModule } from './worker'; - -const oop = ace.acequire('ace/lib/oop'); -const { Mode: JSONMode } = ace.acequire('ace/mode/json'); -const { Tokenizer: AceTokenizer } = ace.acequire('ace/tokenizer'); -const { MatchingBraceOutdent } = ace.acequire('ace/mode/matching_brace_outdent'); -const { CstyleBehaviour } = ace.acequire('ace/mode/behaviour/cstyle'); -const { FoldMode: CStyleFoldMode } = ace.acequire('ace/mode/folding/cstyle'); -const { WorkerClient } = ace.acequire('ace/worker/worker_client'); - -function XJsonMode(this: any) { - this.$tokenizer = new AceTokenizer(xJsonRules.getRules()); - this.$outdent = new MatchingBraceOutdent(); - this.$behaviour = new CstyleBehaviour(); - this.foldingRules = new CStyleFoldMode(); -} - -// Order here matters here: - -// 1. We first inherit -oop.inherits(XJsonMode, JSONMode); - -// 2. Then clobber `createWorker` method to install our worker source. Per ace's wiki: https://github.com/ajaxorg/ace/wiki/Syntax-validation -XJsonMode.prototype.createWorker = function(session: ace.IEditSession) { - const xJsonWorker = new WorkerClient(['ace'], workerModule, 'JsonWorker'); - - xJsonWorker.attachToDocument(session.getDocument()); - - xJsonWorker.on('annotate', function(e: { data: any }) { - session.setAnnotations(e.data); - }); - - xJsonWorker.on('terminate', function() { - session.clearAnnotations(); - }); - - return xJsonWorker; -}; - -export function installXJsonMode(editor: ace.Editor) { - const session = editor.getSession(); - session.setMode(new (XJsonMode as any)()); -} diff --git a/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts b/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts index 4267fd0d2f901..99687de0f1440 100644 --- a/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts +++ b/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts @@ -4,12 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -// Convert triple quotes into regular quotes and escape internal quotes. -function collapseLiteralStrings(data: string) { - return data.replace(/"""(?:\s*\r?\n)?((?:.|\r?\n)*?)(?:\r?\n\s*)?"""/g, function(match, literal) { - return JSON.stringify(literal); - }); -} +import { collapseLiteralStrings } from '../../../../../../src/plugins/es_ui_shared/console_lang/lib'; export function checkForParseErrors(json: string) { const sanitizedJson = collapseLiteralStrings(json); diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts index 26be3421b534e..93b8cce153d3b 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts @@ -3,6 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import '../../../es_ui_shared/console_lang/mocks'; + import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers'; import { WatchCreateJsonTestBed } from './helpers/watch_create_json.helpers'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx index 431eb1cae0608..943233d3c14ed 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx @@ -3,6 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + +import '../../../es_ui_shared/console_lang/mocks'; + import React from 'react'; import { act } from 'react-dom/test-utils'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts index 545bfbdf7cbc2..51285a5786b00 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts @@ -3,6 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import '../../../es_ui_shared/console_lang/mocks'; + import { act } from 'react-dom/test-utils'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import axios from 'axios'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts index a0327c6dfa1db..3370e42b2417f 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import '../../../es_ui_shared/console_lang/mocks'; import { act } from 'react-dom/test-utils'; import * as fixtures from '../../test/fixtures'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts index 973c14893f342..20b7b526705c0 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts @@ -3,6 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import '../../../es_ui_shared/console_lang/mocks'; + import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers, nextTick } from './helpers'; import { WatchStatusTestBed } from './helpers/watch_status.helpers'; diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx index 91185ac604b34..b3a09d3bc0e65 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx @@ -20,6 +20,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; + import { serializeJsonWatch } from '../../../../../../common/lib/serialization'; import { ErrableFormRow, SectionError, Error as ServerError } from '../../../../components'; import { onWatchSave } from '../../watch_edit_actions'; @@ -28,6 +29,8 @@ import { goToWatchList } from '../../../../lib/navigation'; import { RequestFlyout } from '../request_flyout'; import { useAppContext } from '../../../../app_context'; +import { useXJsonMode } from './use_x_json_mode'; + export const JsonWatchEditForm = () => { const { links: { putWatchApiUrl }, @@ -35,6 +38,7 @@ export const JsonWatchEditForm = () => { } = useAppContext(); const { watch, setWatchProperty } = useContext(WatchContext); + const { xJsonMode, convertToJson, setXJson, xJson } = useXJsonMode(watch.watchString); const { errors } = watch.validate(); const hasErrors = !!Object.keys(errors).find(errorKey => errors[errorKey].length >= 1); @@ -160,9 +164,9 @@ export const JsonWatchEditForm = () => { errors={jsonErrors} > { defaultMessage: 'Code editor', } )} - value={watch.watchString} - onChange={(json: string) => { + value={xJson} + onChange={(xjson: string) => { if (validationError) { setValidationError(null); } - setWatchProperty('watchString', json); + setXJson(xjson); + // Keep the watch in sync with the editor content + setWatchProperty('watchString', convertToJson(xjson)); }} /> diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx index 9ac80ade89daa..c906d05be64be 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx @@ -40,6 +40,8 @@ import { JsonWatchEditSimulateResults } from './json_watch_edit_simulate_results import { getTimeUnitLabel } from '../../../../lib/get_time_unit_label'; import { useAppContext } from '../../../../app_context'; +import { useXJsonMode } from './use_x_json_mode'; + const actionModeOptions = Object.keys(ACTION_MODES).map(mode => ({ text: ACTION_MODES[mode], value: ACTION_MODES[mode], @@ -94,6 +96,8 @@ export const JsonWatchEditSimulate = ({ ignoreCondition, } = executeDetails; + const { setXJson, convertToJson, xJsonMode, xJson } = useXJsonMode(alternativeInput); + const columns = [ { field: 'actionId', @@ -371,22 +375,23 @@ export const JsonWatchEditSimulate = ({ > { + value={xJson} + onChange={(xjson: string) => { + setXJson(xjson); setExecuteDetails( new ExecuteDetails({ ...executeDetails, - alternativeInput: json, + alternativeInput: convertToJson(xjson), }) ); }} diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts new file mode 100644 index 0000000000000..7aefb0554e0e8 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts @@ -0,0 +1,24 @@ +/* + * 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 { useState } from 'react'; +import { XJsonMode } from '../../../../../../../es_ui_shared/console_lang'; +import { + collapseLiteralStrings, + expandLiteralStrings, +} from '../../../../../../../../../src/plugins/es_ui_shared/console_lang/lib'; + +export const xJsonMode = new XJsonMode(); + +export const useXJsonMode = (json: string) => { + const [xJson, setXJson] = useState(expandLiteralStrings(json)); + + return { + xJson, + setXJson, + xJsonMode, + convertToJson: collapseLiteralStrings, + }; +}; diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx index c1ebcdc262863..b79f9eee01834 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx @@ -245,7 +245,7 @@ export const WebhookActionFields: React.FunctionComponent = ({ mode="json" width="100%" height="200px" - theme="github" + theme="textmate" data-test-subj="webhookBodyEditor" aria-label={i18n.translate( 'xpack.watcher.sections.watchEdit.threshold.webhookAction.bodyCodeEditorAriaLabel',