From 71ba760ba42fe5d44c2a63a80c0501397c89def4 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Mon, 26 Aug 2019 16:01:43 -0700 Subject: [PATCH 01/15] initial attempt at adding saved-queries to maps --- x-pack/legacy/plugins/maps/index.js | 4 +- .../plugins/maps/public/angular/map.html | 5 ++ .../maps/public/angular/map_controller.js | 57 +++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js index 38fe0c2486a95..83561ed1e6d77 100644 --- a/x-pack/legacy/plugins/maps/index.js +++ b/x-pack/legacy/plugins/maps/index.js @@ -120,7 +120,7 @@ export function maps(kibana) { privileges: { all: { savedObject: { - all: ['map'], + all: ['map', 'query'], read: ['index-pattern'] }, ui: ['save', 'show'], @@ -128,7 +128,7 @@ export function maps(kibana) { read: { savedObject: { all: [], - read: ['map', 'index-pattern'] + read: ['map', 'index-pattern', 'query'] }, ui: ['show'], }, diff --git a/x-pack/legacy/plugins/maps/public/angular/map.html b/x-pack/legacy/plugins/maps/public/angular/map.html index f17b2d537b264..7c4f9cb018e33 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map.html +++ b/x-pack/legacy/plugins/maps/public/angular/map.html @@ -8,7 +8,9 @@ show-search-bar="chrome.getVisible()" show-filter-bar="chrome.getVisible()" show-date-picker="showDatePicker" + show-save-query="showSaveQuery" query="query" + saved-query="savedQuery" on-query-submit="updateQueryAndDispatch" filters="filters" on-filters-updated="updateFiltersAndDispatch" @@ -18,6 +20,9 @@ is-refresh-paused="refreshConfig.isPaused" refresh-interval="refreshConfig.interval" on-refresh-change="onRefreshChange" + on-saved="onQuerySaved" + on-saved-query-updated="onSavedQueryUpdated" + on-clear-saved-query="onClearSavedQuery" > diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index 829af62f45604..94b2b2b3fe965 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -55,6 +55,8 @@ import { import { FilterStateStore } from '@kbn/es-query'; import { setup as data } from '../../../../../../src/legacy/core_plugins/data/public/legacy'; +// const { savedQueryService } = data.search.services; + const REACT_ANCHOR_DOM_ELEMENT_ID = 'react-maps-root'; const app = uiModules.get(MAP_APP_PATH, []); @@ -123,6 +125,60 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta mapStateJSON: savedMap.mapStateJSON, globalState: globalState, }); + /* Saved Queries */ + $scope.onQuerySaved = savedQuery => { + $scope.savedQuery = savedQuery; + }; + + $scope.onSavedQueryUpdated = savedQuery => { + $scope.savedQuery = savedQuery; + }; + + $scope.onClearSavedQuery = () => { + $scope.savedQuery = undefined; + }; + + const updateStateFromSavedQuery = (savedQuery) => { + // use the items from the saved query as the scope variables, + // then sync the app and global state, + // then dispatch set Query + $scope.query = savedQuery.attributes.query; + $scope.filters = savedQuery.attributes.filters || []; + if (savedQuery.attributes.timefilter) { + $scope.time = { + from: savedQuery.attributes.timefilter.timeFrom, + to: savedQuery.attributes.timefilter.timeTo, + }; + if (savedQuery.attributes.timefilter.refreshInterval) { + $scope.refreshInterval = savedQuery.attributes.timefilter.refreshInterval; + } + } + syncAppAndGlobalState(); + dispatchSetQuery(); + }; + $scope.$watch('savedQuery', (newSavedQuery, oldSavedQuery) => { + if (!newSavedQuery) { + $state.savedQuery = undefined; + $scope.query = { + query: '', + language: localStorage.get('kibana.userQueryLanguage') + }; + syncAppAndGlobalState(); + dispatchSetQuery(); + } else { + $state.savedQuery = newSavedQuery.id; + if (newSavedQuery.id === (oldSavedQuery && oldSavedQuery.id)) { + updateStateFromSavedQuery(newSavedQuery); + } + } + }); + + $scope.$watch(() => $state.savedQuery, newSavedQueryId => { + if (!newSavedQueryId) { + $scope.savedQuery = undefined; + return; + } + }); async function onQueryChange({ filters, query, time }) { if (filters) { @@ -388,6 +444,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta timefilter.disableTimeRangeSelector(); timefilter.disableAutoRefreshSelector(); $scope.showDatePicker = true; // used by query-bar directive to enable timepikcer in query bar + $scope.showSavedQuery = true; //used by saved queries to show the saved query management component $scope.topNavMenu = [{ id: 'full-screen', label: i18n.translate('xpack.maps.mapController.fullScreenButtonLabel', { From 180e17534497c34919d4d8c1e3e85a358714657e Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Tue, 27 Aug 2019 12:01:20 -0700 Subject: [PATCH 02/15] Adds savedQuery methods to map_controller --- .../maps/public/angular/map_controller.js | 84 +++++++++++-------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index 94b2b2b3fe965..a0785381a2052 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -55,7 +55,7 @@ import { import { FilterStateStore } from '@kbn/es-query'; import { setup as data } from '../../../../../../src/legacy/core_plugins/data/public/legacy'; -// const { savedQueryService } = data.search.services; +const { savedQueryService } = data.search.services; const REACT_ANCHOR_DOM_ELEMENT_ID = 'react-maps-root'; @@ -126,58 +126,71 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta globalState: globalState, }); /* Saved Queries */ + $scope.showSaveQuery = capabilities.get().maps.saveQuery; + + $scope.$watch(() => capabilities.get().maps.saveQuery, (newCapability) => { + $scope.showSaveQuery = newCapability; + }); + $scope.onQuerySaved = savedQuery => { $scope.savedQuery = savedQuery; }; $scope.onSavedQueryUpdated = savedQuery => { - $scope.savedQuery = savedQuery; + $scope.savedQuery = { ...savedQuery }; }; $scope.onClearSavedQuery = () => { - $scope.savedQuery = undefined; + delete $scope.savedQuery; + delete $state.savedQuery; + onQueryChange({ + filters: [], + query: { + query: '', + language: localStorage.get('kibana.userQueryLanguage') + }, + }); }; - const updateStateFromSavedQuery = (savedQuery) => { - // use the items from the saved query as the scope variables, - // then sync the app and global state, - // then dispatch set Query - $scope.query = savedQuery.attributes.query; - $scope.filters = savedQuery.attributes.filters || []; - if (savedQuery.attributes.timefilter) { - $scope.time = { - from: savedQuery.attributes.timefilter.timeFrom, - to: savedQuery.attributes.timefilter.timeTo, - }; - if (savedQuery.attributes.timefilter.refreshInterval) { - $scope.refreshInterval = savedQuery.attributes.timefilter.refreshInterval; - } + async function updateStateFromSavedQuery(savedQuery) { + // use the items from the saved query as the arguments to onQueryChange + // onQueryChange syncs the app with the global state, taking the args given and setting those to $scope and $state variables. + // For the refresh config, we don't need an 'isPaused' because the app will take the global setting for us. + // onQueryChange then also does the dispatching, so we don't need to worry about that either, + await onQueryChange({ + filters: savedQuery.attributes.filters || [], + query: savedQuery.attributes.query, + time: savedQuery.attributes.timefilter ? + { + from: savedQuery.attributes.timefilter.timeFrom, + to: savedQuery.attributes.timefilter.timeTo + } : undefined + }); + if (savedQuery.attributes.timefilter && savedQuery.attributes.timefilter.refreshInterval) { + // I need to set the refreshInterval but don't know where to get isPaused from + $scope.refreshConfig.interval = savedQuery.attributes.timefilter.refreshInterval; } - syncAppAndGlobalState(); - dispatchSetQuery(); - }; + } + $scope.$watch('savedQuery', (newSavedQuery, oldSavedQuery) => { - if (!newSavedQuery) { - $state.savedQuery = undefined; - $scope.query = { - query: '', - language: localStorage.get('kibana.userQueryLanguage') - }; - syncAppAndGlobalState(); - dispatchSetQuery(); - } else { - $state.savedQuery = newSavedQuery.id; - if (newSavedQuery.id === (oldSavedQuery && oldSavedQuery.id)) { - updateStateFromSavedQuery(newSavedQuery); - } + if (!newSavedQuery) return; + $state.savedQuery = newSavedQuery.id; + + if (newSavedQuery.id === (oldSavedQuery && oldSavedQuery.id)) { + updateStateFromSavedQuery(newSavedQuery); } }); - - $scope.$watch(() => $state.savedQuery, newSavedQueryId => { + $scope.$watch('state.savedQuery', newSavedQueryId => { if (!newSavedQueryId) { $scope.savedQuery = undefined; return; } + savedQueryService.getSavedQuery(newSavedQueryId).then((savedQuery) => { + $scope.$evalAsync(() => { + $scope.savedQuery = savedQuery; + updateStateFromSavedQuery(savedQuery); + }); + }); }); async function onQueryChange({ filters, query, time }) { @@ -444,7 +457,6 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta timefilter.disableTimeRangeSelector(); timefilter.disableAutoRefreshSelector(); $scope.showDatePicker = true; // used by query-bar directive to enable timepikcer in query bar - $scope.showSavedQuery = true; //used by saved queries to show the saved query management component $scope.topNavMenu = [{ id: 'full-screen', label: i18n.translate('xpack.maps.mapController.fullScreenButtonLabel', { From 33e4ec4ce5c69fc5f6cbe6796dd5ddc5f9c75053 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Tue, 27 Aug 2019 13:56:40 -0700 Subject: [PATCH 03/15] Adds saveQuery to Maps ui --- x-pack/legacy/plugins/maps/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js index 83561ed1e6d77..076fae1bb5882 100644 --- a/x-pack/legacy/plugins/maps/index.js +++ b/x-pack/legacy/plugins/maps/index.js @@ -123,7 +123,7 @@ export function maps(kibana) { all: ['map', 'query'], read: ['index-pattern'] }, - ui: ['save', 'show'], + ui: ['save', 'show', 'saveQuery'], }, read: { savedObject: { From 31c767fbfd13637288d3ee6da7c753affc0c61fd Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Tue, 27 Aug 2019 15:39:40 -0700 Subject: [PATCH 04/15] Fixes watcher on state --- .../plugins/maps/public/angular/map_controller.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index a0785381a2052..d47f1842d5df4 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -152,12 +152,16 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta }); }; - async function updateStateFromSavedQuery(savedQuery) { + function updateStateFromSavedQuery(savedQuery) { // use the items from the saved query as the arguments to onQueryChange // onQueryChange syncs the app with the global state, taking the args given and setting those to $scope and $state variables. // For the refresh config, we don't need an 'isPaused' because the app will take the global setting for us. // onQueryChange then also does the dispatching, so we don't need to worry about that either, - await onQueryChange({ + if (savedQuery.attributes.timefilter && savedQuery.attributes.timefilter.refreshInterval) { + // I need to set the refreshInterval but don't know where to get isPaused from + $scope.refreshConfig.interval = savedQuery.attributes.timefilter.refreshInterval; + } + onQueryChange({ filters: savedQuery.attributes.filters || [], query: savedQuery.attributes.query, time: savedQuery.attributes.timefilter ? @@ -166,10 +170,6 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta to: savedQuery.attributes.timefilter.timeTo } : undefined }); - if (savedQuery.attributes.timefilter && savedQuery.attributes.timefilter.refreshInterval) { - // I need to set the refreshInterval but don't know where to get isPaused from - $scope.refreshConfig.interval = savedQuery.attributes.timefilter.refreshInterval; - } } $scope.$watch('savedQuery', (newSavedQuery, oldSavedQuery) => { @@ -180,7 +180,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta updateStateFromSavedQuery(newSavedQuery); } }); - $scope.$watch('state.savedQuery', newSavedQueryId => { + $scope.$watch(() => $state.savedQuery, newSavedQueryId => { if (!newSavedQueryId) { $scope.savedQuery = undefined; return; From 9e72e6820f7fbdd12ffaf3cf13f279ec45aaa285 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Tue, 27 Aug 2019 17:18:25 -0700 Subject: [PATCH 05/15] Fixes adding filters, still debuggin why the timefilter automatically changes to last 15 min on saving a query with a time filter. The time filter saves correctly in the saved query --- .../maps/public/angular/map_controller.js | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index d47f1842d5df4..a1fc3b999c260 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -155,21 +155,25 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta function updateStateFromSavedQuery(savedQuery) { // use the items from the saved query as the arguments to onQueryChange // onQueryChange syncs the app with the global state, taking the args given and setting those to $scope and $state variables. - // For the refresh config, we don't need an 'isPaused' because the app will take the global setting for us. - // onQueryChange then also does the dispatching, so we don't need to worry about that either, - if (savedQuery.attributes.timefilter && savedQuery.attributes.timefilter.refreshInterval) { - // I need to set the refreshInterval but don't know where to get isPaused from - $scope.refreshConfig.interval = savedQuery.attributes.timefilter.refreshInterval; + + // the time filter is tricky here, TODO: fix the timefilter issues + + if (savedQuery.attributes.timefilter) { + if (savedQuery.attributes.timefilter.refreshInterval) { + $scope.refreshConfig.interval = savedQuery.attributes.timefilter.refreshInterval.value; + $scope.refreshConfig.isPaused = savedQuery.attributes.timefilter.refreshInterval.pause; + } + onQueryChange({ + filters: savedQuery.attributes.filters || [], + query: savedQuery.attributes.query, + time: { from: savedQuery.attributes.timefilter.timeFrom, to: savedQuery.attributes.timefilter.timeTo } + }); + } else { + onQueryChange({ + filters: savedQuery.attributes.filters || [], + query: savedQuery.attributes.query, + }); } - onQueryChange({ - filters: savedQuery.attributes.filters || [], - query: savedQuery.attributes.query, - time: savedQuery.attributes.timefilter ? - { - from: savedQuery.attributes.timefilter.timeFrom, - to: savedQuery.attributes.timefilter.timeTo - } : undefined - }); } $scope.$watch('savedQuery', (newSavedQuery, oldSavedQuery) => { From 683b76be8f79da3a995e384f036aa404f9f8e821 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Thu, 29 Aug 2019 10:25:06 -0700 Subject: [PATCH 06/15] Gets time filter working with saved queries --- .../plugins/maps/public/angular/map_controller.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index a1fc3b999c260..3e9ce3146e53b 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -125,6 +125,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta mapStateJSON: savedMap.mapStateJSON, globalState: globalState, }); + /* Saved Queries */ $scope.showSaveQuery = capabilities.get().maps.saveQuery; @@ -153,11 +154,6 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta }; function updateStateFromSavedQuery(savedQuery) { - // use the items from the saved query as the arguments to onQueryChange - // onQueryChange syncs the app with the global state, taking the args given and setting those to $scope and $state variables. - - // the time filter is tricky here, TODO: fix the timefilter issues - if (savedQuery.attributes.timefilter) { if (savedQuery.attributes.timefilter.refreshInterval) { $scope.refreshConfig.interval = savedQuery.attributes.timefilter.refreshInterval.value; @@ -166,7 +162,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta onQueryChange({ filters: savedQuery.attributes.filters || [], query: savedQuery.attributes.query, - time: { from: savedQuery.attributes.timefilter.timeFrom, to: savedQuery.attributes.timefilter.timeTo } + time: savedQuery.attributes.timefilter }); } else { onQueryChange({ @@ -178,12 +174,14 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta $scope.$watch('savedQuery', (newSavedQuery, oldSavedQuery) => { if (!newSavedQuery) return; + $state.savedQuery = newSavedQuery.id; if (newSavedQuery.id === (oldSavedQuery && oldSavedQuery.id)) { updateStateFromSavedQuery(newSavedQuery); } }); + $scope.$watch(() => $state.savedQuery, newSavedQueryId => { if (!newSavedQueryId) { $scope.savedQuery = undefined; @@ -196,7 +194,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta }); }); }); - + /* End of Saved Queries */ async function onQueryChange({ filters, query, time }) { if (filters) { await data.filter.filterManager.setFilters(filters); // Maps and merges filters From 5c8f731e7d2a06a24f9d586933c322c5f3a5f206 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Thu, 29 Aug 2019 15:13:42 -0700 Subject: [PATCH 07/15] Adds saved query management component functionality tests to maps for all privileges --- .../maps/feature_controls/maps_security.ts | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts index cfec4749f6847..fd3de542d87db 100644 --- a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts +++ b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts @@ -13,9 +13,11 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { const appsMenu = getService('appsMenu'); const testSubjects = getService('testSubjects'); const globalNav = getService('globalNav'); + const queryBar = getService('queryBar'); + const savedQueryManagementComponent = getService('savedQueryManagementComponent'); // FLAKY: https://github.com/elastic/kibana/issues/38414 - describe.skip('security feature controls', () => { + describe('security feature controls', () => { before(async () => { await esArchiver.loadIfNeeded('maps/data'); await esArchiver.load('maps/kibana'); @@ -82,6 +84,37 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`doesn't show read-only badge`, async () => { await globalNav.badgeMissingOrFail(); }); + + it('allows saving via the saved query management component popover with no query loaded', async () => { + await PageObjects.maps.openNewMap(); + await queryBar.setQuery('response:200'); + await savedQueryManagementComponent.saveNewQuery('foo', 'bar', true, false); + await savedQueryManagementComponent.savedQueryExistOrFail('foo'); + }); + + it('allows saving a currently loaded saved query as a new query via the saved query management component ', async () => { + await savedQueryManagementComponent.saveCurrentlyLoadedAsNewQuery( + 'foo2', + 'bar2', + true, + false + ); + await savedQueryManagementComponent.savedQueryExistOrFail('foo2'); + }); + + it('allow saving changes to a currently loaded query via the saved query management component', async () => { + await queryBar.setQuery('response:404'); + await savedQueryManagementComponent.updateCurrentlyLoadedQuery('bar2', false, false); + await savedQueryManagementComponent.clearCurrentlyLoadedQuery(); + await savedQueryManagementComponent.loadSavedQuery('foo2'); + const queryString = await queryBar.getQueryString(); + expect(queryString).to.eql('response:404'); + }); + + it('allows deleting saved queries in the saved query management component ', async () => { + await savedQueryManagementComponent.deleteSavedQuery('foo2'); + await savedQueryManagementComponent.savedQueryMissingOrFail('foo2'); + }); }); describe('global maps read-only privileges', () => { From cf7e0b5681e5c45ef60bf48384899e7de8967888 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Thu, 29 Aug 2019 15:20:20 -0700 Subject: [PATCH 08/15] Adds a saved query to the mapping and data for maps security functional tests --- .../es_archives/maps/kibana/data.json | 22 ++++++++++++++ .../es_archives/maps/kibana/mappings.json | 29 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/x-pack/test/functional/es_archives/maps/kibana/data.json b/x-pack/test/functional/es_archives/maps/kibana/data.json index d9baecf23d852..8a3cc77fc3a0b 100644 --- a/x-pack/test/functional/es_archives/maps/kibana/data.json +++ b/x-pack/test/functional/es_archives/maps/kibana/data.json @@ -762,3 +762,25 @@ } } } + +{ + "type": "doc", + "value": { + "index": ".kibana", + "type": "doc", + "id": "query:okjpgs", + "source": { + "query": { + "title": "OKJpgs", + "description": "Ok responses for jpg files", + "query": { + "query": "response:200", + "language": "kuery" + }, + "filters": [{"meta":{"index":"b15b1d40-a8bb-11e9-98cf-2bb06ef63e0b","alias":null,"negate":false,"type":"phrase","key":"extension.raw","value":"jpg","params":{"query":"jpg"},"disabled":false},"query":{"match":{"extension.raw":{"query":"jpg","type":"phrase"}}},"$state":{"store":"appState"}}] + }, + "type": "query", + "updated_at": "2019-07-17T17:54:26.378Z" + } + } +} diff --git a/x-pack/test/functional/es_archives/maps/kibana/mappings.json b/x-pack/test/functional/es_archives/maps/kibana/mappings.json index c7e786b20ac19..7f421123bddf8 100644 --- a/x-pack/test/functional/es_archives/maps/kibana/mappings.json +++ b/x-pack/test/functional/es_archives/maps/kibana/mappings.json @@ -397,6 +397,35 @@ "type": "text" } } + }, + "query": { + "properties": { + "title": { + "type": "text" + }, + "description": { + "type": "text" + }, + "query": { + "properties": { + "language": { + "type": "keyword" + }, + "query": { + "type": "keyword", + "index": false + } + } + }, + "filters": { + "type": "object", + "enabled": false + }, + "timefilter": { + "type": "object", + "enabled": false + } + } } } }, From 40424c9b029f84b6dd67733450b7aced5cbac075 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Thu, 29 Aug 2019 15:41:32 -0700 Subject: [PATCH 09/15] Updates test saved query doc --- x-pack/test/functional/es_archives/maps/kibana/data.json | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/functional/es_archives/maps/kibana/data.json b/x-pack/test/functional/es_archives/maps/kibana/data.json index 8a3cc77fc3a0b..3883d90e5318f 100644 --- a/x-pack/test/functional/es_archives/maps/kibana/data.json +++ b/x-pack/test/functional/es_archives/maps/kibana/data.json @@ -767,7 +767,6 @@ "type": "doc", "value": { "index": ".kibana", - "type": "doc", "id": "query:okjpgs", "source": { "query": { From fcd609869c2c794d292c02e6c6589f68364ce7f0 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Thu, 29 Aug 2019 15:46:18 -0700 Subject: [PATCH 10/15] Adds functional tests for saved queries as a maps read-only user --- .../maps/feature_controls/maps_security.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts index fd3de542d87db..7bc0f88712e55 100644 --- a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts +++ b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts @@ -186,6 +186,31 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`can't add layer`, async () => { await PageObjects.maps.expectMissingAddLayerButton(); }); + + it('allows loading a saved query via the saved query management component', async () => { + await savedQueryManagementComponent.loadSavedQuery('OKJpgs'); + const queryString = await queryBar.getQueryString(); + expect(queryString).to.eql('response:200'); + }); + + it('does not allow saving via the saved query management component popover with no query loaded', async () => { + await savedQueryManagementComponent.saveNewQueryMissingOrFail(); + }); + + it('does not allow saving changes to saved query from the saved query management component', async () => { + await savedQueryManagementComponent.loadSavedQuery('OKJpgs'); + await queryBar.setQuery('response:404'); + await savedQueryManagementComponent.updateCurrentlyLoadedQueryMissingOrFail(); + }); + + it('does not allow deleting a saved query from the saved query management component', async () => { + await savedQueryManagementComponent.deleteSavedQueryMissingOrFail('OKJpgs'); + }); + + it('allows clearing the currently loaded saved query', async () => { + await savedQueryManagementComponent.loadSavedQuery('OKJpgs'); + await savedQueryManagementComponent.clearCurrentlyLoadedQuery(); + }); }); }); From ddf0923488e019803728afce199b7122190c6706 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Thu, 29 Aug 2019 15:47:11 -0700 Subject: [PATCH 11/15] Adds 'skip' back to maps security functional tests --- .../test/functional/apps/maps/feature_controls/maps_security.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts index 7bc0f88712e55..2543eec76340f 100644 --- a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts +++ b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts @@ -17,7 +17,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { const savedQueryManagementComponent = getService('savedQueryManagementComponent'); // FLAKY: https://github.com/elastic/kibana/issues/38414 - describe('security feature controls', () => { + describe.skip('security feature controls', () => { before(async () => { await esArchiver.loadIfNeeded('maps/data'); await esArchiver.load('maps/kibana'); From 4333b872134a12beb57f8e6648e9b624e3398b48 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Tue, 3 Sep 2019 12:25:36 -0700 Subject: [PATCH 12/15] uses onRefreshChange in map_controller --- x-pack/legacy/plugins/maps/public/angular/map_controller.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index 3e9ce3146e53b..5a631294f0398 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -156,8 +156,10 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta function updateStateFromSavedQuery(savedQuery) { if (savedQuery.attributes.timefilter) { if (savedQuery.attributes.timefilter.refreshInterval) { - $scope.refreshConfig.interval = savedQuery.attributes.timefilter.refreshInterval.value; - $scope.refreshConfig.isPaused = savedQuery.attributes.timefilter.refreshInterval.pause; + $scope.onRefreshChange({ + isPaused: savedQuery.attributes.timefilter.refreshInterval.pause, + refreshInterval: savedQuery.attributes.timefilter.refreshInterval.value + }); } onQueryChange({ filters: savedQuery.attributes.filters || [], From 4d6a62ce06400da9cd87e654b7e39a7e58b95e48 Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Wed, 4 Sep 2019 11:40:22 -0700 Subject: [PATCH 13/15] Removes redundant trigger of onQuerySubmit call in the search bar --- .../public/search/search_bar/components/search_bar.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx index e19269d8ae14b..d3fcbde47e04f 100644 --- a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx +++ b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx @@ -265,16 +265,6 @@ class SearchBarUI extends Component { if (this.props.onSaved) { this.props.onSaved(response); } - - if (this.props.onQuerySubmit) { - this.props.onQuerySubmit({ - query: this.state.query, - dateRange: { - from: this.state.dateRangeFrom, - to: this.state.dateRangeTo, - }, - }); - } } catch (error) { toastNotifications.addDanger(`An error occured while saving your query: ${error.message}`); throw error; From 1b8333f701c1512cd514f7356987f7e7b2b4271c Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Wed, 4 Sep 2019 14:20:19 -0700 Subject: [PATCH 14/15] deletes redundant call to updateStateFromSavedQuery in state.savedQuery watcher --- x-pack/legacy/plugins/maps/public/angular/map_controller.js | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index 5a631294f0398..a4c424e8a7bda 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -192,7 +192,6 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta savedQueryService.getSavedQuery(newSavedQueryId).then((savedQuery) => { $scope.$evalAsync(() => { $scope.savedQuery = savedQuery; - updateStateFromSavedQuery(savedQuery); }); }); }); From 72e9d7d17096b6b26f8ca8ce40fa67f6c5a5816e Mon Sep 17 00:00:00 2001 From: Christiane Heiligers Date: Thu, 5 Sep 2019 07:47:55 -0700 Subject: [PATCH 15/15] Refactors savedQuery watchers in map controller --- .../maps/public/angular/map_controller.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index a4c424e8a7bda..b22956156980e 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -174,14 +174,11 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta } } - $scope.$watch('savedQuery', (newSavedQuery, oldSavedQuery) => { + $scope.$watch('savedQuery', (newSavedQuery) => { if (!newSavedQuery) return; $state.savedQuery = newSavedQuery.id; - - if (newSavedQuery.id === (oldSavedQuery && oldSavedQuery.id)) { - updateStateFromSavedQuery(newSavedQuery); - } + updateStateFromSavedQuery(newSavedQuery); }); $scope.$watch(() => $state.savedQuery, newSavedQueryId => { @@ -189,11 +186,14 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta $scope.savedQuery = undefined; return; } - savedQueryService.getSavedQuery(newSavedQueryId).then((savedQuery) => { - $scope.$evalAsync(() => { - $scope.savedQuery = savedQuery; + if ($scope.savedQuery && newSavedQueryId !== $scope.savedQuery.id) { + savedQueryService.getSavedQuery(newSavedQueryId).then((savedQuery) => { + $scope.$evalAsync(() => { + $scope.savedQuery = savedQuery; + updateStateFromSavedQuery(savedQuery); + }); }); - }); + } }); /* End of Saved Queries */ async function onQueryChange({ filters, query, time }) {