diff --git a/src/plugins/kibana/server/lib/__tests__/case_conversion.js b/src/plugins/kibana/common/lib/__tests__/case_conversion.js similarity index 100% rename from src/plugins/kibana/server/lib/__tests__/case_conversion.js rename to src/plugins/kibana/common/lib/__tests__/case_conversion.js diff --git a/src/plugins/kibana/server/lib/case_conversion.js b/src/plugins/kibana/common/lib/case_conversion.js similarity index 100% rename from src/plugins/kibana/server/lib/case_conversion.js rename to src/plugins/kibana/common/lib/case_conversion.js diff --git a/src/plugins/kibana/public/settings/sections/indices/add_data_steps/pattern_review_step.js b/src/plugins/kibana/public/settings/sections/indices/add_data_steps/pattern_review_step.js index be7a220636edf..afc4161bcf857 100644 --- a/src/plugins/kibana/public/settings/sections/indices/add_data_steps/pattern_review_step.js +++ b/src/plugins/kibana/public/settings/sections/indices/add_data_steps/pattern_review_step.js @@ -23,8 +23,8 @@ const testData = { const testPipeline = [ { grok: { - match_field: 'message', - match_pattern: 'foo' + field: 'message', + pattern: 'foo' } }, { diff --git a/src/plugins/kibana/public/settings/sections/indices/directives/kbn_settings_indices.js b/src/plugins/kibana/public/settings/sections/indices/directives/kbn_settings_indices.js index 6a590bc29d8a4..28da65a56c8f9 100644 --- a/src/plugins/kibana/public/settings/sections/indices/directives/kbn_settings_indices.js +++ b/src/plugins/kibana/public/settings/sections/indices/directives/kbn_settings_indices.js @@ -1,25 +1,37 @@ // wrapper directive, which sets some global stuff up like the left nav require('ui/modules').get('apps/settings') -.directive('kbnSettingsIndices', function ($route, config, kbnUrl) { +.directive('kbnSettingsIndices', function ($route, config, kbnUrl, indexPatterns, Private) { return { restrict: 'E', transclude: true, template: require('plugins/kibana/settings/sections/indices/directives/kbn_settings_indices.html'), link: function ($scope) { + const refreshKibanaIndex = Private(require('plugins/kibana/settings/sections/indices/_refresh_kibana_index')); + $scope.showAddNew = !/^\/settings\/indices$/.test($route.current.$$route.originalPath); $scope.editingId = $route.current.params.indexPatternId; config.$bind($scope, 'defaultIndex'); - $scope.$watch('defaultIndex', function () { - var ids = $route.current.locals.indexPatternIds; - $scope.indexPatternList = ids.map(function (id) { - return { - id: id, - url: kbnUrl.eval('#/settings/indices/edit/{{id}}', {id: id}), - class: 'sidebar-item-title ' + ($scope.editingId === id ? 'active' : ''), - default: $scope.defaultIndex === id - }; + function refreshIndexPatternList() { + indexPatterns.getIds.clearCache(); + indexPatterns.getIds() + .then((ids) => { + $scope.indexPatternIds = ids; + $scope.indexPatternList = ids.map(function (id) { + return { + id: id, + url: kbnUrl.eval('#/settings/indices/edit/{{id}}', {id: id}), + class: 'sidebar-item-title ' + ($scope.editingId === id ? 'active' : ''), + default: $scope.defaultIndex === id + }; + }); }); + } + + $scope.$watch('defaultIndex', refreshIndexPatternList); + + $scope.$on('ingest:updated', () => { + refreshKibanaIndex().then(refreshIndexPatternList); }); $scope.$emit('application.load'); diff --git a/src/plugins/kibana/public/settings/sections/indices/filebeat/directives/filebeat_wizard.html b/src/plugins/kibana/public/settings/sections/indices/filebeat/directives/filebeat_wizard.html index 0a99832581970..e81e9e1bfc4c4 100644 --- a/src/plugins/kibana/public/settings/sections/indices/filebeat/directives/filebeat_wizard.html +++ b/src/plugins/kibana/public/settings/sections/indices/filebeat/directives/filebeat_wizard.html @@ -60,7 +60,7 @@

Tail a File

diff --git a/src/plugins/kibana/public/settings/sections/indices/filebeat/directives/filebeat_wizard.js b/src/plugins/kibana/public/settings/sections/indices/filebeat/directives/filebeat_wizard.js index 2c5cc55a61330..fba75f020781f 100644 --- a/src/plugins/kibana/public/settings/sections/indices/filebeat/directives/filebeat_wizard.js +++ b/src/plugins/kibana/public/settings/sections/indices/filebeat/directives/filebeat_wizard.js @@ -1,5 +1,6 @@ -var modules = require('ui/modules'); -var template = require('plugins/kibana/settings/sections/indices/filebeat/directives/filebeat_wizard.html'); +import modules from 'ui/modules'; +import template from 'plugins/kibana/settings/sections/indices/filebeat/directives/filebeat_wizard.html'; +import IngestProvider from 'ui/ingest'; require('plugins/kibana/settings/sections/indices/add_data_steps/pattern_review_step'); require('plugins/kibana/settings/sections/indices/add_data_steps/paste_samples_step'); @@ -15,8 +16,14 @@ modules.get('apps/settings') scope: {}, bindToController: true, controllerAs: 'wizard', - controller: function ($scope, AppState, safeConfirm, kbnUrl) { - var $state = this.state = new AppState(); + controller: function ($scope, AppState, safeConfirm, kbnUrl, $http, Notifier, $window, config, Private) { + const ingest = Private(IngestProvider); + const $state = this.state = new AppState(); + + var notify = new Notifier({ + location: 'Add Data' + }); + var totalSteps = 4; this.stepResults = {}; @@ -36,12 +43,26 @@ modules.get('apps/settings') kbnUrl.change('/discover'); } }; + this.prevStep = () => { if ($state.currentStep > 0) { this.setCurrentStep($state.currentStep - 1); } }; + this.save = () => { + return ingest.save(this.stepResults.indexPattern, this.stepResults.pipeline) + .then( + () => { + this.nextStep(); + }, + (err) => { + notify.error(err); + $window.scrollTo(0,0); + } + ); + }; + $scope.$watch('wizard.state.currentStep', (newValue, oldValue) => { if (this.complete) { $state.currentStep = totalSteps - 1; diff --git a/src/plugins/kibana/server/routes/api/ingest/register_post.js b/src/plugins/kibana/server/routes/api/ingest/register_post.js index 9ff7281db5417..0bd671578b0c7 100644 --- a/src/plugins/kibana/server/routes/api/ingest/register_post.js +++ b/src/plugins/kibana/server/routes/api/ingest/register_post.js @@ -5,7 +5,7 @@ import handleESError from '../../../lib/handle_es_error'; import createMappingsFromPatternFields from '../../../lib/create_mappings_from_pattern_fields'; import initDefaultFieldProps from '../../../lib/init_default_field_props'; import {ingestToPattern, patternToIngest} from '../../../lib/convert_pattern_and_ingest_name'; -import { keysToCamelCaseShallow } from '../../../lib/case_conversion'; +import { keysToCamelCaseShallow } from '../../../../common/lib/case_conversion'; function patternRollback(rootError, indexPatternId, boundCallWithRequest) { const deleteParams = { diff --git a/src/ui/public/ingest/__tests__/ingest.js b/src/ui/public/ingest/__tests__/ingest.js new file mode 100644 index 0000000000000..0d69e3d28069d --- /dev/null +++ b/src/ui/public/ingest/__tests__/ingest.js @@ -0,0 +1,68 @@ +import ngMock from 'ngMock'; +import expect from 'expect.js'; +import IngestProvider from '../ingest'; +import sinon from 'auto-release-sinon'; + +describe('Ingest Service', function () { + let $httpBackend; + let ingest; + let config; + let $rootScope; + + beforeEach(ngMock.module('kibana')); + beforeEach(ngMock.inject(function ($injector, Private) { + ingest = Private(IngestProvider); + config = $injector.get('config'); + $httpBackend = $injector.get('$httpBackend'); + + $rootScope = $injector.get('$rootScope'); + sinon.spy($rootScope, '$broadcast'); + })); + + it('Throws an error if an index pattern is not provided', function () { + expect(ingest.save).to.throwException(/index pattern is required/); + }); + + it('Sets the default index if there isn\'t one already', function () { + $httpBackend + .when('POST', '../api/kibana/ingest') + .respond('ok'); + + expect(config.get('defaultIndex')).to.be(null); + ingest.save({id: 'foo'}); + ingest.save({id: 'bar'}); + $httpBackend.flush(); + expect(config.get('defaultIndex')).to.be('foo'); + }); + + it('Returns error from ingest API if there is one', function (done) { + $httpBackend + .expectPOST('../api/kibana/ingest') + .respond(400); + + ingest.save({id: 'foo'}) + .then( + () => { + throw new Error('expected an error response'); + }, + (error) => { + expect(error.status).to.be(400); + done(); + } + ); + + $httpBackend.flush(); + }); + + it('Broadcasts an ingest:updated event on the rootScope upon succesful save', function () { + $httpBackend + .when('POST', '../api/kibana/ingest') + .respond('ok'); + + ingest.save({id: 'foo'}); + $httpBackend.flush(); + + expect($rootScope.$broadcast.calledOnce); + expect($rootScope.$broadcast.calledWith('ingest:updated')).to.be.ok(); + }); +}); diff --git a/src/ui/public/ingest/ingest.js b/src/ui/public/ingest/ingest.js new file mode 100644 index 0000000000000..181095dc28678 --- /dev/null +++ b/src/ui/public/ingest/ingest.js @@ -0,0 +1,28 @@ +import { keysToSnakeCaseShallow } from '../../../plugins/kibana/common/lib/case_conversion'; +import _ from 'lodash'; + +export default function IngestProvider($rootScope, $http, config) { + + this.save = function (indexPattern, pipeline) { + if (_.isEmpty(indexPattern)) { + throw new Error('index pattern is required'); + } + + const payload = { + index_pattern: keysToSnakeCaseShallow(indexPattern) + }; + if (!_.isEmpty(pipeline)) { + payload.pipeline = pipeline; + } + + return $http.post('../api/kibana/ingest', payload) + .then(() => { + if (!config.get('defaultIndex')) { + config.set('defaultIndex', indexPattern.id); + } + + $rootScope.$broadcast('ingest:updated'); + }); + }; + +}