diff --git a/src/core_plugins/kibana/mappings.json b/src/core_plugins/kibana/mappings.json index 2ccdd5cd8a36f..155742b15c8a7 100644 --- a/src/core_plugins/kibana/mappings.json +++ b/src/core_plugins/kibana/mappings.json @@ -21,6 +21,12 @@ }, "title": { "type": "text" + }, + "type": { + "type": "keyword" + }, + "typeMeta": { + "type": "keyword" } } }, diff --git a/src/core_plugins/kibana/public/discover/controllers/discover.js b/src/core_plugins/kibana/public/discover/controllers/discover.js index e6b6947d07a94..57b40182c70a3 100644 --- a/src/core_plugins/kibana/public/discover/controllers/discover.js +++ b/src/core_plugins/kibana/public/discover/controllers/discover.js @@ -278,11 +278,17 @@ function discoverController( .setField('highlightAll', true) .setField('version', true); + // Even when searching rollups, we want to use the default strategy so that we get back a + // document-like response. + $scope.searchSource.setPreferredSearchStrategyId('default'); + // searchSource which applies time range const timeRangeSearchSource = savedSearch.searchSource.create(); - timeRangeSearchSource.setField('filter', () => { - return timefilter.createFilter($scope.indexPattern); - }); + if(isDefaultTypeIndexPattern($scope.indexPattern)) { + timeRangeSearchSource.setField('filter', () => { + return timefilter.createFilter($scope.indexPattern); + }); + } $scope.searchSource.setParent(timeRangeSearchSource); @@ -393,7 +399,7 @@ function discoverController( $scope.opts = { // number of records to fetch, then paginate through sampleSize: config.get('discover:sampleSize'), - timefield: $scope.indexPattern.timeFieldName, + timefield: isDefaultTypeIndexPattern($scope.indexPattern) && $scope.indexPattern.timeFieldName, savedSearch: savedSearch, indexPatternList: $route.current.locals.ip.list, }; diff --git a/src/core_plugins/kibana/public/kibana.js b/src/core_plugins/kibana/public/kibana.js index 7daafbf6411a9..ed88791241d13 100644 --- a/src/core_plugins/kibana/public/kibana.js +++ b/src/core_plugins/kibana/public/kibana.js @@ -37,6 +37,7 @@ import 'uiExports/fieldFormatEditors'; import 'uiExports/navbarExtensions'; import 'uiExports/contextMenuActions'; import 'uiExports/managementSections'; +import 'uiExports/indexManagement'; import 'uiExports/devTools'; import 'uiExports/docViews'; import 'uiExports/embeddableFactories'; diff --git a/src/core_plugins/kibana/public/management/index.scss b/src/core_plugins/kibana/public/management/index.scss index 4ae0f0ac7474d..db0e0162832e2 100644 --- a/src/core_plugins/kibana/public/management/index.scss +++ b/src/core_plugins/kibana/public/management/index.scss @@ -9,6 +9,7 @@ @import 'hacks'; -// Core +// Core @import 'management_app'; -@import 'sections/settings/advanced_settings'; \ No newline at end of file +@import 'sections/settings/advanced_settings'; +@import 'sections/indices/index'; diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/__tests__/__snapshots__/create_index_pattern_wizard.test.js.snap b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/__tests__/__snapshots__/create_index_pattern_wizard.test.js.snap index 1b40c3cfd6a4f..3365c6f722304 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/__tests__/__snapshots__/create_index_pattern_wizard.test.js.snap +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/__tests__/__snapshots__/create_index_pattern_wizard.test.js.snap @@ -3,8 +3,10 @@ exports[`CreateIndexPatternWizard defaults to the loading state 1`] = `
@@ -13,8 +15,10 @@ exports[`CreateIndexPatternWizard defaults to the loading state 1`] = ` exports[`CreateIndexPatternWizard renders index pattern step when there are indices 1`] = `
@@ -63,8 +91,10 @@ exports[`CreateIndexPatternWizard renders time field step when step is set to 2 exports[`CreateIndexPatternWizard shows system indices even if there are no other indices if the include system indices is toggled 1`] = `
'default', + getIndexPatternName: () => 'name', + checkIndicesForErrors: () => false, + getShowSystemIndices: () => false, + renderPrompt: () => {}, + getIndexPatternMappings: () => { return {}; } +}; jest.mock('../components/step_index_pattern', () => ({ StepIndexPattern: 'StepIndexPattern' })); jest.mock('../components/step_time_field', () => ({ StepTimeField: 'StepTimeField' })); jest.mock('../components/header', () => ({ Header: 'Header' })); @@ -44,6 +51,7 @@ const services = { config: {}, changeUrl: () => {}, scopeApply: () => {}, + indexPatternCreationType: mockIndexPatternCreationType, }; describe('CreateIndexPatternWizard', () => { @@ -154,6 +162,7 @@ describe('CreateIndexPatternWizard', () => { cache: { clear } }, changeUrl, + indexPatternCreationType: mockIndexPatternCreationType }} /> ); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/__tests__/render.test.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/__tests__/render.test.js index 9ef4a3e38ee9b..7c499401bf2fd 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/__tests__/render.test.js +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/__tests__/render.test.js @@ -52,6 +52,7 @@ describe('CreateIndexPatternWizardRender', () => { savedObjectsClient: {}, config: {}, changeUrl: () => {}, + indexPatternCreationType: {}, } ); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/header/__tests__/__snapshots__/header.test.js.snap b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/header/__tests__/__snapshots__/header.test.js.snap index b580db70a893a..71e6009b2c126 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/header/__tests__/__snapshots__/header.test.js.snap +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/header/__tests__/__snapshots__/header.test.js.snap @@ -10,9 +10,13 @@ exports[`Header should render normally 1`] = ` >

@@ -46,23 +50,6 @@ exports[`Header should render normally 1`] = `

- - - } - onChange={[Function]} - /> -

