diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/angular_template.html b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/angular_template.html new file mode 100644 index 0000000000000..25e12e2ea97da --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/angular_template.html @@ -0,0 +1,5 @@ + + +
+
+
diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/constants/index.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/constants/index.js new file mode 100644 index 0000000000000..ba29bd874b813 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/constants/index.js @@ -0,0 +1,7 @@ +// This isn't ideal. We want to avoid searching for 20 indices +// then filtering out the majority of them because they are sysetm indices. +// We'd like to filter system indices out in the query +// so if we can accomplish that in the future, this logic can go away +export const ESTIMATED_NUMBER_OF_SYSTEM_INDICES = 100; +export const MAX_NUMBER_OF_MATCHING_INDICES = 100; +export const MAX_SEARCH_SIZE = MAX_NUMBER_OF_MATCHING_INDICES + ESTIMATED_NUMBER_OF_SYSTEM_INDICES; diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/create_index_pattern_wizard.html b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/create_index_pattern_wizard.html deleted file mode 100644 index 732458288d59f..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/create_index_pattern_wizard.html +++ /dev/null @@ -1,157 +0,0 @@ - - -
- -

- Create index pattern -

- -
- -
-
-
-

- Kibana uses index patterns to retrieve data from Elasticsearch indices for things like visualizations. -

-
-
- -
-
- -
-
-
- -
-
-
- -
- -
- -
-
-
- -
-

- Checking for Elasticsearch data -

-
-
-
- -
-
-

- Reticulating splines... -

-
-
-
- - -
-
-

- Couldn't find any Elasticsearch data -

-
-

- - You'll need to index some data into Elasticsearch before you can create an index pattern. - - - Learn how. - -

