From cf5a044ef5914cfd4116cbc3f4c853db4753b346 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Wed, 19 Jul 2017 11:46:51 -0700 Subject: [PATCH] [5.x] Use single ES document type #12794 Partial backport containing 5.x specific changes --- .../edit_index_pattern/edit_index_pattern.js | 2 +- .../scripted_field_editor.js | 15 ++++- .../lib/mocha/decorate_mocha_ui.js | 4 ++ src/ui/public/agg_types/controls/field.html | 2 +- .../saved_object/saved_object_loader.js | 2 +- src/ui/public/index_patterns/_field.js | 2 +- .../public/index_patterns/_index_pattern.js | 2 +- .../kbn_top_nav/__tests__/bread_crumb_urls.js | 61 ------------------- .../bread_crumbs/bread_crumb_urls.js | 27 -------- .../bread_crumbs/bread_crumbs.html | 10 +-- .../kbn_top_nav/bread_crumbs/bread_crumbs.js | 38 +++++++----- src/ui/public/routes/breadcrumbs.js | 22 +++++++ src/ui/public/routes/route_manager.js | 37 +++++++---- src/ui/public/routes/routes.js | 22 ++++--- .../__tests__/saved_objects_client.js | 2 +- .../saved_objects/find_object_by_title.js | 2 +- .../saved_objects/saved_objects_client.js | 2 +- 17 files changed, 115 insertions(+), 137 deletions(-) delete mode 100644 src/ui/public/kbn_top_nav/__tests__/bread_crumb_urls.js delete mode 100644 src/ui/public/kbn_top_nav/bread_crumbs/bread_crumb_urls.js create mode 100644 src/ui/public/routes/breadcrumbs.js diff --git a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_index_pattern.js b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_index_pattern.js index b6d930b5683d8..4075b58cb0a44 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_index_pattern.js +++ b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/edit_index_pattern.js @@ -46,7 +46,7 @@ uiModules.get('apps/management') $scope.kbnUrl = Private(UrlProvider); $scope.indexPattern = $route.current.locals.indexPattern; - docTitle.change($scope.indexPattern.id); + docTitle.change($scope.indexPattern.title); const otherPatterns = _.filter($route.current.locals.indexPatterns, pattern => { return pattern.id !== $scope.indexPattern.id; diff --git a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/scripted_field_editor/scripted_field_editor.js b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/scripted_field_editor/scripted_field_editor.js index 8c90e44ec36f4..38266d304a6bb 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/scripted_field_editor/scripted_field_editor.js +++ b/src/core_plugins/kibana/public/management/sections/indices/edit_index_pattern/scripted_field_editor/scripted_field_editor.js @@ -9,6 +9,19 @@ uiRoutes .when('/management/kibana/indices/:indexPatternId/create-field/', { mode: 'create' }) .defaults(/management\/kibana\/indices\/[^\/]+\/(field|create-field)(\/|$)/, { template, + mapBreadcrumbs($route, breadcrumbs) { + const { indexPattern } = $route.current.locals; + return breadcrumbs.map(crumb => { + if (crumb.id !== indexPattern.id) { + return crumb; + } + + return { + ...crumb, + display: indexPattern.title + }; + }); + }, resolve: { indexPattern: function ($route, courier) { return courier.indexPatterns.get($route.current.params.indexPatternId) @@ -46,7 +59,7 @@ uiRoutes throw new Error('unknown fieldSettings mode ' + this.mode); } - docTitle.change([this.field.name || 'New Scripted Field', this.indexPattern.id]); + docTitle.change([this.field.name || 'New Scripted Field', this.indexPattern.title]); this.goBack = function () { kbnUrl.changeToRoute(this.indexPattern, 'edit'); }; diff --git a/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js b/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js index 682ef1c64b624..ac3c845500b2c 100644 --- a/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js +++ b/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js @@ -112,17 +112,21 @@ export function decorateMochaUi(lifecycle, context) { switch (property) { case 'describe': case 'describe.only': + case 'describe.skip': case 'xdescribe': case 'context': case 'context.only': + case 'context.skip': case 'xcontext': return wrapSuiteFunction(property, value); case 'it': case 'it.only': + case 'it.skip': case 'xit': case 'specify': case 'specify.only': + case 'specify.skip': case 'xspecify': return wrapTestFunction(property, value); diff --git a/src/ui/public/agg_types/controls/field.html b/src/ui/public/agg_types/controls/field.html index 9b5a2797c9f6e..4c52e80cb2294 100644 --- a/src/ui/public/agg_types/controls/field.html +++ b/src/ui/public/agg_types/controls/field.html @@ -27,7 +27,7 @@