@@ -116,23 +107,6 @@ exports[`Header should render without including system indices 1`] = `

- - - } - onChange={[Function]} - /> - ( @@ -41,7 +44,10 @@ export const Header = ({

@@ -58,18 +64,30 @@ export const Header = ({

- - } - id="checkboxShowSystemIndices" - checked={isIncludingSystemIndices} - onChange={onChangeIncludingSystemIndices} - /> - + { + showSystemIndices ? ( + + } + id="checkboxShowSystemIndices" + checked={isIncludingSystemIndices} + onChange={onChangeIncludingSystemIndices} + /> + + ) : null + } + { + prompt ? ( + + + {prompt} + + ) : null + }
); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/__tests__/__snapshots__/step_index_pattern.test.js.snap b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/__tests__/__snapshots__/step_index_pattern.test.js.snap index 6e1a64e823e41..0e6091fccbb33 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/__tests__/__snapshots__/step_index_pattern.test.js.snap +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/__tests__/__snapshots__/step_index_pattern.test.js.snap @@ -7,7 +7,7 @@ Object { data-test-subj="createIndexPatternStep1Header" errors={ Array [ - "An index pattern cannot contain spaces or the characters: {characterList}", + "A {indexPatternName} cannot contain spaces or the characters: {characterList}", ] } goToNextStep={[Function]} @@ -19,38 +19,42 @@ Object { "i18n": Array [ Array [ Object { - "defaultMessage": "An index pattern cannot contain spaces or the characters: {characterList}", + "defaultMessage": "A {indexPatternName} cannot contain spaces or the characters: {characterList}", "id": "kbn.management.createIndexPattern.step.invalidCharactersErrorMessage", }, Object { "characterList": "\\\\, /, ?, \\", <, >, |", + "indexPatternName": "name", }, ], Array [ Object { - "defaultMessage": "An index pattern cannot contain spaces or the characters: {characterList}", + "defaultMessage": "A {indexPatternName} cannot contain spaces or the characters: {characterList}", "id": "kbn.management.createIndexPattern.step.invalidCharactersErrorMessage", }, Object { "characterList": "\\\\, /, ?, \\", <, >, |", + "indexPatternName": "name", }, ], Array [ Object { - "defaultMessage": "An index pattern cannot contain spaces or the characters: {characterList}", + "defaultMessage": "A {indexPatternName} cannot contain spaces or the characters: {characterList}", "id": "kbn.management.createIndexPattern.step.invalidCharactersErrorMessage", }, Object { "characterList": "\\\\, /, ?, \\", <, >, |", + "indexPatternName": "name", }, ], Array [ Object { - "defaultMessage": "An index pattern cannot contain spaces or the characters: {characterList}", + "defaultMessage": "A {indexPatternName} cannot contain spaces or the characters: {characterList}", "id": "kbn.management.createIndexPattern.step.invalidCharactersErrorMessage", }, Object { "characterList": "\\\\, /, ?, \\", <, >, |", + "indexPatternName": "name", }, ], ], diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/__tests__/step_index_pattern.test.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/__tests__/step_index_pattern.test.js index 37df9762b54df..fb2b41e859753 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/__tests__/step_index_pattern.test.js +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/__tests__/step_index_pattern.test.js @@ -25,7 +25,12 @@ import { Header } from '../components/header'; jest.mock('../../../lib/ensure_minimum_time', () => ({ ensureMinimumTime: async (promises) => Array.isArray(promises) ? await Promise.all(promises) : await promises })); - +const mockIndexPatternCreationType = { + getIndexPatternType: () => 'default', + getIndexPatternName: () => 'name', + checkIndicesForErrors: () => false, + getShowSystemIndices: () => false +}; // If we don't mock this, Jest fails with the error `TypeError: Cannot redefine property: prototype // at Function.defineProperties`. jest.mock('ui/index_patterns', () => ({ @@ -39,7 +44,7 @@ jest.mock('ui/chrome', () => ({ })); jest.mock('../../../lib/get_indices', () => ({ - getIndices: (service, query) => { + getIndices: (service, indexPatternCreationType, query) => { if (query.startsWith('e')) { return [ { name: 'es' }, @@ -67,6 +72,7 @@ const createComponent = props => { esService={esService} savedObjectsClient={savedObjectsClient} goToNextStep={goToNextStep} + indexPatternCreationType={mockIndexPatternCreationType} {...props} /> ); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__tests__/__snapshots__/indices_list.test.js.snap b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__tests__/__snapshots__/indices_list.test.js.snap index bdacb3b6c4734..342b8a0c531bb 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__tests__/__snapshots__/indices_list.test.js.snap +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__tests__/__snapshots__/indices_list.test.js.snap @@ -15,6 +15,10 @@ exports[`IndicesList should change pages 1`] = ` > kibana + es + @@ -134,6 +142,10 @@ exports[`IndicesList should change per page 1`] = ` > kibana + @@ -258,6 +270,10 @@ exports[`IndicesList should highlight the query in the matches 1`] = ` bana + es + @@ -377,6 +397,10 @@ exports[`IndicesList should render normally 1`] = ` > kibana + es + @@ -496,6 +524,10 @@ exports[`IndicesList updating props should render all new indices 1`] = ` > kibana + es + kibana + es + kibana + es + kibana + es + kibana + es + diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__tests__/indices_list.test.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__tests__/indices_list.test.js index f4dfae32a6a32..b958dbbf58122 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__tests__/indices_list.test.js +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__tests__/indices_list.test.js @@ -22,8 +22,8 @@ import { IndicesList } from '../indices_list'; import { shallow } from 'enzyme'; const indices = [ - { name: 'kibana' }, - { name: 'es' } + { name: 'kibana', tags: [] }, + { name: 'es', tags: [] } ]; describe('IndicesList', () => { diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/indices_list.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/indices_list.js index c8a1f89b18458..df90abce00e48 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/indices_list.js +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/indices_list.js @@ -22,6 +22,7 @@ import PropTypes from 'prop-types'; import { PER_PAGE_INCREMENTS } from '../../../../constants'; import { + EuiBadge, EuiFlexGroup, EuiFlexItem, EuiSpacer, @@ -185,6 +186,13 @@ export class IndicesList extends Component { {this.highlightIndexName(index.name, queryWithoutWildcard)} + + {index.tags.map(tag => { + return ( + {tag.name} + ); + })} + ); }); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/status_message/__tests__/__snapshots__/status_message.test.js.snap b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/status_message/__tests__/__snapshots__/status_message.test.js.snap index 41d1ee57bea20..0cdb384b3af22 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/status_message/__tests__/__snapshots__/status_message.test.js.snap +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/status_message/__tests__/__snapshots__/status_message.test.js.snap @@ -174,8 +174,8 @@ exports[`StatusMessage should show that system indices exist 1`] = ` > diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.js index a403925f24dd1..772d7ec900ec1 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.js +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.js @@ -35,6 +35,7 @@ export const StatusMessage = ({ }, isIncludingSystemIndices, query, + showSystemIndicies, }) => { let statusIcon; let statusMessage; @@ -58,7 +59,7 @@ export const StatusMessage = ({ ); } - else if (!isIncludingSystemIndices) { + else if (!isIncludingSystemIndices && showSystemIndicies) { statusMessage = ( { - const { esService } = this.props; + const { esService, indexPatternCreationType } = this.props; const { existingIndexPatterns } = this.state; if (existingIndexPatterns.includes(query)) { @@ -104,7 +108,7 @@ export class StepIndexPatternComponent extends Component { this.setState({ isLoadingIndices: true, indexPatternExists: false }); if (query.endsWith('*')) { - const exactMatchedIndices = await ensureMinimumTime(getIndices(esService, query, MAX_SEARCH_SIZE)); + const exactMatchedIndices = await ensureMinimumTime(getIndices(esService, indexPatternCreationType, query, MAX_SEARCH_SIZE)); // If the search changed, discard this state if (query !== this.lastQuery) { return; @@ -117,8 +121,8 @@ export class StepIndexPatternComponent extends Component { partialMatchedIndices, exactMatchedIndices, ] = await ensureMinimumTime([ - getIndices(esService, `${query}*`, MAX_SEARCH_SIZE), - getIndices(esService, query, MAX_SEARCH_SIZE), + getIndices(esService, indexPatternCreationType, `${query}*`, MAX_SEARCH_SIZE), + getIndices(esService, indexPatternCreationType, query, MAX_SEARCH_SIZE), ]); // If the search changed, discard this state @@ -167,6 +171,7 @@ export class StepIndexPatternComponent extends Component { } renderStatusMessage(matchedIndices) { + const { indexPatternCreationType } = this.props; const { query, isLoadingIndices, indexPatternExists, isIncludingSystemIndices } = this.state; if (isLoadingIndices || indexPatternExists) { @@ -176,6 +181,7 @@ export class StepIndexPatternComponent extends Component { return ( @@ -230,27 +236,31 @@ export class StepIndexPatternComponent extends Component { } renderHeader({ exactMatchedIndices: indices }) { - const { goToNextStep, intl } = this.props; - const { query, showingIndexPatternQueryErrors, indexPatternExists } = this.state; + const { goToNextStep, indexPatternCreationType, intl } = this.props; + const { query, showingIndexPatternQueryErrors, indexPatternExists, indexPatternName } = this.state; let containsErrors = false; const errors = []; - const characterList = ILLEGAL_CHARACTERS.slice(0, ILLEGAL_CHARACTERS.length - 1).join(', '); + const characterList = this.ILLEGAL_CHARACTERS.slice(0, this.ILLEGAL_CHARACTERS.length - 1).join(', '); + const checkIndices = indexPatternCreationType.checkIndicesForErrors(indices); if (!query || !query.length || query === '.' || query === '..') { // This is an error scenario but do not report an error containsErrors = true; - } - else if (containsIllegalCharacters(query, ILLEGAL_CHARACTERS)) { + } else if (containsIllegalCharacters(query, ILLEGAL_CHARACTERS)) { const errorMessage = intl.formatMessage( { id: 'kbn.management.createIndexPattern.step.invalidCharactersErrorMessage', - defaultMessage: 'An index pattern cannot contain spaces or the characters: {characterList}' + defaultMessage: 'A {indexPatternName} cannot contain spaces or the characters: {characterList}' }, - { characterList }); + { characterList, indexPatternName } + ); errors.push(errorMessage); containsErrors = true; + } else if (checkIndices) { + errors.push(...checkIndices); + containsErrors = true; } const isInputInvalid = showingIndexPatternQueryErrors && containsErrors && errors.length > 0; diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/__tests__/__snapshots__/step_time_field.test.js.snap b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/__tests__/__snapshots__/step_time_field.test.js.snap index 78b941d09c129..0234dfa2d4c6d 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/__tests__/__snapshots__/step_time_field.test.js.snap +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/__tests__/__snapshots__/step_time_field.test.js.snap @@ -63,9 +63,10 @@ exports[`StepTimeField should render a selected timeField 1`] = ` >
({ extractTimeFields: fields => fields, })); +const mockIndexPatternCreationType = { + getIndexPatternType: () => 'default', + getIndexPatternName: () => 'name' +}; const noop = () => {}; const indexPatternsService = { fieldsFetcher: { @@ -45,6 +49,7 @@ describe('StepTimeField', () => { indexPatternsService={indexPatternsService} goToPreviousStep={noop} createIndexPattern={noop} + indexPatternCreationType={mockIndexPatternCreationType} /> ); @@ -58,6 +63,7 @@ describe('StepTimeField', () => { indexPatternsService={indexPatternsService} goToPreviousStep={noop} createIndexPattern={noop} + indexPatternCreationType={mockIndexPatternCreationType} /> ); @@ -78,6 +84,7 @@ describe('StepTimeField', () => { indexPatternsService={indexPatternsService} goToPreviousStep={noop} createIndexPattern={noop} + indexPatternCreationType={mockIndexPatternCreationType} /> ); @@ -100,6 +107,7 @@ describe('StepTimeField', () => { indexPatternsService={indexPatternsService} goToPreviousStep={noop} createIndexPattern={noop} + indexPatternCreationType={mockIndexPatternCreationType} /> ); @@ -128,6 +136,7 @@ describe('StepTimeField', () => { indexPatternsService={indexPatternsService} goToPreviousStep={noop} createIndexPattern={noop} + indexPatternCreationType={mockIndexPatternCreationType} /> ); @@ -151,6 +160,7 @@ describe('StepTimeField', () => { indexPatternsService={indexPatternsService} goToPreviousStep={noop} createIndexPattern={noop} + indexPatternCreationType={mockIndexPatternCreationType} /> ); @@ -174,6 +184,7 @@ describe('StepTimeField', () => { indexPatternsService={indexPatternsService} goToPreviousStep={noop} createIndexPattern={noop} + indexPatternCreationType={mockIndexPatternCreationType} /> ); @@ -189,6 +200,7 @@ describe('StepTimeField', () => { indexPatternsService={indexPatternsService} goToPreviousStep={noop} createIndexPattern={noop} + indexPatternCreationType={mockIndexPatternCreationType} /> ); @@ -207,6 +219,7 @@ describe('StepTimeField', () => { indexPatternsService={indexPatternsService} goToPreviousStep={noop} createIndexPattern={noop} + indexPatternCreationType={mockIndexPatternCreationType} /> ); diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/components/header/__tests__/__snapshots__/header.test.js.snap b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/components/header/__tests__/__snapshots__/header.test.js.snap index 414b83eccb77c..9abe47d4fe04d 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/components/header/__tests__/__snapshots__/header.test.js.snap +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/components/header/__tests__/__snapshots__/header.test.js.snap @@ -21,13 +21,14 @@ exports[`Header should render normally 1`] = ` grow={true} > ki* , + "indexPatternName": undefined, } } /> diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/components/header/header.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/components/header/header.js index 1ccaf90f66484..67e8053eb6bbd 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/components/header/header.js +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/components/header/header.js @@ -29,6 +29,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; export const Header = ({ indexPattern, + indexPatternName, }) => (
@@ -43,8 +44,11 @@ export const Header = ({ {indexPattern} }} + defaultMessage="You've defined {indexPattern} as your {indexPatternName}. Now you can specify some settings before we create it." + values={{ + indexPattern: {indexPattern}, + indexPatternName, + }} />
diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/step_time_field.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/step_time_field.js index b514e571166d1..13353d41e5ad0 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/step_time_field.js +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/components/step_time_field/step_time_field.js @@ -43,11 +43,17 @@ export class StepTimeFieldComponent extends Component { indexPatternsService: PropTypes.object.isRequired, goToPreviousStep: PropTypes.func.isRequired, createIndexPattern: PropTypes.func.isRequired, + indexPatternCreationType: PropTypes.object.isRequired, } constructor(props) { super(props); + const { + getIndexPatternType, + getIndexPatternName, + } = props.indexPatternCreationType; + this.state = { timeFields: [], selectedTimeField: undefined, @@ -56,6 +62,8 @@ export class StepTimeFieldComponent extends Component { isFetchingTimeFields: false, isCreating: false, indexPatternId: '', + indexPatternType: getIndexPatternType(), + indexPatternName: getIndexPatternName(), }; } @@ -65,9 +73,12 @@ export class StepTimeFieldComponent extends Component { fetchTimeFields = async () => { const { indexPatternsService, indexPattern } = this.props; + const { getFetchForWildcardOptions } = this.props.indexPatternCreationType; this.setState({ isFetchingTimeFields: true }); - const fields = await ensureMinimumTime(indexPatternsService.fieldsFetcher.fetchForWildcard(indexPattern)); + const fields = await ensureMinimumTime( + indexPatternsService.fieldsFetcher.fetchForWildcard(indexPattern, getFetchForWildcardOptions()) + ); const timeFields = extractTimeFields(fields); this.setState({ timeFields, isFetchingTimeFields: false }); @@ -113,6 +124,7 @@ export class StepTimeFieldComponent extends Component { indexPatternId, isCreating, isFetchingTimeFields, + indexPatternName, } = this.state; if (isCreating) { @@ -156,8 +168,11 @@ export class StepTimeFieldComponent extends Component { return ( -
- +
+ { this.setState({ allIndices: [], isInitiallyLoadingIndices: true }); const { services } = this.props; - const allIndices = await ensureMinimumTime(getIndices(services.es, `*`, MAX_SEARCH_SIZE)); + const allIndices = await ensureMinimumTime(getIndices(services.es, this.indexPatternCreationType, `*`, MAX_SEARCH_SIZE)); // this.setState({ allIndices, isInitiallyLoadingIndices: false }); } @@ -74,6 +78,7 @@ export class CreateIndexPatternWizard extends Component { id: indexPatternId, title: indexPattern, timeFieldName, + ...this.indexPatternCreationType.getIndexPatternMappings() }); const createdId = await emptyPattern.create(); @@ -105,8 +110,11 @@ export class CreateIndexPatternWizard extends Component { return (
); } @@ -138,6 +146,7 @@ export class CreateIndexPatternWizard extends Component { isIncludingSystemIndices={isIncludingSystemIndices} esService={services.es} savedObjectsClient={services.savedObjectsClient} + indexPatternCreationType={this.indexPatternCreationType} goToNextStep={this.goToTimeFieldStep} /> ); @@ -151,6 +160,7 @@ export class CreateIndexPatternWizard extends Component { indexPatternsService={services.indexPatterns} goToPreviousStep={this.goToIndexPatternStep} createIndexPattern={this.createIndexPattern} + indexPatternCreationType={this.indexPatternCreationType} /> ); } 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 2b5c3987af420..2db685ba85169 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 @@ -21,6 +21,7 @@ import { SavedObjectsClientProvider } from 'ui/saved_objects'; import uiRoutes from 'ui/routes'; import angularTemplate from './angular_template.html'; import 'ui/index_patterns'; +import { IndexPatternCreationFactory } from 'ui/management/index_pattern_creation'; import { renderCreateIndexPatternWizard, destroyCreateIndexPatternWizard } from './render'; @@ -29,13 +30,17 @@ uiRoutes.when('/management/kibana/index', { controller: function ($scope, $injector) { // Wait for the directives to execute const kbnUrl = $injector.get('kbnUrl'); + const Private = $injector.get('Private'); $scope.$$postDigest(() => { const $routeParams = $injector.get('$routeParams'); + const indexPatternCreationProvider = Private(IndexPatternCreationFactory)($routeParams.type); + const indexPatternCreationType = indexPatternCreationProvider.getType(); const services = { config: $injector.get('config'), es: $injector.get('es'), indexPatterns: $injector.get('indexPatterns'), - savedObjectsClient: $injector.get('Private')(SavedObjectsClientProvider), + savedObjectsClient: Private(SavedObjectsClientProvider), + indexPatternCreationType, changeUrl: url => { $scope.$evalAsync(() => kbnUrl.changePath(url)); }, diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/lib/__tests__/get_indices.test.js b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/lib/__tests__/get_indices.test.js index f5dcccf6da50b..502111b457332 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/lib/__tests__/get_indices.test.js +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern_wizard/lib/__tests__/get_indices.test.js @@ -21,6 +21,15 @@ import { getIndices } from '../get_indices'; import successfulResponse from './api/get_indices.success.json'; import errorResponse from './api/get_indices.error.json'; import exceptionResponse from './api/get_indices.exception.json'; +const mockIndexPatternCreationType = { + getIndexPatternType: () => 'default', + getIndexPatternName: () => 'name', + checkIndicesForErrors: () => false, + getShowSystemIndices: () => false, + renderPrompt: () => {}, + getIndexPatternMappings: () => { return {}; }, + getIndexTags: () => { return []; } +}; describe('getIndices', () => { it('should work in a basic case', async () => { @@ -28,20 +37,20 @@ describe('getIndices', () => { search: () => new Promise((resolve) => resolve(successfulResponse)) }; - const result = await getIndices(es, 'kibana', 1); + const result = await getIndices(es, mockIndexPatternCreationType, 'kibana', 1); expect(result.length).toBe(2); expect(result[0].name).toBe('1'); expect(result[1].name).toBe('2'); }); it('should ignore ccs query-all', async () => { - expect((await getIndices(null, '*:')).length).toBe(0); + expect((await getIndices(null, mockIndexPatternCreationType, '*:')).length).toBe(0); }); it('should ignore a single comma', async () => { - expect((await getIndices(null, ',')).length).toBe(0); - expect((await getIndices(null, ',*')).length).toBe(0); - expect((await getIndices(null, ',foobar')).length).toBe(0); + expect((await getIndices(null, mockIndexPatternCreationType, ',')).length).toBe(0); + expect((await getIndices(null, mockIndexPatternCreationType, ',*')).length).toBe(0); + expect((await getIndices(null, mockIndexPatternCreationType, ',foobar')).length).toBe(0); }); it('should trim the input', async () => { @@ -52,7 +61,7 @@ describe('getIndices', () => { }), }; - await getIndices(es, 'kibana ', 1); + await getIndices(es, mockIndexPatternCreationType, 'kibana ', 1); expect(index).toBe('kibana'); }); @@ -64,7 +73,7 @@ describe('getIndices', () => { }), }; - await getIndices(es, 'kibana', 10); + await getIndices(es, mockIndexPatternCreationType, 'kibana', 10); expect(limit).toBe(10); }); @@ -74,7 +83,7 @@ describe('getIndices', () => { search: () => new Promise((resolve) => resolve(errorResponse)) }; - const result = await getIndices(es, 'kibana', 1); + const result = await getIndices(es, mockIndexPatternCreationType, 'kibana', 1); expect(result.length).toBe(0); }); @@ -83,7 +92,7 @@ describe('getIndices', () => { search: () => { throw new Error('Fail'); } }; - await expect(getIndices(es, 'kibana', 1)).rejects.toThrow(); + await expect(getIndices(es, mockIndexPatternCreationType, 'kibana', 1)).rejects.toThrow(); }); it('should handle index_not_found_exception errors gracefully', async () => { @@ -91,12 +100,12 @@ describe('getIndices', () => { search: () => new Promise((resolve, reject) => reject(exceptionResponse)) }; - const result = await getIndices(es, 'kibana', 1); + const result = await getIndices(es, mockIndexPatternCreationType, 'kibana', 1); expect(result.length).toBe(0); }); it('should throw an exception if no limit is provided', async () => { - await expect(getIndices({}, 'kibana')).rejects.toThrow(); + await expect(getIndices({}, mockIndexPatternCreationType, 'kibana')).rejects.toThrow(); }); }); }); 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 index 7638daf1c5720..099f07a698cbf 100644 --- 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 @@ -19,7 +19,7 @@ import { get, sortBy } from 'lodash'; -export async function getIndices(es, rawPattern, limit) { +export async function getIndices(es, indexPatternCreationType, rawPattern, limit) { const pattern = rawPattern.trim(); // Searching for `*:` fails for CCS environments. The search request @@ -57,7 +57,7 @@ export async function getIndices(es, rawPattern, limit) { size: limit, } } - } + }, } }; @@ -67,11 +67,18 @@ export async function getIndices(es, rawPattern, limit) { return []; } - return sortBy(response.aggregations.indices.buckets.map(bucket => { - return { - name: bucket.key - }; - }), 'name'); + return sortBy( + response.aggregations.indices.buckets.map(bucket => { + return bucket.key; + }) + .map((indexName) => { + return { + name: indexName, + tags: indexPatternCreationType.getIndexTags(indexName) + }; + }) + , 'name' + ); } catch (err) { const type = get(err, 'body.error.caused_by.type'); diff --git a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_index_pattern.html b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_index_pattern.html index 9e8d982090177..9b42d52159206 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_index_pattern.html +++ b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_index_pattern.html @@ -15,15 +15,22 @@ delete="removePattern()" > -

- - - +

+ + + + + +   + + + {{tag.name}}

+

, @@ -184,11 +186,14 @@ uiModules.get('apps/management') $scope, $location, $route, config, indexPatterns, Private, AppState, docTitle, confirmModal) { const $state = $scope.state = new AppState(); const { fieldWildcardMatcher } = Private(FieldWildcardProvider); + const indexPatternListProvider = Private(IndexPatternListFactory)(); $scope.fieldWildcardMatcher = fieldWildcardMatcher; $scope.editSectionsProvider = Private(IndicesEditSectionsProvider); $scope.kbnUrl = Private(KbnUrlProvider); $scope.indexPattern = $route.current.locals.indexPattern; + $scope.indexPattern.tags = indexPatternListProvider.getIndexPatternTags($scope.indexPattern); + $scope.getFieldInfo = indexPatternListProvider.getFieldInfo; docTitle.change($scope.indexPattern.title); const otherPatterns = _.filter($route.current.locals.indexPatterns, pattern => { @@ -196,7 +201,7 @@ uiModules.get('apps/management') }); $scope.$watch('indexPattern.fields', function () { - $scope.editSections = $scope.editSectionsProvider($scope.indexPattern); + $scope.editSections = $scope.editSectionsProvider($scope.indexPattern, indexPatternListProvider); $scope.refreshFilters(); $scope.fields = $scope.indexPattern.getNonScriptedFields(); updateIndexedFieldsTable($scope, $state); diff --git a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_sections.js b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_sections.js index 20a8e49c7eee2..c7f53096bfa6e 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_sections.js +++ b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_sections.js @@ -22,7 +22,7 @@ import { i18n } from '@kbn/i18n'; export function IndicesEditSectionsProvider() { - return function (indexPattern) { + return function (indexPattern, indexPatternListProvider) { const fieldCount = _.countBy(indexPattern.fields, function (field) { return (field.scripted) ? 'scripted' : 'indexed'; }); @@ -33,22 +33,28 @@ export function IndicesEditSectionsProvider() { sourceFilters: indexPattern.sourceFilters ? indexPattern.sourceFilters.length : 0, }); - return [ - { - title: i18n.translate('kbn.management.editIndexPattern.tabs.fieldsHeader', { defaultMessage: 'Fields' }), - index: 'indexedFields', - count: fieldCount.indexed - }, - { + const editSections = []; + + editSections.push({ + title: i18n.translate('kbn.management.editIndexPattern.tabs.fieldsHeader', { defaultMessage: 'Fields' }), + index: 'indexedFields', + count: fieldCount.indexed + }); + + if(indexPatternListProvider.areScriptedFieldsEnabled(indexPattern)) { + editSections.push({ title: i18n.translate('kbn.management.editIndexPattern.tabs.scriptedHeader', { defaultMessage: 'Scripted fields' }), index: 'scriptedFields', count: fieldCount.scripted - }, - { - title: i18n.translate('kbn.management.editIndexPattern.tabs.sourceHeader', { defaultMessage: 'Source filters' }), - index: 'sourceFilters', - count: fieldCount.sourceFilters - } - ]; + }); + } + + editSections.push({ + title: i18n.translate('kbn.management.editIndexPattern.tabs.sourceHeader', { defaultMessage: 'Source filters' }), + index: 'sourceFilters', + count: fieldCount.sourceFilters + }); + + return editSections; }; } diff --git a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/__tests__/__snapshots__/indexed_fields_table.test.js.snap b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/__tests__/__snapshots__/indexed_fields_table.test.js.snap index 45f8b04cbf712..277ad1248ff3e 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/__tests__/__snapshots__/indexed_fields_table.test.js.snap +++ b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/__tests__/__snapshots__/indexed_fields_table.test.js.snap @@ -17,6 +17,7 @@ exports[`IndexedFieldsTable should filter based on the query bar 1`] = ` "excluded": false, "format": undefined, "indexPattern": undefined, + "info": undefined, "name": "Elastic", "routes": undefined, "searchable": true, @@ -45,6 +46,7 @@ exports[`IndexedFieldsTable should filter based on the type filter 1`] = ` "excluded": false, "format": undefined, "indexPattern": undefined, + "info": undefined, "name": "timestamp", "routes": undefined, "type": "date", @@ -73,6 +75,7 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "excluded": false, "format": undefined, "indexPattern": undefined, + "info": undefined, "name": "Elastic", "routes": undefined, "searchable": true, @@ -82,6 +85,7 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "excluded": false, "format": undefined, "indexPattern": undefined, + "info": undefined, "name": "timestamp", "routes": undefined, "type": "date", @@ -91,6 +95,7 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "excluded": false, "format": undefined, "indexPattern": undefined, + "info": undefined, "name": "conflictingField", "routes": undefined, "type": "conflict", diff --git a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/__tests__/__snapshots__/table.test.js.snap b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/__tests__/__snapshots__/table.test.js.snap index d000633a2caad..0ff7cbe0d6d0b 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/__tests__/__snapshots__/table.test.js.snap +++ b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/__tests__/__snapshots__/table.test.js.snap @@ -97,16 +97,19 @@ exports[`Table should render normally 1`] = ` Array [ Object { "displayName": "Elastic", + "info": Object {}, "name": "Elastic", "searchable": true, }, Object { "displayName": "timestamp", + "info": Object {}, "name": "timestamp", "type": "date", }, Object { "displayName": "conflictingField", + "info": Object {}, "name": "conflictingField", "type": "conflict", }, diff --git a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/__tests__/table.test.js b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/__tests__/table.test.js index 752d99267e330..c538bb5f24085 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/__tests__/table.test.js +++ b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/__tests__/table.test.js @@ -28,9 +28,9 @@ const indexPattern = { }; const items = [ - { name: 'Elastic', displayName: 'Elastic', searchable: true }, - { name: 'timestamp', displayName: 'timestamp', type: 'date' }, - { name: 'conflictingField', displayName: 'conflictingField', type: 'conflict' }, + { name: 'Elastic', displayName: 'Elastic', searchable: true, info: {} }, + { name: 'timestamp', displayName: 'timestamp', type: 'date', info: {} }, + { name: 'conflictingField', displayName: 'conflictingField', type: 'conflict', info: {} }, ]; describe('Table', () => { @@ -55,7 +55,7 @@ describe('Table', () => { /> ); - const tableCell = shallow(component.prop('columns')[0].render('Elastic')); + const tableCell = shallow(component.prop('columns')[0].render('Elastic', items[0])); expect(tableCell).toMatchSnapshot(); }); @@ -68,7 +68,7 @@ describe('Table', () => { /> ); - const tableCell = shallow(component.prop('columns')[0].render('timestamp', true)); + const tableCell = shallow(component.prop('columns')[0].render('timestamp', items[1])); expect(tableCell).toMatchSnapshot(); }); @@ -94,7 +94,7 @@ describe('Table', () => { /> ); - const tableCell = shallow(component.prop('columns')[3].render(false)); + const tableCell = shallow(component.prop('columns')[3].render(false, items[2])); expect(tableCell).toMatchSnapshot(); }); diff --git a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/table.js b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/table.js index 628e42e9e9653..71c648d77a43e 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/table.js +++ b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/components/table/table.js @@ -39,13 +39,19 @@ export class TableComponent extends PureComponent { return value ? : ; } - renderFieldName(name, isTimeField) { + renderFieldName(name, field) { + const { indexPattern } = this.props; const { intl } = this.props; - const label = intl.formatMessage({ - id: 'kbn.management.editIndexPattern.fields.table.primaryTimeAria', + + const infoLabel = intl.formatMessage({ + id: 'kbn.management.editIndexPattern.fields.table.additionalInfoAriaLabel', + defaultMessage: 'Additional field information' + }); + const timeLabel = intl.formatMessage({ + id: 'kbn.management.editIndexPattern.fields.table.primaryTimeAriaLabel', defaultMessage: 'Primary time field' }); - const content = intl.formatMessage({ + const timeContent = intl.formatMessage({ id: 'kbn.management.editIndexPattern.fields.table.primaryTimeTooltip', defaultMessage: 'This field represents the time that events occurred.' }); @@ -53,17 +59,28 @@ export class TableComponent extends PureComponent { return ( {name} - {isTimeField ? ( + {field.info && field.info.length ? ( + +   +

{info}
)} + /> + + ) : null} + {indexPattern.timeFieldName === name ? (   - ) : ''} + ) : null} ); } @@ -98,7 +115,7 @@ export class TableComponent extends PureComponent { } render() { - const { indexPattern, items, editField, intl } = this.props; + const { items, editField, intl } = this.props; const pagination = { initialPageSize: 10, @@ -111,8 +128,8 @@ export class TableComponent extends PureComponent { name: intl.formatMessage({ id: 'kbn.management.editIndexPattern.fields.table.nameHeader', defaultMessage: 'Name' }), dataType: 'string', sortable: true, - render: (value) => { - return this.renderFieldName(value, indexPattern.timeFieldName === value); + render: (value, field) => { + return this.renderFieldName(value, field); }, width: '38%', 'data-test-subj': 'indexedFieldName', diff --git a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/indexed_fields_table.js b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/indexed_fields_table.js index 646abf6798756..607e7fa66242c 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/indexed_fields_table.js +++ b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/indexed_fields_table/indexed_fields_table.js @@ -36,6 +36,7 @@ export class IndexedFieldsTable extends Component { indexedFieldTypeFilter: PropTypes.string, helpers: PropTypes.shape({ redirectToRoute: PropTypes.func.isRequired, + getFieldInfo: PropTypes.func, }), fieldWildcardMatcher: PropTypes.func.isRequired, } @@ -57,7 +58,7 @@ export class IndexedFieldsTable extends Component { } mapFields(fields) { - const { indexPattern, fieldWildcardMatcher } = this.props; + const { indexPattern, fieldWildcardMatcher, helpers } = this.props; const sourceFilters = indexPattern.sourceFilters && indexPattern.sourceFilters.map(f => f.value); const fieldWildcardMatch = fieldWildcardMatcher(sourceFilters || []); @@ -70,6 +71,7 @@ export class IndexedFieldsTable extends Component { indexPattern: field.indexPattern, format: getFieldFormat(indexPattern, field.name), excluded: fieldWildcardMatch ? fieldWildcardMatch(field.name) : false, + info: helpers.getFieldInfo && helpers.getFieldInfo(indexPattern, field.name), }; }) || []; } diff --git a/src/core_plugins/kibana/public/management/sections/indices/index.html b/src/core_plugins/kibana/public/management/sections/indices/index.html index 26dee3efa77b8..1c2c5faa6aea8 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/index.html +++ b/src/core_plugins/kibana/public/management/sections/indices/index.html @@ -1,52 +1,7 @@
diff --git a/src/core_plugins/kibana/public/management/sections/indices/index.js b/src/core_plugins/kibana/public/management/sections/indices/index.js index 69416c56e5c39..fbe715c6f0f07 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/index.js +++ b/src/core_plugins/kibana/public/management/sections/indices/index.js @@ -18,6 +18,8 @@ */ import { management } from 'ui/management'; +import { IndexPatternListFactory } from 'ui/management/index_pattern_list'; +import { IndexPatternCreationFactory } from 'ui/management/index_pattern_creation'; import './create_index_pattern_wizard'; import './edit_index_pattern'; import uiRoutes from 'ui/routes'; @@ -27,13 +29,45 @@ import { SavedObjectsClientProvider } from 'ui/saved_objects'; import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { IndexPatternList } from './index_pattern_list'; + +const INDEX_PATTERN_LIST_DOM_ELEMENT_ID = 'indexPatternListReact'; + +export function updateIndexPatternList( + $scope, + indexPatternCreationOptions, + defaultIndex, + indexPatterns, +) { + const node = document.getElementById(INDEX_PATTERN_LIST_DOM_ELEMENT_ID); + if (!node) { + return; + } + + render( + , + node, + ); +} + +export const destroyIndexPatternList = () => { + const node = document.getElementById(INDEX_PATTERN_LIST_DOM_ELEMENT_ID); + node && unmountComponentAtNode(node); +}; + const indexPatternsResolutions = { indexPatterns: function (Private) { const savedObjectsClient = Private(SavedObjectsClientProvider); return savedObjectsClient.find({ type: 'index-pattern', - fields: ['title'], + fields: ['title', 'type'], perPage: 10000 }).then(response => response.savedObjects); } @@ -52,28 +86,55 @@ uiRoutes // wrapper directive, which sets some global stuff up like the left nav uiModules.get('apps/management') - .directive('kbnManagementIndices', function ($route, config, kbnUrl) { + .directive('kbnManagementIndices', function ($route, config, kbnUrl, Private) { return { restrict: 'E', transclude: true, template: indexTemplate, - link: function ($scope) { - $scope.editingId = $route.current.params.indexPatternId; - config.bindToScope($scope, 'defaultIndex'); + link: async function ($scope) { + const indexPatternListProvider = Private(IndexPatternListFactory)(); + const indexPatternCreationProvider = Private(IndexPatternCreationFactory)(); + const indexPatternCreationOptions = await indexPatternCreationProvider.getIndexPatternCreationOptions((url) => { + $scope.$evalAsync(() => kbnUrl.change(url)); + }); - $scope.$watch('defaultIndex', function () { + const renderList = () => { $scope.indexPatternList = $route.current.locals.indexPatterns.map(pattern => { const id = pattern.id; + const tags = indexPatternListProvider.getIndexPatternTags(pattern, $scope.defaultIndex === id); return { id: id, title: pattern.get('title'), url: kbnUrl.eval('#/management/kibana/indices/{{id}}', { id: id }), - class: 'sidebar-item-title ' + ($scope.editingId === id ? 'active' : ''), - default: $scope.defaultIndex === id + active: $scope.editingId === id, + default: $scope.defaultIndex === id, + tag: tags && tags.length ? tags[0] : null, }; - }); - }); + }).sort((a, b) => { + if(a.default) { + return -1; + } + if(b.default) { + return 1; + } + if(a.title < b.title) { + return -1; + } + if(a.title > b.title) { + return 1; + } + return 0; + }) || []; + + updateIndexPatternList($scope, indexPatternCreationOptions, $scope.defaultIndex, $scope.indexPatternList); + }; + + $scope.$on('$destroy', destroyIndexPatternList); + $scope.editingId = $route.current.params.indexPatternId; + $scope.$watch('defaultIndex', () => renderList()); + config.bindToScope($scope, 'defaultIndex'); + $scope.$apply(); } }; }); diff --git a/src/core_plugins/kibana/public/management/sections/indices/index.scss b/src/core_plugins/kibana/public/management/sections/indices/index.scss new file mode 100644 index 0000000000000..2a4aadf0d4fd6 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/index.scss @@ -0,0 +1,15 @@ +#indexPatternListReact { + .indexPatternList__headerWrapper { + padding-bottom: $euiSizeS; + } + + .euiButtonEmpty__content { + justify-content: left; + padding: 0; + + span { + text-overflow: ellipsis; + overflow: hidden; + } + } +} diff --git a/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/create_button/create_button.js b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/create_button/create_button.js new file mode 100644 index 0000000000000..176ba0da03229 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/create_button/create_button.js @@ -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 React, { Component } from 'react'; +import PropTypes from 'prop-types'; + +import { + EuiButton, + EuiPopover, + EuiContextMenuPanel, + EuiContextMenuItem, + EuiDescriptionList, + EuiDescriptionListTitle, + EuiDescriptionListDescription, +} from '@elastic/eui'; + +export class CreateButton extends Component { + constructor(props) { + super(props); + this.state = { + isPopoverOpen: false, + }; + } + + static propTypes = { + options: PropTypes.arrayOf(PropTypes.shape({ + text: PropTypes.string.isRequired, + description: PropTypes.string, + onClick: PropTypes.func.isRequired, + })), + } + + togglePopover = () => { + this.setState({ + isPopoverOpen: !this.state.isPopoverOpen, + }); + } + + closePopover = () => { + this.setState({ + isPopoverOpen: false, + }); + } + + render() { + const { options, children } = this.props; + const { isPopoverOpen } = this.state; + + if(!options || !options.length) { + return null; + } + + if(options.length === 1) { + return ( + + {children} + + ); + } + + const button = ( + + {children} + + ); + + if(options.length > 1) { + return ( + + { + return ( + + + + {option.text} + + + {option.description} + + + + ); + })} + /> + + ); + } + } +} diff --git a/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/create_button/index.js b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/create_button/index.js new file mode 100644 index 0000000000000..caf956479ad99 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/create_button/index.js @@ -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 { CreateButton } from './create_button'; diff --git a/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/header/header.js b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/header/header.js new file mode 100644 index 0000000000000..5e16c641e039e --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/header/header.js @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { CreateButton } from '../create_button'; +import { I18nProvider, FormattedMessage } from '@kbn/i18n/react'; + +export const Header = ({ + indexPatternCreationOptions +}) => ( + + + + + +); diff --git a/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/header/index.js b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/header/index.js new file mode 100644 index 0000000000000..ac1e7bac06c87 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/header/index.js @@ -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 { Header } from './header'; diff --git a/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/list/index.js b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/list/index.js new file mode 100644 index 0000000000000..501bca9658d8e --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/list/index.js @@ -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 { List } from './list'; diff --git a/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/list/list.js b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/list/list.js new file mode 100644 index 0000000000000..07dd4efbfbcb6 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/components/list/list.js @@ -0,0 +1,83 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { Component, Fragment } from 'react'; +import PropTypes from 'prop-types'; + +import { + EuiButtonEmpty, + EuiBadge, + EuiCallOut, + EuiSpacer, +} from '@elastic/eui'; + +export class List extends Component { + static propTypes = { + indexPatterns: PropTypes.array, + defaultIndex: PropTypes.string, + } + + renderList() { + const { indexPatterns } = this.props; + return indexPatterns && indexPatterns.length ? ( +
+ { + indexPatterns.map(pattern => { + return ( +
+ + {pattern.default ? : ''} + {pattern.active ? {pattern.title} : pattern.title} {pattern.tag ? ( + + {{pattern.tag.name} } + + ) : null} + + +
+ ); + }) + } +
+ ) : null; + } + + renderNoDefaultMessage() { + const { defaultIndex } = this.props; + return !defaultIndex ? ( +
+ +
+ ) : null; + } + + render() { + return ( +
+ {this.renderNoDefaultMessage()} + {this.renderList()} +
+ ); + } +} diff --git a/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/index.js b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/index.js new file mode 100644 index 0000000000000..6a030202731c1 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/index.js @@ -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 { IndexPatternList } from './index_pattern_list'; diff --git a/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/index_pattern_list.js b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/index_pattern_list.js new file mode 100644 index 0000000000000..73351d73bd912 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/indices/index_pattern_list/index_pattern_list.js @@ -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. + */ + +import React, { Fragment } from 'react'; + +import { Header } from './components/header'; +import { List } from './components/list'; + +export const IndexPatternList = ({ + indexPatternCreationOptions, + defaultIndex, + indexPatterns +}) => ( + +
+
+
+ +
+); diff --git a/src/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js b/src/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js index 24c59142e75fb..be332b0780249 100644 --- a/src/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js +++ b/src/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js @@ -53,15 +53,27 @@ function addJsonFieldToIndexPattern(target, sourceString, fieldName, indexName) async function importIndexPattern(doc, indexPatterns, overwriteAll) { // TODO: consolidate this is the code in create_index_pattern_wizard.js const emptyPattern = await indexPatterns.get(); - const { title, timeFieldName, fields, fieldFormatMap, sourceFilters } = doc._source; + const { + title, + timeFieldName, + fields, + fieldFormatMap, + sourceFilters, + type, + typeMeta, + } = doc._source; const importedIndexPattern = { id: doc._id, title, - timeFieldName + timeFieldName, }; + if (type) { + importedIndexPattern.type = type; + } addJsonFieldToIndexPattern(importedIndexPattern, fields, 'fields', title); addJsonFieldToIndexPattern(importedIndexPattern, fieldFormatMap, 'fieldFormatMap', title); addJsonFieldToIndexPattern(importedIndexPattern, sourceFilters, 'sourceFilters', title); + addJsonFieldToIndexPattern(importedIndexPattern, typeMeta, 'typeMeta', title); Object.assign(emptyPattern, importedIndexPattern); const newId = await emptyPattern.create(true, !overwriteAll); @@ -128,14 +140,11 @@ export async function resolveIndexPatternConflicts( export async function saveObjects(objs, overwriteAll) { let importCount = 0; - await awaitEachItemInParallel( - objs, - async obj => { - if (await saveObject(obj, overwriteAll)) { - importCount++; - } + await awaitEachItemInParallel(objs, async obj => { + if (await saveObject(obj, overwriteAll)) { + importCount++; } - ); + }); return importCount; } @@ -143,12 +152,7 @@ export async function saveObject(obj, overwriteAll) { return await obj.save({ confirmOverwrite: !overwriteAll }); } -export async function resolveSavedSearches( - savedSearches, - services, - indexPatterns, - overwriteAll -) { +export async function resolveSavedSearches(savedSearches, services, indexPatterns, overwriteAll) { let importCount = 0; await awaitEachItemInParallel(savedSearches, async searchDoc => { const obj = await getSavedObject(searchDoc, services); @@ -163,12 +167,7 @@ export async function resolveSavedSearches( return importCount; } -export async function resolveSavedObjects( - savedObjects, - overwriteAll, - services, - indexPatterns -) { +export async function resolveSavedObjects(savedObjects, overwriteAll, services, indexPatterns) { const docTypes = groupByType(savedObjects); // Keep track of how many we actually import because the user @@ -177,19 +176,20 @@ export async function resolveSavedObjects( // Keep a record of any objects which fail to import for unknown reasons. const failedImports = []; // Start with the index patterns since everything is dependent on them - await awaitEachItemInParallel( - docTypes.indexPatterns, - async indexPatternDoc => { - try { - const importedIndexPatternId = await importIndexPattern(indexPatternDoc, indexPatterns, overwriteAll); - if (importedIndexPatternId) { - importedObjectCount++; - } - } catch (error) { - failedImports.push({ indexPatternDoc, error }); + await awaitEachItemInParallel(docTypes.indexPatterns, async indexPatternDoc => { + try { + const importedIndexPatternId = await importIndexPattern( + indexPatternDoc, + indexPatterns, + overwriteAll + ); + if (importedIndexPatternId) { + importedObjectCount++; } + } catch (error) { + failedImports.push({ indexPatternDoc, error }); } - ); + }); // We want to do the same for saved searches, but we want to keep them separate because they need // to be applied _first_ because other saved objects can be dependent on those saved searches existing diff --git a/src/core_plugins/timelion/public/directives/timelion_expression_suggestions/arg_value_suggestions.js b/src/core_plugins/timelion/public/directives/timelion_expression_suggestions/arg_value_suggestions.js index 1874ab1487b53..81d459f70a5e1 100644 --- a/src/core_plugins/timelion/public/directives/timelion_expression_suggestions/arg_value_suggestions.js +++ b/src/core_plugins/timelion/public/directives/timelion_expression_suggestions/arg_value_suggestions.js @@ -67,14 +67,16 @@ export function ArgValueSuggestionsProvider(Private, indexPatterns) { const search = partial ? `${partial}*` : '*'; const resp = await savedObjectsClient.find({ type: 'index-pattern', - fields: ['title'], + fields: ['title', 'type'], search: `${search}`, search_fields: ['title'], perPage: 25 }); - return resp.savedObjects.map(savedObject => { - return { name: savedObject.attributes.title }; - }); + return resp.savedObjects + .filter(savedObject => !savedObject.get('type')) + .map(savedObject => { + return { name: savedObject.attributes.title }; + }); }, metric: async function (partial, functionArgs) { if (!partial || !partial.includes(':')) { diff --git a/src/server/index_patterns/routes/fields_for_wildcard_route.js b/src/server/index_patterns/routes/fields_for_wildcard_route.js index f92c01328c980..2ca6a007bd182 100644 --- a/src/server/index_patterns/routes/fields_for_wildcard_route.js +++ b/src/server/index_patterns/routes/fields_for_wildcard_route.js @@ -27,7 +27,7 @@ export const createFieldsForWildcardRoute = pre => ({ validate: { query: Joi.object().keys({ pattern: Joi.string().required(), - meta_fields: Joi.array().items(Joi.string()).default([]) + meta_fields: Joi.array().items(Joi.string()).default([]), }).default() }, handler(req, reply) { diff --git a/src/server/index_patterns/service/index_patterns_service.js b/src/server/index_patterns/service/index_patterns_service.js index 68e800e4277f3..62b99b26ed7e4 100644 --- a/src/server/index_patterns/service/index_patterns_service.js +++ b/src/server/index_patterns/service/index_patterns_service.js @@ -32,7 +32,7 @@ export class IndexPatternsService { * Get a list of field objects for an index pattern that may contain wildcards * * @param {Object} [options={}] - * @property {String} options.pattern The moment compatible time pattern + * @property {String} options.pattern The index pattern * @property {Number} options.metaFields The list of underscore prefixed fields that should * be left in the field list (all others are removed). * @return {Promise>} diff --git a/src/ui/public/agg_types/buckets/date_histogram.js b/src/ui/public/agg_types/buckets/date_histogram.js index 925e9a5ab4883..78c926e9cdfcf 100644 --- a/src/ui/public/agg_types/buckets/date_histogram.js +++ b/src/ui/public/agg_types/buckets/date_histogram.js @@ -104,6 +104,11 @@ export const dateHistogramBucketAgg = new BucketAggType({ default: null, write: _.noop, }, + { + name: 'useNormalizedEsInterval', + default: true, + write: _.noop, + }, { name: 'interval', type: 'optioned', @@ -124,8 +129,8 @@ export const dateHistogramBucketAgg = new BucketAggType({ write: function (agg, output, aggs) { setBounds(agg, true); agg.buckets.setInterval(getInterval(agg)); - - const interval = agg.buckets.getInterval(); + const { useNormalizedEsInterval } = agg.params; + const interval = agg.buckets.getInterval(useNormalizedEsInterval); output.bucketInterval = interval; output.params.interval = interval.expression; diff --git a/src/ui/public/agg_types/buckets/histogram.js b/src/ui/public/agg_types/buckets/histogram.js index 40502ced08343..4e6448068f584 100644 --- a/src/ui/public/agg_types/buckets/histogram.js +++ b/src/ui/public/agg_types/buckets/histogram.js @@ -19,6 +19,8 @@ import _ from 'lodash'; +import { i18n } from '@kbn/i18n'; +import { toastNotifications } from 'ui/notify'; import '../../validate_date_interval'; import chrome from 'ui/chrome'; import { BucketAggType } from './_bucket_agg_type'; @@ -95,6 +97,12 @@ export const histogramBucketAgg = new BucketAggType({ min: _.get(resp, 'aggregations.minAgg.value'), max: _.get(resp, 'aggregations.maxAgg.value') }); + }) + .catch(() => { + toastNotifications.addWarning(i18n.translate('common.ui.aggTypes.histogram.missingMaxMinValuesWarning', { + // eslint-disable-next-line max-len + defaultMessage: 'Unable to retrieve max and min values to auto-scale histogram buckets. This may lead to poor visualization performance.' + })); }); }, write: function (aggConfig, output) { diff --git a/src/ui/public/agg_types/controls/order_and_size.html b/src/ui/public/agg_types/controls/order_and_size.html index 6a5626b3e140e..0daee545ea149 100644 --- a/src/ui/public/agg_types/controls/order_and_size.html +++ b/src/ui/public/agg_types/controls/order_and_size.html @@ -1,6 +1,6 @@
-
+