-
- -
-
-
-
-
- - -
- - - - - -
-
-
-
-
diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/create_index_pattern_wizard.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/create_index_pattern_wizard.js index 597e0822be592..007cef37a0f43 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/create_index_pattern_wizard.js +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/create_index_pattern_wizard.js @@ -1,307 +1,232 @@ -import _ from 'lodash'; -import { IndexPatternMissingIndices } from 'ui/errors'; -import 'ui/directives/validate_index_pattern'; -import 'ui/directives/auto_select_if_only_one'; -import 'ui/directives/documentation_href'; -import uiRoutes from 'ui/routes'; -import { uiModules } from 'ui/modules'; -import template from './create_index_pattern_wizard.html'; -import { sendCreateIndexPatternRequest } from './send_create_index_pattern_request'; -import './step_index_pattern'; -import './step_time_field'; -import './matching_indices_list'; -import './create_index_pattern_wizard.less'; - -uiRoutes - .when('/management/kibana/index', { - template, - }); - -uiModules.get('apps/management') - .controller('managementIndicesCreate', function ( - $routeParams, - $scope, - $timeout, - config, - es, - indexPatterns, - kbnUrl, - Notifier, - Promise - ) { - // This isn't ideal. We want to avoid searching for 20 indices - // then filtering out the majority of them because they are sysetm indices. - // We'd like to filter system indices out in the query - // so if we can accomplish that in the future, this logic can go away - const ESTIMATED_NUMBER_OF_SYSTEM_INDICES = 20; - const MAX_NUMBER_OF_MATCHING_INDICES = 20; - const MAX_SEARCH_SIZE = MAX_NUMBER_OF_MATCHING_INDICES + ESTIMATED_NUMBER_OF_SYSTEM_INDICES; - const notify = new Notifier(); - const disabledDividerOption = { - isDisabled: true, - display: '───', - }; - const noTimeFieldOption = { - display: `I don't want to use the Time Filter`, +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { + EuiSpacer, + EuiTitle, + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiTextColor, + EuiSwitch, + EuiPanel, + EuiIcon, + EuiLink, + EuiButton, +} from '@elastic/eui'; + +import { MAX_SEARCH_SIZE } from './constants'; +import { getIndices } from './lib/get_indices'; + +export class CreateIndexPatternWizard extends Component { + static propTypes = { + loadingDataDocUrl: PropTypes.string.isRequired, + services: PropTypes.shape({ + es: PropTypes.object.isRequired, + indexPatterns: PropTypes.object.isRequired, + config: PropTypes.object.isRequired, + kbnUrl: PropTypes.object.isRequired, + notify: PropTypes.object.isRequired, + }).isRequired, + } + + constructor(props) { + super(props); + this.state = { + step: 1, + indexPattern: '', + initialIndices: [], + isInitiallyLoadingIndices: true, + isIncludingSystemIndices: false, }; + } - // Configure the new index pattern we're going to create. - this.formValues = { - id: $routeParams.id ? decodeURIComponent($routeParams.id) : undefined, - name: '', - expandWildcard: false, - timeFieldOption: undefined, - }; - - // UI state. - this.timeFieldOptions = []; - this.wizardStep = 'indexPattern'; - this.isFetchingExistingIndices = true; - this.isFetchingMatchingIndices = false; - this.isFetchingTimeFieldOptions = false; - this.isCreatingIndexPattern = false; - this.doesIncludeSystemIndices = false; - let allIndices = []; - let matchingIndices = []; - let partialMatchingIndices = []; - this.allIndices = []; - this.matchingIndices = []; - this.partialMatchingIndices = []; + async componentWillMount() { + const { services } = this.props; + const initialIndices = await getIndices(services.es, `*`, MAX_SEARCH_SIZE); + this.setState({ initialIndices, isInitiallyLoadingIndices: false }); + } - function createReasonableWait() { - return new Promise(resolve => { - // Make every fetch take a set amount of time so the user gets some feedback that something - // is happening. - $timeout(() => { - resolve(); - }, 500); - }); - } + createIndexPattern = async (timeFieldName, indexPatternId) => { + const { services } = this.props; + const { indexPattern } = this.state; - function getIndices(rawPattern, limit = MAX_SEARCH_SIZE) { - const pattern = rawPattern.trim(); + const emptyPattern = await services.indexPatterns.get(); - // Searching for `*:` fails for CCS environments. The search request - // is worthless anyways as the we should only send a request - // for a specific query (where we do not append *) if there is at - // least a single character being searched for. - if (pattern === '*:') { - return []; - } + Object.assign(emptyPattern, { + id: indexPatternId, + title: indexPattern, + timeFieldName, + }); - const params = { - index: pattern, - ignore: [404], - body: { - size: 0, // no hits - aggs: { - indices: { - terms: { - field: '_index', - size: limit, - } - } - } - } - }; + const createdId = await emptyPattern.create(); - return es.search(params) - .then(response => { - if (!response || response.error || !response.aggregations) { - return []; - } - - return _.sortBy(response.aggregations.indices.buckets.map(bucket => { - return { - name: bucket.key - }; - }), 'name'); - }) - .catch(err => { - const type = _.get(err, 'body.error.caused_by.type'); - if (type === 'index_not_found_exception') { - // This happens in a CSS environment when the controlling node returns a 500 even though the data - // nodes returned a 404. Remove this when/if this is handled: https://github.com/elastic/elasticsearch/issues/27461 - return []; - } - throw err; - }); + if (!services.config.get('defaultIndex')) { + services.config.set('defaultIndex', createdId); } - const whiteListIndices = indices => { - if (!indices) { - return indices; - } - - const acceptableIndices = this.doesIncludeSystemIndices - ? indices - // All system indices begin with a period. - : indices.filter(index => !index.name.startsWith('.')); - - return acceptableIndices.slice(0, MAX_NUMBER_OF_MATCHING_INDICES); - }; - - const updateWhiteListedIndices = () => { - this.allIndices = whiteListIndices(allIndices); - this.matchingIndices = whiteListIndices(matchingIndices); - this.partialMatchingIndices = whiteListIndices(partialMatchingIndices); - }; - - this.onIncludeSystemIndicesChange = () => { - updateWhiteListedIndices(); - }; - - let mostRecentFetchMatchingIndicesRequest; - - this.fetchMatchingIndices = () => { - this.isFetchingMatchingIndices = true; - - // Default to searching for all indices. - const exactSearchQuery = this.formValues.name; - let partialSearchQuery = this.formValues.name; - - if (!_.endsWith(partialSearchQuery, '*')) { - partialSearchQuery = `${partialSearchQuery}*`; - } - if (!_.startsWith(partialSearchQuery, '*')) { - partialSearchQuery = `*${partialSearchQuery}`; - } - - const thisFetchMatchingIndicesRequest = mostRecentFetchMatchingIndicesRequest = Promise.all([ - getIndices(exactSearchQuery), - getIndices(partialSearchQuery), - createReasonableWait() - ]) - .then(([ - matchingIndicesResponse, - partialMatchingIndicesResponse - ]) => { - if (thisFetchMatchingIndicesRequest === mostRecentFetchMatchingIndicesRequest) { - matchingIndices = matchingIndicesResponse; - partialMatchingIndices = partialMatchingIndicesResponse; - updateWhiteListedIndices(); - this.isFetchingMatchingIndices = false; - } - }).catch(error => { - notify.error(error); - }); - }; - - this.fetchExistingIndices = () => { - this.isFetchingExistingIndices = true; - const allExistingLocalIndicesPattern = '*'; - - Promise.all([ - getIndices(allExistingLocalIndicesPattern), - createReasonableWait() - ]) - .then(([allIndicesResponse]) => { - // Cache all indices. - allIndices = allIndicesResponse; - updateWhiteListedIndices(); - this.isFetchingExistingIndices = false; - }).catch(error => { - notify.error(error); - this.isFetchingExistingIndices = false; - }); - }; - - this.isSystemIndicesCheckBoxVisible = () => ( - this.wizardStep === 'indexPattern' + services.indexPatterns.cache.clear(createdId); + services.kbnUrl.change(`/management/kibana/indices/${createdId}`); + } + + goToTimeFieldStep = (indexPattern) => { + this.setState({ step: 2, indexPattern }); + } + + goToIndexPatternStep = () => { + this.setState({ step: 1 }); + } + + onChangeIncludingSystemIndices = () => { + this.setState(state => ({ + isIncludingSystemIndices: !state.isIncludingSystemIndices, + })); + } + + renderHeader() { + const { isIncludingSystemIndices } = this.state; + + return ( +
+ + +

Create index pattern

+
+ + + +

+ + Kibana uses index patterns to retrieve data from Elasticsearch indices for things like visualizations. + +

+
+
+ + + +
+ +
); + } - this.goToIndexPatternStep = () => { - this.wizardStep = 'indexPattern'; - }; + renderInitialLoadingState() { + const { isInitiallyLoadingIndices } = this.state; - this.goToTimeFieldStep = () => { - // Re-initialize this step. - this.formValues.timeFieldOption = undefined; - this.fetchTimeFieldOptions(); - this.wizardStep = 'timeField'; - }; + if (!isInitiallyLoadingIndices) { + return null; + } - this.hasIndices = () => ( - this.allIndices.length + return ( + + + + + +

Checking for Elasticsearch data

+
+
+ + +

+ + + Reticulating splines... + +

+
+
+
+
); + } - const extractTimeFieldsFromFields = fields => { - const dateFields = fields.filter(field => field.type === 'date'); - - if (dateFields.length === 0) { - return [{ - display: `The indices which match this index pattern don't contain any time fields.`, - }]; - } - - return [ - ...dateFields.map(field => ({ - display: field.name, - fieldName: field.name - })), - disabledDividerOption, - noTimeFieldOption, - ]; - }; - - this.fetchTimeFieldOptions = () => { - this.isFetchingTimeFieldOptions = true; - this.formValues.timeFieldOption = undefined; - this.timeFieldOptions = []; + renderInitialEmptyState() { + const { initialIndices, isInitiallyLoadingIndices } = this.state; + const { loadingDataDocUrl } = this.props; - Promise.all([ - indexPatterns.fieldsFetcher.fetchForWildcard(this.formValues.name), - createReasonableWait(), - ]) - .then(([fields]) => { - this.timeFieldOptions = extractTimeFieldsFromFields(fields); - }) - .catch(error => { - notify.error(error); - }) - .finally(() => { - this.isFetchingTimeFieldOptions = false; - }); - }; - - this.createIndexPattern = () => { - this.isCreatingIndexPattern = true; + if (initialIndices.length > 0 || isInitiallyLoadingIndices) { + return null; + } - const { - id, - name, - timeFieldOption, - } = this.formValues; + return ( + + + + + +

Couldn't find any Elasticsearch data

+
+
+ + +

+ + You'll need to index some data into Elasticsearch before you can create an index pattern. + +   + + Learn how. + +

+
+ + + + + Check for new data + + + +
+
+
+ ); + } - const timeFieldName = timeFieldOption - ? timeFieldOption.fieldName - : undefined; + renderStepOne() { + const { + isInitiallyLoadingIndices, + step, + } = this.state; - sendCreateIndexPatternRequest(indexPatterns, { - id, - name, - timeFieldName, - }).then(createdId => { - if (!createdId) { - return; - } + if (isInitiallyLoadingIndices || step !== 1) { + return null; + } - if (!config.get('defaultIndex')) { - config.set('defaultIndex', createdId); - } + return ( +
Step One
+ ); + } - indexPatterns.cache.clear(createdId); - kbnUrl.change(`/management/kibana/indices/${createdId}`); - }).catch(err => { - if (err instanceof IndexPatternMissingIndices) { - return notify.error(`Couldn't locate any indices matching that pattern. Please add the index to Elasticsearch`); - } + renderStepTwo() { + const { step } = this.state; - notify.fatal(err); - }).finally(() => { - this.isCreatingIndexPattern = false; - }); - }; + if (step !== 2) { + return null; + } - this.fetchExistingIndices(); - }); + return ( +
Step Two
+ ); + } + + render() { + return ( +
+ {this.renderHeader()} + {this.renderInitialLoadingState()} + {this.renderInitialEmptyState()} + {this.renderStepOne()} + {this.renderStepTwo()} +
+ ); + } +} diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/create_index_pattern_wizard.less b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/create_index_pattern_wizard.less deleted file mode 100644 index ce9d492978734..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/create_index_pattern_wizard.less +++ /dev/null @@ -1,4 +0,0 @@ -.createIndexPatternPrompt { - width: 100%; - max-width: 600px; -} diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/index.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/index.js index e6b701ce12c25..866cb2e99e341 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/index.js +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/index.js @@ -1 +1,37 @@ -import './create_index_pattern_wizard'; +import uiRoutes from 'ui/routes'; +import angularTemplate from './angular_template.html'; +import 'ui/index_patterns'; + +import React from 'react'; +import { render } from 'react-dom'; +import { documentationLinks } from 'ui/documentation_links'; +import { CreateIndexPatternWizard } from './create_index_pattern_wizard'; + +uiRoutes.when('/management/kibana/index', { + template: angularTemplate, + controller: function ($scope, $injector) { + // Wait for the directives to execute + $scope.$$postDigest(() => { + const Notifier = $injector.get('Notifier'); + const $routeParams = $injector.get('$routeParams'); + const services = { + config: $injector.get('config'), + es: $injector.get('es'), + indexPatterns: $injector.get('indexPatterns'), + kbnUrl: $injector.get('kbnUrl'), + notify: new Notifier(), + }; + + const initialQuery = $routeParams.id ? decodeURIComponent($routeParams.id) : undefined; + + render( + , + document.getElementById('react') + ); + }); + } +}); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/lib/get_indices.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/lib/get_indices.js new file mode 100644 index 0000000000000..af1387625c4ee --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/lib/get_indices.js @@ -0,0 +1,51 @@ +import { get, sortBy } from 'lodash'; + +export async function getIndices(es, rawPattern, limit) { + const pattern = rawPattern.trim(); + + // Searching for `*:` fails for CCS environments. The search request + // is worthless anyways as the we should only send a request + // for a specific query (where we do not append *) if there is at + // least a single character being searched for. + if (pattern === '*:') { + return []; + } + + const params = { + index: pattern, + ignore: [404], + body: { + size: 0, // no hits + aggs: { + indices: { + terms: { + field: '_index', + size: limit, + } + } + } + } + }; + + try { + const response = await es.search(params); + if (!response || response.error || !response.aggregations) { + return []; + } + + return sortBy(response.aggregations.indices.buckets.map(bucket => { + return { + name: bucket.key + }; + }), 'name'); + } + catch (err) { + const type = get(err, 'body.error.caused_by.type'); + if (type === 'index_not_found_exception') { + // This happens in a CSS environment when the controlling node returns a 500 even though the data + // nodes returned a 404. Remove this when/if this is handled: https://github.com/elastic/elasticsearch/issues/27461 + return []; + } + throw err; + } +} diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/index.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/index.js deleted file mode 100644 index 5571f47154ed6..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/index.js +++ /dev/null @@ -1 +0,0 @@ -import './matching_indices_list'; diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/matching_indices_list.html b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/matching_indices_list.html deleted file mode 100644 index 4f54312e919b3..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/matching_indices_list.html +++ /dev/null @@ -1,112 +0,0 @@ -
-
-

- Looking for matching indices -

-
-

- Just a sec... -

-
- -
- -
-
-

- - - (representative sample only) - -

-
-
-
- - - -
-
-
- -
- - - - - - - - -
- -
-
diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/matching_indices_list.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/matching_indices_list.js deleted file mode 100644 index 25e073006b86f..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/matching_indices_list.js +++ /dev/null @@ -1,63 +0,0 @@ -import 'ui/pager_control'; -import 'ui/pager'; -import { last } from 'lodash'; -import { uiModules } from 'ui/modules'; -import { callAfterBindingsWorkaround } from 'ui/compat'; -import './matching_indices_list.less'; -import template from './matching_indices_list.html'; - -const module = uiModules.get('apps/management'); - -module.directive('matchingIndicesList', function ($filter, pagerFactory) { - return { - restrict: 'E', - replace: true, - template, - transclude: true, - controllerAs: 'matchingIndicesList', - bindToController: true, - scope: { - indices: '=', - pattern: '=', - isLoading: '=', - }, - link: function (scope) { - scope.$watch('matchingIndicesList.indices', () => { - scope.matchingIndicesList.calculateItemsOnPage(); - }); - scope.$watch('matchingIndicesList.pattern', () => { - if (last(scope.matchingIndicesList.pattern) === '*') { - const end = scope.matchingIndicesList.pattern.length - 1; - scope.matchingIndicesList.formattedPattern = scope.matchingIndicesList.pattern.substring(0, end); - } else { - scope.matchingIndicesList.formattedPattern = scope.matchingIndicesList.pattern; - } - }); - }, - controller: callAfterBindingsWorkaround(function () { - this.pageOfIndices = []; - - this.calculateItemsOnPage = () => { - const limitTo = $filter('limitTo'); - this.pager.setTotalItems(this.indices.length); - this.pageOfIndices = limitTo(this.indices, this.pager.pageSize, this.pager.startIndex); - }; - - this.pager = pagerFactory.create(this.indices.length, 10, 1); - - this.hasMultiplePages = () => { - return this.indices.length > this.pager.pageSize; - }; - - this.onPageNext = () => { - this.pager.nextPage(); - this.calculateItemsOnPage(); - }; - - this.onPagePrevious = () => { - this.pager.previousPage(); - this.calculateItemsOnPage(); - }; - }), - }; -}); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/matching_indices_list.less b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/matching_indices_list.less deleted file mode 100644 index 598a153ca5055..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/matching_indices_list/matching_indices_list.less +++ /dev/null @@ -1,3 +0,0 @@ -.matchingIndicesListLoadingPrompt { - min-height: 60px; -} diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/send_create_index_pattern_request.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/send_create_index_pattern_request.js deleted file mode 100644 index 7e62ba6a15251..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/send_create_index_pattern_request.js +++ /dev/null @@ -1,18 +0,0 @@ -export function sendCreateIndexPatternRequest(indexPatterns, { - id, - name, - timeFieldName, -}) { - // get an empty indexPattern to start - return indexPatterns.get() - .then(indexPattern => { - Object.assign(indexPattern, { - id, - title: name, - timeFieldName, - }); - - // fetch the fields - return indexPattern.create(); - }); -} diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/append_wildcard.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/append_wildcard.js deleted file mode 100644 index 146e7f6e6bb07..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/append_wildcard.js +++ /dev/null @@ -1,29 +0,0 @@ -import { uiModules } from 'ui/modules'; -import { appendWildcard } from './lib/append_wildcard'; - -const module = uiModules.get('apps/management'); - -/** - * This directive automatically appends a wildcard to the input field - * after the user starts typing. It lets the user delete the wildcard - * if necessary. If the value of the input field is set back to an empty - * string, the wildcard is immediately re-appended after the user starts - * typing. This is intended to be a UX improvement for the index pattern - * creation page. See https://github.com/elastic/kibana/pull/13454 - */ -module.directive('appendWildcard', function () { - return { - require: 'ngModel', - link: function ($scope, $elem, $attrs, $ctrl) { - $elem.on('keydown', (e) => { - const newIndexPattern = appendWildcard(e, $elem.val()); - if (newIndexPattern) { - e.preventDefault(); - $elem.val(newIndexPattern); - $elem[0].setSelectionRange(1, 1); - $ctrl.$setViewValue(newIndexPattern); - } - }); - } - }; -}); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/index.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/index.js deleted file mode 100644 index 90b9da92c0559..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/index.js +++ /dev/null @@ -1 +0,0 @@ -import './step_index_pattern'; diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/lib/__tests__/append_wildcard.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/lib/__tests__/append_wildcard.js deleted file mode 100644 index 39dbf88da5015..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/lib/__tests__/append_wildcard.js +++ /dev/null @@ -1,40 +0,0 @@ -import expect from 'expect.js'; - -import { appendWildcard } from '../append_wildcard'; - -describe('append_wildcard', function () { - it('should add a wildcard for an alphabet input', () => { - [ - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', - 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', - 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' - ].forEach(char => { - expect(appendWildcard({ key: char }, '')).to.be(`${char}*`); - expect(appendWildcard({ key: char.toUpperCase() }, '')).to.be(`${char.toUpperCase()}*`); - }); - }); - - it('should add a wildcard for a number input', () => { - ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].forEach(num => { - expect(appendWildcard({ key: num }, '')).to.be(`${num}*`); - }); - }); - - it('should NOT add a wildcard for a non alphanumeric input', () => { - ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+'].forEach(char => { - expect(appendWildcard({ key: char }, '')).to.be(undefined); - }); - }); - - it('should NOT add a wildcard for multi-length input', () => { - expect(appendWildcard({ key: 'Tab' }, '')).to.be(undefined); - }); - - it('should NOT add a wildcard if the value is longer than 1 character', () => { - expect(appendWildcard({ key: 'a' }, 'b')).to.be(undefined); - }); - - it('should NOT add a wildcard if the input is a wildcard', () => { - expect(appendWildcard({ key: '*' }, '')).to.be(undefined); - }); -}); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/lib/append_wildcard.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/lib/append_wildcard.js deleted file mode 100644 index 8003e59920116..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/lib/append_wildcard.js +++ /dev/null @@ -1,35 +0,0 @@ -export const appendWildcard = (keyboardEvent, value) => { - const { - key: keyPressed, - metaKey, - ctrlKey, - altKey, - } = keyboardEvent; - - // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode - // is not recommended so we need to rely on `key` but browser support - // is still spotty (https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) - // so just bail if it's not supported - if (!keyPressed) { - return; - } - - // If the user is holding down ctrl/cmd, they are performing some shortcut - // and do not interpret literally - if (metaKey || ctrlKey || altKey) { - return; - } - - // If it's not a letter, number or is something longer, reject it - if (!/[a-z0-9]/i.test(keyPressed) || keyPressed.length !== 1) { - return; - } - - let newValue = value + keyPressed; - if (newValue.length !== 1 || newValue === '*') { - return; - } - - newValue += '*'; - return newValue; -}; diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/step_index_pattern.html b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/step_index_pattern.html deleted file mode 100644 index ac58e35d055c6..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/step_index_pattern.html +++ /dev/null @@ -1,165 +0,0 @@ -
-

- Step 1 of 2: Define index pattern -

- -
- -
-
-
-
- -
- - -
-
-

- You can use a * as a wildcard in your index pattern. -

-
-

- You can't use empty spaces or the characters \ / ? " < > |. -

-
-
-
-
- - -
-
-
- -
- - -
-
- - - - - - You've entered an invalid index pattern. Please adjust it to match any of your {{stepIndexPattern.allIndices.length}} indices, below. - - - -
-
- - - You only have a single index. You can create an index pattern to match it. - - - - Your index pattern can match any of your {{stepIndexPattern.allIndices.length}} indices, below. - - -
-
- - - The index pattern you've entered doesn't match any indices. You can match any of your {{stepIndexPattern.allIndices.length}} indices, below. - - -
-
- - - Your index pattern doesn't match any indices, but you have {{stepIndexPattern.partialMatchingIndices.length}} {{stepIndexPattern.partialMatchingIndices.length > 1 ? 'indices' : 'index'}} which {{stepIndexPattern.partialMatchingIndices.length > 1 ? 'look' : 'looks'}} similar. - - -
-
- - - - - - Success! Your index pattern matches {{stepIndexPattern.matchingIndices.length}} {{stepIndexPattern.matchingIndices.length > 1 ? 'indices' : 'index'}}. - - - -
-
-
diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/step_index_pattern.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/step_index_pattern.js deleted file mode 100644 index 77775c7864036..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/step_index_pattern.js +++ /dev/null @@ -1,94 +0,0 @@ -import { uiModules } from 'ui/modules'; -import './step_index_pattern.less'; -import template from './step_index_pattern.html'; -import './append_wildcard'; - -const module = uiModules.get('apps/management'); - -module.directive('stepIndexPattern', function () { - return { - restrict: 'E', - template, - replace: true, - controllerAs: 'stepIndexPattern', - bindToController: true, - scope: { - fetchExistingIndices: '&', - isFetchingExistingIndices: '=', - fetchMatchingIndices: '&', - isFetchingMatchingIndices: '=', - hasIndices: '&', - indexPatternName: '=', - allIndices: '=', - partialMatchingIndices: '=', - matchingIndices: '=', - goToNextStep: '&', - }, - link: function (scope) { - scope.$watch('stepIndexPattern.allIndices', scope.stepIndexPattern.updateList); - scope.$watch('stepIndexPattern.matchingIndices', scope.stepIndexPattern.updateList); - scope.$watch('stepIndexPattern.indexPatternName', () => { - // Only send the request if there's valid input. - if (scope.stepIndexPattern.indexPatternNameForm && scope.stepIndexPattern.indexPatternNameForm.$valid) { - scope.stepIndexPattern.fetchMatchingIndices(); - } - - // If the index pattern name is invalid, we should reflect that state in the list. - scope.stepIndexPattern.updateList(); - }); - scope.$watchCollection('stepIndexPattern.indexPatternNameForm.$error', () => { - // If we immediately replace the input with an invalid string, then only the form state - // changes, but not the `indexPatternName` value, so we need to watch both. - scope.stepIndexPattern.updateList(); - }); - }, - controller: function () { - this.matchingIndicesListType = 'noMatches'; - this.canGoToNextStep = () => ( - !this.isFetchingMatchingIndices - && !this.indexPatternNameForm.$invalid - && this.hasExactMatches() - ); - - const hasInvalidIndexPattern = () => ( - this.indexPatternNameForm - && !this.indexPatternNameForm.$error.required - && this.indexPatternNameForm.$error.indexPattern - ); - - const hasNoInput = () => ( - !this.indexPatternName - || !this.indexPatternName.trim() - ); - - this.hasExactMatches = () => ( - this.matchingIndices.length - ); - - const hasPartialMatches = () => ( - !this.matchingIndices.length - && this.partialMatchingIndices.length - ); - - this.updateList = () => { - if (hasInvalidIndexPattern()) { - return this.matchingIndicesListType = 'invalidIndexPattern'; - } - - if (hasNoInput()) { - return this.matchingIndicesListType = 'noInput'; - } - - if (this.hasExactMatches()) { - return this.matchingIndicesListType = 'exactMatches'; - } - - if (hasPartialMatches()) { - return this.matchingIndicesListType = 'partialMatches'; - } - - this.matchingIndicesListType = 'noMatches'; - }; - }, - }; -}); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/step_index_pattern.less b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/step_index_pattern.less deleted file mode 100644 index dd37653fc6aeb..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_index_pattern/step_index_pattern.less +++ /dev/null @@ -1,3 +0,0 @@ -.createIndexPatternInputField.ng-untouched { - box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.08), inset -400px 0 0 0 #fbfbfb; -} diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/index.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/index.js deleted file mode 100644 index 02994a505bd11..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/index.js +++ /dev/null @@ -1 +0,0 @@ -import './step_time_field'; diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/step_time_field.html b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/step_time_field.html deleted file mode 100644 index 231dbb28f06a9..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/step_time_field.html +++ /dev/null @@ -1,212 +0,0 @@ -
-

- Step 2 of 2: Configure settings -

- -
- -

- You've defined {{stepTimeField.indexPatternName}} as your index pattern. Now you can specify some settings before we create it. -

- -
- -
-
-
-
- -
- - -
-
- -
- - - - - - - - - - - -

- The indices which match this index pattern don't contain any time fields. -

-
- -
- The Time Filter will use this field to filter your data by time. -
- -
- You can choose not to have a time field, but you will not be able to narrow down your data by a time range. -
-
- - - - -
-
-
- -
-
- -
-
- - Kibana will provide a unique identifier for each index pattern. - If you do not want to use this unique ID, enter a custom one. - -
-
- -
- - -
-
- -
-
- -
-
-
diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/step_time_field.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/step_time_field.js deleted file mode 100644 index 89f324388680d..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/step_time_field.js +++ /dev/null @@ -1,69 +0,0 @@ -import 'ui/toggle_panel'; -import { uiModules } from 'ui/modules'; -import { callAfterBindingsWorkaround } from 'ui/compat'; -import './step_time_field.less'; -import template from './step_time_field.html'; - -const module = uiModules.get('apps/management'); - -module.directive('stepTimeField', function () { - return { - restrict: 'E', - template, - replace: true, - controllerAs: 'stepTimeField', - bindToController: true, - scope: { - indexPatternId: '=', - indexPatternName: '=', - timeFieldOptions: '=', - selectedTimeFieldOption: '=', - fetchTimeFieldOptions: '&', - isFetchingTimeFieldOptions: '=', - goToPreviousStep: '&', - createIndexPattern: '&', - }, - controller: callAfterBindingsWorkaround(function () { - this.isTimeFieldSelectDisabled = () => ( - this.isFetchingTimeFieldOptions - || this.timeFieldOptionsError - ); - - this.isFormValid = () => ( - this.form.$valid - ); - - this.hasTimeFieldOptions = () => ( - this.timeFieldOptions.length > 1 - ); - - this.canCreateIndexPattern = () => ( - !this.timeFieldOptionsError - && !this.isFetchingTimeFieldOptions - && this.isFormValid() - ); - - this.canShowMainSelect = () => ( - !this.isFetchingTimeFieldOptions && this.hasTimeFieldOptions() - ); - - this.canShowLoadingSelect = () => ( - this.isFetchingTimeFieldOptions - ); - - this.canShowNoTimeBasedFieldsMessage = () => ( - !this.isFetchingTimeFieldOptions && !this.hasTimeFieldOptions() - ); - - this.canShowHelpText = () => ( - this.isFetchingTimeFieldOptions || this.hasTimeFieldOptions() - ); - - this.toggleAdvancedOptions = () => { - this.showAdvancedOptions = !this.showAdvancedOptions; - }; - - this.showAdvancedOptions = !!this.indexPatternId; - }), - }; -}); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/step_time_field.less b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/step_time_field.less deleted file mode 100644 index fce886eeb4715..0000000000000 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/step_time_field/step_time_field.less +++ /dev/null @@ -1,16 +0,0 @@ -/** - * 1. Match select width. - */ -.timeFieldNameLabel { - width: 400px; /* 1 */ - display: flex; - align-items: center; - justify-content: space-between; -} - -/** - * 1. Bring the line-height down or else this link expands its container when it becomes visible. - */ - .timeFieldRefreshButton { - line-height: 1 !important; /* 1 */ -}