- No Compatible Fields: The "{{ vis.indexPattern.id }}" index pattern does not contain any of the following field types: {{ agg.type.params.byName.field.filterFieldTypes | commaList:false }} + No Compatible Fields: The "{{ vis.indexPattern.title }}" index pattern does not contain any of the following field types: {{ agg.type.params.byName.field.filterFieldTypes | commaList:false }}

diff --git a/src/ui/public/courier/saved_object/saved_object_loader.js b/src/ui/public/courier/saved_object/saved_object_loader.js index 9488b85dcd7b3..cfdf39552bcd4 100644 --- a/src/ui/public/courier/saved_object/saved_object_loader.js +++ b/src/ui/public/courier/saved_object/saved_object_loader.js @@ -89,7 +89,7 @@ export class SavedObjectLoader { * @param size * @returns {Promise} */ - find(search, size = 100) { + find(search = '', size = 100) { return this.savedObjectsClient.find( { type: this.lowercaseType, diff --git a/src/ui/public/index_patterns/_field.js b/src/ui/public/index_patterns/_field.js index c8462bf34dbd9..4439f9243dcc6 100644 --- a/src/ui/public/index_patterns/_field.js +++ b/src/ui/public/index_patterns/_field.js @@ -27,7 +27,7 @@ export function IndexPatternsFieldProvider(Private, shortDotsFilter, $rootScope, notify.error( 'Unknown field type "' + spec.type + '"' + ' for field "' + spec.name + '"' + - ' in indexPattern "' + indexPattern.id + '"' + ' in indexPattern "' + indexPattern.title + '"' ); } diff --git a/src/ui/public/index_patterns/_index_pattern.js b/src/ui/public/index_patterns/_index_pattern.js index eaba238303ce4..c85c0e3a57f96 100644 --- a/src/ui/public/index_patterns/_index_pattern.js +++ b/src/ui/public/index_patterns/_index_pattern.js @@ -393,7 +393,7 @@ export function IndexPatternProvider(Private, $http, config, kbnIndex, Promise, }); } - async save() { + save() { return savedObjectsClient.update(type, this.id, this.prepBody()) .then(({ id }) => setId(this, id)); } diff --git a/src/ui/public/kbn_top_nav/__tests__/bread_crumb_urls.js b/src/ui/public/kbn_top_nav/__tests__/bread_crumb_urls.js deleted file mode 100644 index 8db81c0ac8b58..0000000000000 --- a/src/ui/public/kbn_top_nav/__tests__/bread_crumb_urls.js +++ /dev/null @@ -1,61 +0,0 @@ -import expect from 'expect.js'; - -import { getBreadCrumbUrls } from '../bread_crumbs/bread_crumb_urls'; - -describe('getBreadCrumbUrls', function () { - - it('returns urls for the breadcrumbs', function () { - const breadCrumbUrls = getBreadCrumbUrls( - ['path1', 'path2', 'a', 'longlonglonglong'], - 'http://test.com/path1/path2/a/longlonglonglong'); - expect(breadCrumbUrls.length).to.equal(4); - expect(breadCrumbUrls[0].url).to.equal('http://test.com/path1'); - expect(breadCrumbUrls[0].title).to.equal('Path 1'); - - expect(breadCrumbUrls[1].url).to.equal('http://test.com/path1/path2'); - expect(breadCrumbUrls[1].title).to.equal('Path 2'); - - expect(breadCrumbUrls[2].url).to.equal('http://test.com/path1/path2/a'); - expect(breadCrumbUrls[2].title).to.equal('A'); - - expect(breadCrumbUrls[3].url).to.equal('http://test.com/path1/path2/a/longlonglonglong'); - expect(breadCrumbUrls[3].title).to.equal('Longlonglonglong'); - }); - - it('is case insensitive', function () { - const breadCrumbUrls = getBreadCrumbUrls(['paTh1', 'path2'], 'http://TEST.com/paTh1/path2'); - expect(breadCrumbUrls.length).to.equal(2); - expect(breadCrumbUrls[0].url).to.equal('http://TEST.com/paTh1'); - expect(breadCrumbUrls[0].path).to.equal('paTh1'); - expect(breadCrumbUrls[0].title).to.equal('Pa Th 1'); - - expect(breadCrumbUrls[1].url).to.equal('http://TEST.com/paTh1/path2'); - expect(breadCrumbUrls[1].title).to.equal('Path 2'); - }); - - it('handles no breadcrumbs case', function () { - const breadCrumbUrls = getBreadCrumbUrls([], 'http://test.com'); - expect(breadCrumbUrls.length).to.equal(0); - }); - - it('handles spaces in breadcrumbs', function () { - const breadCrumbUrls = getBreadCrumbUrls( - ['something', 'somethingElse', 'snake_case', 'longLongLongLong'], - 'http://test.com/something/somethingElse/snake_case/longLongLongLong'); - expect(breadCrumbUrls.length).to.equal(4); - expect(breadCrumbUrls[0].url).to.equal('http://test.com/something'); - expect(breadCrumbUrls[0].title).to.equal('Something'); - - expect(breadCrumbUrls[1].url).to.equal('http://test.com/something/somethingElse'); - expect(breadCrumbUrls[1].path).to.equal('somethingElse'); - expect(breadCrumbUrls[1].title).to.equal('Something Else'); - - expect(breadCrumbUrls[2].url).to.equal('http://test.com/something/somethingElse/snake_case'); - expect(breadCrumbUrls[2].path).to.equal('snake_case'); - expect(breadCrumbUrls[2].title).to.equal('Snake Case'); - - expect(breadCrumbUrls[3].url).to.equal('http://test.com/something/somethingElse/snake_case/longLongLongLong'); - expect(breadCrumbUrls[3].title).to.equal('Long Long Long Long'); - }); - -}); diff --git a/src/ui/public/kbn_top_nav/bread_crumbs/bread_crumb_urls.js b/src/ui/public/kbn_top_nav/bread_crumbs/bread_crumb_urls.js deleted file mode 100644 index fc5146a613642..0000000000000 --- a/src/ui/public/kbn_top_nav/bread_crumbs/bread_crumb_urls.js +++ /dev/null @@ -1,27 +0,0 @@ -import _ from 'lodash'; -/** - * @typedef BreadCrumbUrl {Object} - * @property title {String} the display title for the breadcrumb - * @property path {String} the subdirectory for this particular breadcrumb - * @property url {String} a url for the breadcrumb - */ - -/** - * - * @param {Array.} breadcrumbs An array of breadcrumbs for the given url. - * @param {String} url The current url that the breadcrumbs have been generated for - * @returns {Array. An array comprised of objects that - * will contain both the url for the given breadcrumb, as well as the breadcrumb the url - * was generated for. - */ -export function getBreadCrumbUrls(breadcrumbs, url) { - // the url should not have a slash on the end or else the route will not be properly built - const urlBase = url.replace(/\/+$/, '').replace(breadcrumbs.join('/'), ''); - return breadcrumbs.map((path, index) => { - return { - path: path, - title: _.startCase(path), - url: urlBase + breadcrumbs.slice(0, index + 1).join('/') - }; - }); -} diff --git a/src/ui/public/kbn_top_nav/bread_crumbs/bread_crumbs.html b/src/ui/public/kbn_top_nav/bread_crumbs/bread_crumbs.html index e48b704f30a8a..9a98f763cb85e 100644 --- a/src/ui/public/kbn_top_nav/bread_crumbs/bread_crumbs.html +++ b/src/ui/public/kbn_top_nav/bread_crumbs/bread_crumbs.html @@ -1,23 +1,23 @@
- {{ breadcrumb.title }} + {{ breadcrumb.display }}
({ - path: path, - title: _.startCase(path) - })); + function omitPagesFilter(crumb) { + return ( + !$scope.omitPages || + !$scope.omitPages.includes(crumb.id) + ); } - if ($scope.omitCurrentPage === true) { - $scope.breadcrumbs.pop(); + + function omitCurrentPageFilter(crumb) { + return !($scope.omitCurrentPage && crumb.current); } + + $scope.$watchMulti([ + '[]omitPages', + 'omitCurrentPage' + ], function getBreadcrumbs() { + $scope.breadcrumbs = ( + uiRouter + .getBreadcrumbs() + .filter(omitPagesFilter) + .filter(omitCurrentPageFilter) + ); + }); } }; }); diff --git a/src/ui/public/routes/breadcrumbs.js b/src/ui/public/routes/breadcrumbs.js new file mode 100644 index 0000000000000..c9ffd284639e5 --- /dev/null +++ b/src/ui/public/routes/breadcrumbs.js @@ -0,0 +1,22 @@ +import { trim, startCase } from 'lodash'; + +/** + * Take a path (from $location.path() usually) and parse + * it's segments into a list of breadcrumbs + * + * @param {string} path + * @return {Array} + */ +export function parsePathToBreadcrumbs(path) { + return trim(path, '/') + .split('/') + .reduce((acc, id, i, parts) => [ + ...acc, + { + id, + display: startCase(id), + href: i === 0 ? `#/${id}` : `${acc[i - 1].href}/${id}`, + current: i === (parts.length - 1) + } + ], []); +} diff --git a/src/ui/public/routes/route_manager.js b/src/ui/public/routes/route_manager.js index 065ad6cacdbc5..af5938a4ab017 100644 --- a/src/ui/public/routes/route_manager.js +++ b/src/ui/public/routes/route_manager.js @@ -1,7 +1,8 @@ -import _ from 'lodash'; +import { defaultsDeep, wrap } from 'lodash'; import { wrapRouteWithPrep } from './wrap_route_with_prep'; import { RouteSetupManager } from './route_setup_manager'; +import { parsePathToBreadcrumbs } from './breadcrumbs'; function RouteManager() { const self = this; @@ -15,18 +16,17 @@ function RouteManager() { const path = args[0]; const route = args[1] || {}; - // merge in any defaults - defaults.forEach(function (args) { - if (args[0].test(path)) { - _.merge(route, args[1]); + defaults.forEach(def => { + if (def.regex.test(path)) { + defaultsDeep(route, def.value); } }); - if (route.reloadOnSearch === void 0) { + if (route.reloadOnSearch == null) { route.reloadOnSearch = false; } - if (route.requireDefaultIndex === void 0) { + if (route.requireDefaultIndex == null) { route.requireDefaultIndex = false; } @@ -40,14 +40,22 @@ function RouteManager() { } }; + self.run = function ($location, $route, $injector) { + self.getBreadcrumbs = () => { + const breadcrumbs = parsePathToBreadcrumbs($location.path()); + const map = $route.current.mapBreadcrumbs; + return map ? $injector.invoke(map, null, { breadcrumbs }) : breadcrumbs; + }; + }; + const wrapSetupAndChain = (fn, ...args) => { fn.apply(setup, args); return this; }; - this.addSetupWork = _.wrap(setup.addSetupWork, wrapSetupAndChain); - this.afterSetupWork = _.wrap(setup.afterSetupWork, wrapSetupAndChain); - this.afterWork = _.wrap(setup.afterWork, wrapSetupAndChain); + this.addSetupWork = wrap(setup.addSetupWork, wrapSetupAndChain); + this.afterSetupWork = wrap(setup.afterSetupWork, wrapSetupAndChain); + this.afterWork = wrap(setup.afterWork, wrapSetupAndChain); self.when = function (path, route) { when.push([path, route]); @@ -56,8 +64,8 @@ function RouteManager() { // before attaching the routes to the routeProvider, test the RE // against the .when() path and add/override the resolves if there is a match - self.defaults = function (RE, def) { - defaults.push([RE, def]); + self.defaults = function (regex, value) { + defaults.push({ regex, value }); return self; }; @@ -66,6 +74,11 @@ function RouteManager() { return self; }; + self.getBreadcrumbs = function () { + // overwritten in self.run(); + return []; + }; + self.RouteManager = RouteManager; } diff --git a/src/ui/public/routes/routes.js b/src/ui/public/routes/routes.js index 35eb9407eb05e..d4fa5e1847365 100644 --- a/src/ui/public/routes/routes.js +++ b/src/ui/public/routes/routes.js @@ -4,12 +4,18 @@ import { uiModules } from 'ui/modules'; const defaultRouteManager = new RouteManager(); import { WAIT_FOR_URL_CHANGE_TOKEN } from './route_setup_manager'; -module.exports = { - ...defaultRouteManager, - WAIT_FOR_URL_CHANGE_TOKEN, - enable() { - uiModules - .get('kibana', ['ngRoute']) - .config(defaultRouteManager.config); +// eslint-disable-next-line kibana-custom/no-default-export +export default Object.create(defaultRouteManager, { + WAIT_FOR_URL_CHANGE_TOKEN: { + value: WAIT_FOR_URL_CHANGE_TOKEN + }, + + enable: { + value() { + uiModules + .get('kibana', ['ngRoute']) + .config(defaultRouteManager.config) + .run(defaultRouteManager.run); + } } -}; +}); diff --git a/src/ui/public/saved_objects/__tests__/saved_objects_client.js b/src/ui/public/saved_objects/__tests__/saved_objects_client.js index 855dbabfa4669..742cf40afdd2f 100644 --- a/src/ui/public/saved_objects/__tests__/saved_objects_client.js +++ b/src/ui/public/saved_objects/__tests__/saved_objects_client.js @@ -298,7 +298,7 @@ describe('SavedObjectsClient', () => { expect($http.calledOnce).to.be(true); const options = $http.getCall(0).args[0]; - expect(options.url).to.eql(`${basePath}/api/saved_objects/index-pattern?type=index-pattern&invalid=true`); + expect(options.url).to.eql(`${basePath}/api/saved_objects/?type=index-pattern&invalid=true`); }); it('accepts fields', () => { diff --git a/src/ui/public/saved_objects/find_object_by_title.js b/src/ui/public/saved_objects/find_object_by_title.js index 0059c40d7f435..7e9bbb0d42fb8 100644 --- a/src/ui/public/saved_objects/find_object_by_title.js +++ b/src/ui/public/saved_objects/find_object_by_title.js @@ -17,7 +17,7 @@ export function findObjectByTitle(savedObjectsClient, type, title) { type, perPage: 10, search: `"${title}"`, - searchFields: 'title', + searchFields: ['title'], fields: ['title'] }).then(response => { const match = find(response.savedObjects, (obj) => { diff --git a/src/ui/public/saved_objects/saved_objects_client.js b/src/ui/public/saved_objects/saved_objects_client.js index 71180bc3175d4..c0f34c3c100cb 100644 --- a/src/ui/public/saved_objects/saved_objects_client.js +++ b/src/ui/public/saved_objects/saved_objects_client.js @@ -74,7 +74,7 @@ export class SavedObjectsClient { * @returns {promise} - { savedObjects: [ SavedObject({ id, type, version, attributes }) ]} */ find(options = {}) { - const url = this._getUrl([options.type], keysToSnakeCaseShallow(options)); + const url = this._getUrl([], keysToSnakeCaseShallow(options)); return this._request('GET', url).then(resp => { resp.saved_objects = resp.saved_objects.map(d => this.createSavedObject(d));