diff --git a/docs/management/dashboard_only_mode/images/advanced_dashboard_mode_role_setup.png b/docs/management/dashboard_only_mode/images/advanced_dashboard_mode_role_setup.png deleted file mode 100644 index 1e9600e4d4eb4..0000000000000 Binary files a/docs/management/dashboard_only_mode/images/advanced_dashboard_mode_role_setup.png and /dev/null differ diff --git a/docs/management/dashboard_only_mode/images/custom_dashboard_mode_role.png b/docs/management/dashboard_only_mode/images/custom_dashboard_mode_role.png deleted file mode 100644 index e9285ac914308..0000000000000 Binary files a/docs/management/dashboard_only_mode/images/custom_dashboard_mode_role.png and /dev/null differ diff --git a/docs/management/dashboard_only_mode/images/dashboard-only-user-role.png b/docs/management/dashboard_only_mode/images/dashboard-only-user-role.png deleted file mode 100644 index 0773f0f3a3407..0000000000000 Binary files a/docs/management/dashboard_only_mode/images/dashboard-only-user-role.png and /dev/null differ diff --git a/docs/management/dashboard_only_mode/images/view_only_dashboard.png b/docs/management/dashboard_only_mode/images/view_only_dashboard.png deleted file mode 100644 index a82a09c27e6e8..0000000000000 Binary files a/docs/management/dashboard_only_mode/images/view_only_dashboard.png and /dev/null differ diff --git a/docs/management/dashboard_only_mode/index.asciidoc b/docs/management/dashboard_only_mode/index.asciidoc deleted file mode 100644 index 030a006646020..0000000000000 --- a/docs/management/dashboard_only_mode/index.asciidoc +++ /dev/null @@ -1,84 +0,0 @@ -[role="xpack"] -[[xpack-dashboard-only-mode]] -== Dashboard-only mode - -deprecated[7.4.0, "Using the `kibana_dashboard_only_user` role is deprecated. Use <> instead."] - -In dashboard-only mode, users have access to only the *Dashboard* app. -Users can view and filter the dashboards, but cannot create, edit, or delete -them. This enables you to: - -* Show off your dashboards without giving users access to all of {kib} - -* Share your {kib} dashboards without the risk of users accidentally -editing or deleting them - -Dashboard-only mode pairs well with fullscreen mode. -You can share your dashboard with the team responsible -for showing the dashboard on a big-screen monitor, and not worry about it being modified. - -[role="screenshot"] -image:management/dashboard_only_mode/images/view_only_dashboard.png["View Only Dashboard"] - -[[setup-dashboard-only-mode]] -[float] -=== Assign dashboard-only mode -With {security} enabled, you can restrict users to dashboard-only mode by assigning -them the built-in `kibana_dashboard_only_user` role. - -. Go to *Management > Security > Users*. -. Create or edit a user. -. Assign the `kibana_dashboard_only_user` role and a role that <>. -+ -For example, -to enable users to view the dashboards in the sample data sets, you must assign them -the `kibana_dashboard_only_user` role and a role that has -`read` access to the kibana_* indices. -+ -[role="screenshot"] -image:management/dashboard_only_mode/images/dashboard-only-user-role.png["Dashboard Only mode has no editing controls"] - -[IMPORTANT] -=========================================== -* If you assign users the `kibana_dashboard_only_user` role and a role -with write permissions to {kib}, they *will* have write access, -even though the controls remain hidden in {kib}. - -* If you also assign users the reserved `superuser` role, they will have full -access to {kib}. - -=========================================== - -[float] -[[grant-read-access-to-indices]] -=== Grant read access to indices - -The `kibana_dashboard_only_user` role -does not provide access to data indices. -You must also assign the user a role that grants `read` access -to each index you are using. Use *Management > Security > Roles* to create or edit a -role and assign index privileges. -For information on roles and privileges, see {ref}/authorization.html[User authorization]. - -[role="screenshot"] -image:management/dashboard_only_mode/images/custom_dashboard_mode_role.png["Dashboard Only mode has no editing controls"] - - -[float] -[[advanced-dashboard-mode-configuration]] -=== Advanced settings for dashboard only mode - -The `kibana_dashboard_only_user` role grants access to all spaces. -If your setup requires access to a -subset of spaces, you can create a custom role, and then tag it as Dashboard only mode. - -. Go to *Management > Advanced Settings*, and search for `xpackDashboardMode:roles`. -+ -By -default, this is set to -`kibana_dashboard_only_user`. - -. Add as many roles as you require. -+ -[role="screenshot"] -image:management/dashboard_only_mode/images/advanced_dashboard_mode_role_setup.png["Advanced dashboard mode role setup"] diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index 6fe45235dd882..bb34c4e442856 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -55,3 +55,9 @@ This page has moved. Please see {stack-ov}/create-jobs.html#job-tips[Machine lea == Extend your use case This page was deleted. See <> and <>. + +[role="exclude",id="xpack-dashboard-only-mode"] +== Dashboard-only mode + +Using the `kibana_dashboard_only_user` role is deprecated. +Use <> instead. diff --git a/docs/user/dashboard.asciidoc b/docs/user/dashboard.asciidoc index da3bea264f6a6..35a0364d380e8 100644 --- a/docs/user/dashboard.asciidoc +++ b/docs/user/dashboard.asciidoc @@ -154,7 +154,6 @@ To open an element for editing, put the dashboard in *Edit* mode, and then select *Edit* from the panel menu. The changes you make appear in every dashboard that uses the element. -include::{kib-repo-dir}/management/dashboard_only_mode/index.asciidoc[] diff --git a/docs/user/graph/configuring-graph.asciidoc b/docs/user/graph/configuring-graph.asciidoc index d521f9d8d2846..5427bdee79ecb 100644 --- a/docs/user/graph/configuring-graph.asciidoc +++ b/docs/user/graph/configuring-graph.asciidoc @@ -59,14 +59,14 @@ image::user/graph/images/graph-read-only-badge.png[Example of Graph's read only [discrete] [[disable-drill-down]] -=== Disabling drill down configuration +=== Disabling drilldown configuration -By default, users can configure _drill down_ URLs to display additional +By default, users can configure _drilldown_ URLs to display additional information about a selected vertex in a new browser window. For example, -you could configure a drill down URL to perform a web search for the selected +you could configure a drilldown URL to perform a web search for the selected vertex term. -To prevent users from adding drill down URLs, set +To prevent users from adding drilldown URLs, set `xpack.graph.canEditDrillDownUrls` to `false` in `kibana.yml`: [source,yaml] diff --git a/docs/user/graph/getting-started.asciidoc b/docs/user/graph/getting-started.asciidoc index 19f3df341338e..7b3bd10147966 100644 --- a/docs/user/graph/getting-started.asciidoc +++ b/docs/user/graph/getting-started.asciidoc @@ -2,30 +2,30 @@ [[graph-getting-started]] == Using Graph -Graph is automatically enabled in {es} and {kib}. +You must index data into {es} before you can create a graph. +<> or get started with a <>. +[float] [[exploring-connections]] -To start exploring connections in your data: +=== Graph connections in your data -. From the side navigation, open the graph explorer. - -. Select an index pattern to specify what indices you want to explore. +. From the side navigation, open *Graph*. + -For example, if you are indexing log data with Logstash, you could select the -`logstash-*` index pattern to visualize connections within the log entries. +If this is your first graph, follow the prompts to create it. +For subsequent graphs, click *New*. + +. Select a data source to explore. -. Select one or more multi-value fields that contain the terms you want to +. Add one or more multi-value fields that contain the terms you want to graph. + -The vertices in the graph are selected from these terms. If you're -visualizing connections between Apache log entries, you could select the -`url.raw` field and the `geo.src` field so you can look at which pages are -being accessed from different locations. +The vertices in the graph are selected from these terms. . Enter a search query to discover relationships between terms in the selected fields. + -For example, to generate a graph of the successful requests to +For example, if you are using the {kib} sample web logs data set, and you want +to generate a graph of the successful requests to particular pages from different locations, you could search for the 200 response code. The weight of the connection between two vertices indicates how strongly they are related. @@ -38,25 +38,86 @@ image::user/graph/images/graph-url-connections.png["URL connections"] [role="screenshot"] image::user/graph/images/graph-link-summary.png["Link summary"] -. Use the toolbar buttons to explore +. Use the control bar on the right to explore additional connections: + -* To display additional vertices that connect to your graph, click Expand -image:user/graph/images/graph-expand-button.jpg[Expand Selection]. +* To display additional vertices that connect to your graph, click the expand icon +image:user/graph/images/graph-expand-button.png[Expand Selection]. * To display additional -connections between the displayed vertices, click Link -image:user/graph/images/graph-link-button.jpg[Add links to existing terms] +connections between the displayed vertices, click the link icon +image:user/graph/images/graph-link-button.png[Add links to existing terms]. * To explore a particular area of the -graph, select the vertices you are interested in, and click Expand or Link. -* To step back through your changes to the graph, click Undo -image:user/graph/images/graph-undo-button.jpg[Undo]. +graph, select the vertices you are interested in, and then click expand or link. +* To step back through your changes to the graph, click undo +image:user/graph/images/graph-undo-button.png[Undo] and redo +image:user/graph/images/graph-redo-button.png[Redo]. . To see more relationships in your data, submit additional queries. + [role="screenshot"] image::user/graph/images/graph-add-query.png["Adding networks"] +. *Save* your graph. + +[float] +[[style-vertex-properties]] +=== Style vertex properties + +Each vertex has a color, icon, and label. To change +the color or icon of all vertices +of a certain field, click the field badge below the search bar, and then +select *Edit settings*. + +To change the color and label of selected vertices, +click the style icon image:user/graph/images/graph-style-button.png[Style] +in the control bar on the right. + + +[float] +[[edit-graph-settings]] +=== Edit graph settings + +By default, *Graph* is configured to tune out noise in your data. +If this isn't a good fit for your data, use *Settings > Advanced settings* +to adjust the way *Graph* queries your data. You can tune the graph to show +only the results relevant to you and to improve performance. +For more information, see <>. + +You can configure the number of vertices that a search or +expand operation adds to the graph. +By default, only the five most relevant terms for any given field are added +at a time. This keeps the graph from overflowing. To increase this number, click +a field below the search bar, select *Edit Settings*, and change *Terms per hop*. + +[float] +[[graph-block-terms]] +=== Block terms from the graph +Documents that match a blocked term are not allowed in the graph. +To block a term, select its vertex and click +the block icon +image:user/graph/images/graph-block-button.png[Block selection] +in the control panel. +For a list of blocked terms, go to *Settings > Blocked terms*. + +[float] +[[graph-drill-down]] +=== Drill down into raw documents +With drilldowns, you can display additional information about a +selected vertex in a new browser window. For example, you might +configure a drilldown URL to perform a web search for the selected vertex term. + +Use the drilldown icon image:user/graph/images/graph-info-icon.png[Drilldown selection] +in the control panel to show the drilldown buttons for the selected vertices. +To configure drilldowns, go to *Settings > Drilldowns*. See also +<>. -NOTE: By default, when you submit a search query, Graph searches all available -fields. You can constrain your search to a particular field using the Lucene -query syntax. For example, `machine.os: osx`. +[float] +[[graph-run-layout]] +=== Run and pause layout +Graph uses a "force layout", where vertices behave like magnets, +pushing off of one another. By default, when you add a new vertex to +the graph, all vertices begin moving. In some cases, the movement might +go on for some time. To freeze the current vertex position, +click the pause icon +image:user/graph/images/graph-pause-button.png[Block selection] +in the control panel. diff --git a/docs/user/graph/images/graph-add-query.png b/docs/user/graph/images/graph-add-query.png old mode 100644 new mode 100755 index 7f0cea7fb3aa4..0b978462ae75e Binary files a/docs/user/graph/images/graph-add-query.png and b/docs/user/graph/images/graph-add-query.png differ diff --git a/docs/user/graph/images/graph-block-button.png b/docs/user/graph/images/graph-block-button.png new file mode 100755 index 0000000000000..b378883572f3c Binary files /dev/null and b/docs/user/graph/images/graph-block-button.png differ diff --git a/docs/user/graph/images/graph-expand-button.jpg b/docs/user/graph/images/graph-expand-button.jpg deleted file mode 100644 index 296ba9d25ad5e..0000000000000 Binary files a/docs/user/graph/images/graph-expand-button.jpg and /dev/null differ diff --git a/docs/user/graph/images/graph-expand-button.png b/docs/user/graph/images/graph-expand-button.png new file mode 100755 index 0000000000000..7d9816a8adb93 Binary files /dev/null and b/docs/user/graph/images/graph-expand-button.png differ diff --git a/docs/user/graph/images/graph-info-icon.png b/docs/user/graph/images/graph-info-icon.png new file mode 100644 index 0000000000000..c1e89384b738c Binary files /dev/null and b/docs/user/graph/images/graph-info-icon.png differ diff --git a/docs/user/graph/images/graph-link-button.jpg b/docs/user/graph/images/graph-link-button.jpg deleted file mode 100644 index 7c7f177011576..0000000000000 Binary files a/docs/user/graph/images/graph-link-button.jpg and /dev/null differ diff --git a/docs/user/graph/images/graph-link-button.png b/docs/user/graph/images/graph-link-button.png new file mode 100755 index 0000000000000..43ac85537b9bb Binary files /dev/null and b/docs/user/graph/images/graph-link-button.png differ diff --git a/docs/user/graph/images/graph-link-summary.png b/docs/user/graph/images/graph-link-summary.png old mode 100644 new mode 100755 index e669a2d79e0e3..ca07f350f975e Binary files a/docs/user/graph/images/graph-link-summary.png and b/docs/user/graph/images/graph-link-summary.png differ diff --git a/docs/user/graph/images/graph-pause-button.png b/docs/user/graph/images/graph-pause-button.png new file mode 100755 index 0000000000000..e05418d7df7f9 Binary files /dev/null and b/docs/user/graph/images/graph-pause-button.png differ diff --git a/docs/user/graph/images/graph-redo-button.png b/docs/user/graph/images/graph-redo-button.png new file mode 100755 index 0000000000000..5adcfa478652e Binary files /dev/null and b/docs/user/graph/images/graph-redo-button.png differ diff --git a/docs/user/graph/images/graph-style-button.png b/docs/user/graph/images/graph-style-button.png new file mode 100644 index 0000000000000..5015e39b8095a Binary files /dev/null and b/docs/user/graph/images/graph-style-button.png differ diff --git a/docs/user/graph/images/graph-undo-button.jpg b/docs/user/graph/images/graph-undo-button.jpg deleted file mode 100644 index 5c87a2809a480..0000000000000 Binary files a/docs/user/graph/images/graph-undo-button.jpg and /dev/null differ diff --git a/docs/user/graph/images/graph-undo-button.png b/docs/user/graph/images/graph-undo-button.png new file mode 100755 index 0000000000000..e8a72b8b358c5 Binary files /dev/null and b/docs/user/graph/images/graph-undo-button.png differ diff --git a/docs/user/graph/images/graph-url-connections.png b/docs/user/graph/images/graph-url-connections.png old mode 100644 new mode 100755 index 737c081cd691b..94c9c4341d9b8 Binary files a/docs/user/graph/images/graph-url-connections.png and b/docs/user/graph/images/graph-url-connections.png differ diff --git a/docs/user/graph/troubleshooting.asciidoc b/docs/user/graph/troubleshooting.asciidoc index ff3568ed41afa..4ce287396f809 100644 --- a/docs/user/graph/troubleshooting.asciidoc +++ b/docs/user/graph/troubleshooting.asciidoc @@ -1,6 +1,6 @@ [role="xpack"] [[graph-troubleshooting]] -== Graph Troubleshooting +== Graph troubleshooting ++++ Troubleshooting ++++ diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx index b9825ceeecdb6..656b54040ad99 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx @@ -26,9 +26,6 @@ import { IInjector } from 'ui/chrome'; // @ts-ignore import * as filterActions from 'plugins/kibana/discover/doc_table/actions/filter'; -// @ts-ignore -import { getFilterGenerator } from 'ui/filter_manager'; - import { AppStateClass as TAppStateClass, AppState as TAppState, diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/_stubs.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/_stubs.js index f472ff9250eb5..b3d37083b37f7 100644 --- a/src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/_stubs.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/_stubs.js @@ -26,7 +26,8 @@ export function createIndexPatternsStub() { get: sinon.spy(indexPatternId => Promise.resolve({ id: indexPatternId, - isTimeNanosBased: () => false + isTimeNanosBased: () => false, + popularizeField: () => {}, }) ), }; diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_add_filter.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_add_filter.js index b136b03bd500b..5a445a65939ed 100644 --- a/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_add_filter.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_add_filter.js @@ -19,32 +19,33 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import sinon from 'sinon'; import { getServices } from '../../../../kibana_services'; import { createStateStub } from './_utils'; import { QueryParameterActionsProvider } from '../actions'; - +import { createIndexPatternsStub } from '../../api/__tests__/_stubs'; +import { npStart } from 'ui/new_platform'; describe('context app', function () { beforeEach(ngMock.module('kibana')); + beforeEach(ngMock.module(function createServiceStubs($provide) { + $provide.value('indexPatterns', createIndexPatternsStub()); + })); + describe('action addFilter', function () { - let filterManagerStub; let addFilter; beforeEach(ngMock.inject(function createPrivateStubs(Private) { - filterManagerStub = createQueryFilterStub(); - Private.stub(getServices().FilterBarQueryFilterProvider, filterManagerStub); - + Private.stub(getServices().FilterBarQueryFilterProvider); addFilter = Private(QueryParameterActionsProvider).addFilter; })); it('should pass the given arguments to the filterManager', function () { const state = createStateStub(); + const filterManagerAddStub = npStart.plugins.data.query.filterManager.addFilters; addFilter(state)('FIELD_NAME', 'FIELD_VALUE', 'FILTER_OPERATION'); - const filterManagerAddStub = filterManagerStub.addFilters; //get the generated filter const generatedFilter = filterManagerAddStub.firstCall.args[0][0]; const queryKeys = Object.keys(generatedFilter.query.match_phrase); @@ -55,20 +56,12 @@ describe('context app', function () { it('should pass the index pattern id to the filterManager', function () { const state = createStateStub(); + const filterManagerAddStub = npStart.plugins.data.query.filterManager.addFilters; addFilter(state)('FIELD_NAME', 'FIELD_VALUE', 'FILTER_OPERATION'); - const filterManagerAddStub = filterManagerStub.addFilters; const generatedFilter = filterManagerAddStub.firstCall.args[0][0]; - expect(filterManagerAddStub.calledOnce).to.be(true); expect(generatedFilter.meta.index).to.eql('INDEX_PATTERN_ID'); }); }); }); - -function createQueryFilterStub() { - return { - addFilters: sinon.stub(), - getAppFilters: sinon.stub(), - }; -} diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/actions.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/actions.js index 9f7b180e8fe7d..10fe6c0e2eda1 100644 --- a/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/actions.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/actions.js @@ -18,7 +18,8 @@ */ import _ from 'lodash'; -import { getServices, getFilterGenerator } from '../../../kibana_services'; +import { generateFilters } from '../../../../../../../../plugins/data/public'; +import { npStart } from 'ui/new_platform'; import { MAX_CONTEXT_SIZE, @@ -27,9 +28,8 @@ import { } from './constants'; -export function QueryParameterActionsProvider(indexPatterns, Private) { - const queryFilter = Private(getServices().FilterBarQueryFilterProvider); - const filterGen = getFilterGenerator(queryFilter); +export function QueryParameterActionsProvider(indexPatterns) { + const { filterManager } = npStart.plugins.data.query; const setPredecessorCount = (state) => (predecessorCount) => ( state.queryParameters.predecessorCount = clamp( @@ -55,13 +55,13 @@ export function QueryParameterActionsProvider(indexPatterns, Private) { ); const updateFilters = () => filters => { - queryFilter.setFilters(filters); + filterManager.setFilters(filters); }; const addFilter = (state) => async (field, values, operation) => { const indexPatternId = state.queryParameters.indexPatternId; - const newFilters = filterGen.generate(field, values, operation, indexPatternId); - queryFilter.addFilters(newFilters); + const newFilters = generateFilters(filterManager, field, values, operation, indexPatternId); + filterManager.addFilters(newFilters); const indexPattern = await indexPatterns.get(indexPatternId); indexPattern.popularizeField(field.name, 1); }; diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/angular/discover.js index 3a3f58ca83af0..8ee23bfb005a2 100644 --- a/src/legacy/core_plugins/kibana/public/discover/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/discover.js @@ -31,7 +31,6 @@ import './doc_table'; import { getSort } from './doc_table/lib/get_sort'; import { getSortForSearchSource } from './doc_table/lib/get_sort_for_search_source'; import * as columnActions from './doc_table/actions/columns'; -import * as filterActions from './doc_table/actions/filter'; import indexTemplate from './discover.html'; import { showOpenSearchPanel } from '../top_nav/show_open_search_panel'; @@ -41,7 +40,6 @@ import { getPainlessError } from './get_painless_error'; import { angular, buildVislibDimensions, - getFilterGenerator, getRequestInspectorStats, getResponseInspectorStats, getServices, @@ -76,7 +74,7 @@ const { import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../breadcrumbs'; import { extractTimeFilter, changeTimeFilter } from '../../../../data/public'; import { start as data } from '../../../../data/public/legacy'; - +import { generateFilters } from '../../../../../../plugins/data/public'; const { savedQueryService } = data.search.services; @@ -195,7 +193,6 @@ function discoverController( const shareContextMenuExtensions = Private(ShareContextMenuExtensionsRegistryProvider); const queryFilter = Private(FilterBarQueryFilterProvider); - const filterGen = getFilterGenerator(queryFilter); const inspectorAdapters = { requests: new RequestAdapter() @@ -900,7 +897,8 @@ function discoverController( // TODO: On array fields, negating does not negate the combination, rather all terms $scope.filterQuery = function (field, values, operation) { $scope.indexPattern.popularizeField(field, 1); - filterActions.addFilter(field, values, operation, $scope.indexPattern.id, $scope.state, filterGen); + const newFilters = generateFilters(queryFilter, field, values, operation, $scope.indexPattern.id); + return queryFilter.addFilters(newFilters); }; $scope.addColumn = function addColumn(columnName) { diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/actions/filter.js b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/actions/filter.js deleted file mode 100644 index 1f5db791469b9..0000000000000 --- a/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/actions/filter.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 { addFilter } from '../../actions/filter'; -import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import NoDigestPromises from 'test_utils/no_digest_promises'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import sinon from 'sinon'; - -function getFilterGeneratorStub() { - return { - add: sinon.stub() - }; -} - -describe('doc table filter actions', function () { - NoDigestPromises.activateForSuite(); - - let filterGen; - let indexPattern; - - beforeEach(ngMock.module( - 'kibana', - function ($provide) { - $provide.service('indexPatterns', require('fixtures/mock_index_patterns')); - } - )); - - beforeEach(ngMock.inject(function (Private) { - indexPattern = Private(StubbedLogstashIndexPatternProvider); - filterGen = getFilterGeneratorStub(); - })); - - describe('add', function () { - - it('should defer to the FilterManager when dealing with a lucene query', function () { - const state = { - query: { query: 'foo', language: 'lucene' } - }; - const args = ['foo', ['bar'], '+', indexPattern, ]; - addFilter('foo', ['bar'], '+', indexPattern, state, filterGen); - expect(filterGen.add.calledOnce).to.be(true); - expect(filterGen.add.calledWith(...args)).to.be(true); - }); - - }); - - -}); diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/actions/filter.js b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/actions/filter.js deleted file mode 100644 index 1a2854ec15412..0000000000000 --- a/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/actions/filter.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 function addFilter(field, values = [], operation, index, state, filterGen) { - if (!Array.isArray(values)) { - values = [values]; - } - - filterGen.add(field, values, operation, index); -} diff --git a/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts b/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts index d719864d99447..c575465a377e2 100644 --- a/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts +++ b/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts @@ -25,7 +25,9 @@ import { npStart } from 'ui/new_platform'; import { esFilters, TimeRange, + FilterManager, onlyDisabledFiltersChanged, + generateFilters, getTime, Query, } from '../../../../../../plugins/data/public'; @@ -43,7 +45,6 @@ import { getSortForSearchSource } from '../angular/doc_table/lib/get_sort_for_se import { Adapters, angular, - getFilterGenerator, getRequestInspectorStats, getResponseInspectorStats, getServices, @@ -72,18 +73,6 @@ interface SearchScope extends ng.IScope { isLoading?: boolean; } -export interface FilterManager { - generate: ( - field: { - name: string; - scripted: boolean; - }, - values: string | string[], - operation: string, - index: number - ) => esFilters.Filter[]; -} - interface SearchEmbeddableConfig { $rootScope: ng.IRootScopeService; $compile: ng.ICompileService; @@ -107,7 +96,7 @@ export class SearchEmbeddable extends Embeddable private autoRefreshFetchSubscription?: Subscription; private subscription?: Subscription; public readonly type = SEARCH_EMBEDDABLE_TYPE; - private filterGen: FilterManager; + private filterManager: FilterManager; private abortController?: AbortController; private prevTimeRange?: TimeRange; @@ -134,7 +123,7 @@ export class SearchEmbeddable extends Embeddable parent ); - this.filterGen = getFilterGenerator(queryFilter); + this.filterManager = queryFilter as FilterManager; this.savedSearch = savedSearch; this.$rootScope = $rootScope; this.$compile = $compile; @@ -251,7 +240,7 @@ export class SearchEmbeddable extends Embeddable }; searchScope.filter = async (field, value, operator) => { - let filters = this.filterGen.generate(field, value, operator, indexPattern.id); + let filters = generateFilters(this.filterManager, field, value, operator, indexPattern.id); filters = filters.map(filter => ({ ...filter, $state: { store: esFilters.FilterStateStore.APP_STATE }, diff --git a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts index a220cf59f6cf6..d0eb115e32676 100644 --- a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts @@ -84,8 +84,6 @@ export { angular }; export { buildVislibDimensions } from 'ui/visualize/loader/pipeline_helpers/build_pipeline'; // @ts-ignore export { callAfterBindingsWorkaround } from 'ui/compat'; -// @ts-ignore -export { getFilterGenerator } from 'ui/filter_manager'; export { getRequestInspectorStats, getResponseInspectorStats, diff --git a/src/legacy/ui/public/filter_manager/__tests__/filter_generator.js b/src/legacy/ui/public/filter_manager/__tests__/filter_generator.js deleted file mode 100644 index 5b6455bf20847..0000000000000 --- a/src/legacy/ui/public/filter_manager/__tests__/filter_generator.js +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 _ from 'lodash'; -import sinon from 'sinon'; -import MockState from 'fixtures/mock_state'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { getFilterGenerator } from '..'; -import { FilterBarQueryFilterProvider } from '../../filter_manager/query_filter'; -import { uniqFilters, esFilters } from '../../../../../plugins/data/public'; - -let queryFilter; -let filterGen; -let appState; - -function checkAddFilters(length, comps, idx) { - idx = idx || 0; - const filters = queryFilter.addFilters.getCall(idx).args[0]; - - expect(filters.length).to.be(length); - if (!Array.isArray(comps)) return; - comps.forEach(function (comp, i) { - expect(filters[i]).to.eql(comp); - }); -} - -describe('Filter Manager', function () { - beforeEach(ngMock.module( - 'kibana', - 'kibana/global_state', - function ($provide) { - $provide.service('indexPatterns', require('fixtures/mock_index_patterns')); - - appState = new MockState({ filters: [] }); - $provide.service('getAppState', function () { - return function () { return appState; }; - }); - } - )); - - beforeEach(ngMock.inject(function (_$rootScope_, Private) { - - // mock required queryFilter methods, used in the manager - queryFilter = Private(FilterBarQueryFilterProvider); - filterGen = getFilterGenerator(queryFilter); - sinon.stub(queryFilter, 'getAppFilters').callsFake(() => appState.filters); - sinon.stub(queryFilter, 'addFilters').callsFake((filters) => { - if (!Array.isArray(filters)) filters = [filters]; - appState.filters = uniqFilters(appState.filters.concat(filters)); - }); - })); - - it('should have an `add` function', function () { - expect(filterGen.add).to.be.a(Function); - }); - - it('should add a filter', function () { - filterGen.add('myField', 1, '+', 'myIndex'); - expect(queryFilter.addFilters.callCount).to.be(1); - checkAddFilters(1, [{ - meta: { index: 'myIndex', negate: false }, - query: { match_phrase: { myField: 1 } } - }]); - }); - - it('should add multiple filters if passed an array of values', function () { - filterGen.add('myField', [1, 2, 3], '+', 'myIndex'); - expect(queryFilter.addFilters.callCount).to.be(1); - checkAddFilters(3, [{ - meta: { index: 'myIndex', negate: false }, - query: { match_phrase: { myField: 1 } } - }, { - meta: { index: 'myIndex', negate: false }, - query: { match_phrase: { myField: 2 } } - }, { - meta: { index: 'myIndex', negate: false }, - query: { match_phrase: { myField: 3 } } - }]); - }); - - it('should add an exists filter if _exists_ is used as the field', function () { - filterGen.add('_exists_', 'myField', '+', 'myIndex'); - checkAddFilters(1, [{ - meta: { index: 'myIndex', negate: false }, - exists: { field: 'myField' } - }]); - }); - - it('should negate existing filter instead of added a conflicting filter', function () { - filterGen.add('myField', 1, '+', 'myIndex'); - checkAddFilters(1, [{ - meta: { index: 'myIndex', negate: false }, - query: { match_phrase: { myField: 1 } } - }], 0); - expect(appState.filters).to.have.length(1); - - // NOTE: negating exists filters also forces disabled to false - filterGen.add('myField', 1, '-', 'myIndex'); - checkAddFilters(1, [{ - meta: { index: 'myIndex', negate: true, disabled: false }, - query: { match_phrase: { myField: 1 } } - }], 1); - expect(appState.filters).to.have.length(1); - - filterGen.add('_exists_', 'myField', '+', 'myIndex'); - checkAddFilters(1, [{ - meta: { index: 'myIndex', negate: false }, - exists: { field: 'myField' } - }], 2); - expect(appState.filters).to.have.length(2); - - filterGen.add('_exists_', 'myField', '-', 'myIndex'); - checkAddFilters(1, [{ - meta: { index: 'myIndex', negate: true, disabled: false }, - exists: { field: 'myField' } - }], 3); - expect(appState.filters).to.have.length(2); - - const scriptedField = { name: 'scriptedField', scripted: true, script: 1, lang: 'painless' }; - filterGen.add(scriptedField, 1, '+', 'myIndex'); - checkAddFilters(1, [{ - meta: { index: 'myIndex', negate: false, field: 'scriptedField' }, - script: esFilters.getPhraseScript(scriptedField, 1) - }], 4); - expect(appState.filters).to.have.length(3); - - filterGen.add(scriptedField, 1, '-', 'myIndex'); - checkAddFilters(1, [{ - meta: { index: 'myIndex', negate: true, disabled: false, field: 'scriptedField' }, - script: esFilters.getPhraseScript(scriptedField, 1) - }], 5); - expect(appState.filters).to.have.length(3); - }); - - it('should enable matching filters being changed', function () { - _.each([true, false], function (negate) { - appState.filters = [{ - query: { match_phrase: { myField: 1 } }, - meta: { disabled: true, negate: negate } - }]; - expect(appState.filters.length).to.be(1); - expect(appState.filters[0].meta.disabled).to.be(true); - - filterGen.add('myField', 1, '+', 'myIndex'); - expect(appState.filters.length).to.be(1); - expect(appState.filters[0].meta.disabled).to.be(false); - }); - }); -}); diff --git a/src/legacy/ui/public/filter_manager/filter_generator.js b/src/legacy/ui/public/filter_manager/filter_generator.js deleted file mode 100644 index e11e0ff6653a7..0000000000000 --- a/src/legacy/ui/public/filter_manager/filter_generator.js +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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 _ from 'lodash'; -import { esFilters } from '../../../../plugins/data/public'; - -// Adds a filter to a passed state -export function getFilterGenerator(queryFilter) { - const filterGen = {}; - - filterGen.generate = (field, values, operation, index) => { - values = Array.isArray(values) ? values : [values]; - const fieldName = _.isObject(field) ? field.name : field; - const filters = _.flatten([queryFilter.getAppFilters()]); - const newFilters = []; - - const negate = (operation === '-'); - - // TODO: On array fields, negating does not negate the combination, rather all terms - _.each(values, function (value) { - let filter; - const existing = _.find(filters, function (filter) { - if (!filter) return; - - if (fieldName === '_exists_' && filter.exists) { - return filter.exists.field === value; - } - - if (esFilters.isPhraseFilter(filter)) { - return esFilters.getPhraseFilterField(filter) === fieldName && esFilters.getPhraseFilterValue(filter) === value; - } - - if (filter.script) { - return filter.meta.field === fieldName && filter.script.script.params.value === value; - } - }); - - if (existing) { - existing.meta.disabled = false; - if (existing.meta.negate !== negate) { - existing.meta.negate = !existing.meta.negate; - } - newFilters.push(existing); - return; - } - - switch (fieldName) { - case '_exists_': - filter = { - meta: { negate, index }, - exists: { - field: value - } - }; - break; - default: - if (field.scripted) { - filter = { - meta: { negate, index, field: fieldName }, - script: esFilters.getPhraseScript(field, value) - }; - } else { - filter = { meta: { negate, index }, query: { match_phrase: {} } }; - filter.query.match_phrase[fieldName] = value; - } - - break; - } - - newFilters.push(filter); - }); - - return newFilters; - }; - - filterGen.add = function (field, values, operation, index) { - const newFilters = this.generate(field, values, operation, index); - return queryFilter.addFilters(newFilters); - }; - - return filterGen; -} diff --git a/src/legacy/ui/public/filter_manager/index.js b/src/legacy/ui/public/filter_manager/index.js index 6adc4e0965ccd..ce99d4cac3017 100644 --- a/src/legacy/ui/public/filter_manager/index.js +++ b/src/legacy/ui/public/filter_manager/index.js @@ -17,4 +17,3 @@ * under the License. */ -export { getFilterGenerator } from './filter_generator'; diff --git a/src/plugins/data/public/query/filter_manager/index.ts b/src/plugins/data/public/query/filter_manager/index.ts index 7955cdd825ee6..ce7a479151797 100644 --- a/src/plugins/data/public/query/filter_manager/index.ts +++ b/src/plugins/data/public/query/filter_manager/index.ts @@ -22,3 +22,4 @@ export { FilterManager } from './filter_manager'; export { uniqFilters } from './lib/uniq_filters'; export { mapAndFlattenFilters } from './lib/map_and_flatten_filters'; export { onlyDisabledFiltersChanged } from './lib/only_disabled'; +export { generateFilters } from './lib/generate_filters'; diff --git a/src/plugins/data/public/query/filter_manager/lib/generate_filter.test.ts b/src/plugins/data/public/query/filter_manager/lib/generate_filter.test.ts new file mode 100644 index 0000000000000..46cf0fd9c111e --- /dev/null +++ b/src/plugins/data/public/query/filter_manager/lib/generate_filter.test.ts @@ -0,0 +1,130 @@ +/* + * 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 { generateFilters } from './generate_filters'; +import { FilterManager } from '../filter_manager'; +import { esFilters } from '../../..'; + +const INDEX_NAME = 'my-index'; +const EXISTS_FIELD_NAME = '_exists_'; +const FIELD = { + name: 'my-field', +}; +const PHRASE_VALUE = 'my-value'; + +describe('Generate filters', () => { + let mockFilterManager: FilterManager; + let filtersArray: esFilters.Filter[]; + + beforeEach(() => { + filtersArray = []; + mockFilterManager = { + getAppFilters: () => { + return filtersArray; + }, + } as FilterManager; + }); + + it('should create exists filter', () => { + const filters = generateFilters( + mockFilterManager, + EXISTS_FIELD_NAME, + FIELD.name, + '', + INDEX_NAME + ); + expect(filters).toHaveLength(1); + expect(filters[0].meta.index === INDEX_NAME); + expect(filters[0].meta.negate).toBeFalsy(); + expect(esFilters.isExistsFilter(filters[0])).toBeTruthy(); + }); + + it('should create negated exists filter', () => { + const filters = generateFilters( + mockFilterManager, + EXISTS_FIELD_NAME, + FIELD.name, + '-', + INDEX_NAME + ); + expect(filters).toHaveLength(1); + expect(filters[0].meta.index === INDEX_NAME); + expect(filters[0].meta.negate).toBeTruthy(); + expect(esFilters.isExistsFilter(filters[0])).toBeTruthy(); + }); + + it('should update and re-enable EXISTING exists filter', () => { + const filter = esFilters.buildExistsFilter(FIELD, { id: INDEX_NAME }); + filter.meta.disabled = true; + filtersArray.push(filter); + + const filters = generateFilters(mockFilterManager, '_exists_', FIELD.name, '-', INDEX_NAME); + expect(filters).toHaveLength(1); + expect(filters[0].meta.index === INDEX_NAME); + expect(filters[0].meta.negate).toBeTruthy(); + expect(filters[0].meta.disabled).toBeFalsy(); + expect(esFilters.isExistsFilter(filters[0])).toBeTruthy(); + }); + + it('should create phrase filter', () => { + const filters = generateFilters(mockFilterManager, FIELD, PHRASE_VALUE, '', INDEX_NAME); + expect(filters).toHaveLength(1); + expect(filters[0].meta.index === INDEX_NAME); + expect(filters[0].meta.negate).toBeFalsy(); + expect(esFilters.isPhraseFilter(filters[0])).toBeTruthy(); + expect((filters[0] as esFilters.PhraseFilter).query.match_phrase).toEqual({ + [FIELD.name]: PHRASE_VALUE, + }); + }); + + it('should create negated phrase filter', () => { + const filters = generateFilters(mockFilterManager, FIELD, PHRASE_VALUE, '-', INDEX_NAME); + expect(filters).toHaveLength(1); + expect(filters[0].meta.index === INDEX_NAME); + expect(filters[0].meta.negate).toBeTruthy(); + expect(esFilters.isPhraseFilter(filters[0])).toBeTruthy(); + expect((filters[0] as esFilters.PhraseFilter).query.match_phrase).toEqual({ + [FIELD.name]: PHRASE_VALUE, + }); + }); + + it('should create multiple phrase filters', () => { + const ANOTHER_PHRASE = 'another-value'; + const filters = generateFilters( + mockFilterManager, + FIELD, + [PHRASE_VALUE, ANOTHER_PHRASE], + '', + INDEX_NAME + ); + expect(filters).toHaveLength(2); + expect(filters[0].meta.index === INDEX_NAME); + expect(filters[0].meta.negate).toBeFalsy(); + expect(filters[1].meta.index === INDEX_NAME); + expect(filters[1].meta.negate).toBeFalsy(); + expect(esFilters.isPhraseFilter(filters[0])).toBeTruthy(); + expect(esFilters.isPhraseFilter(filters[1])).toBeTruthy(); + expect((filters[0] as esFilters.PhraseFilter).query.match_phrase).toEqual({ + [FIELD.name]: PHRASE_VALUE, + }); + expect((filters[1] as esFilters.PhraseFilter).query.match_phrase).toEqual({ + [FIELD.name]: ANOTHER_PHRASE, + }); + }); +}); diff --git a/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts b/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts new file mode 100644 index 0000000000000..5c4cdc2717338 --- /dev/null +++ b/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts @@ -0,0 +1,112 @@ +/* + * 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 _ from 'lodash'; +import { FilterManager, esFilters, Field } from '../../..'; + +function getExistingFilter( + appFilters: esFilters.Filter[], + fieldName: string, + value: any +): esFilters.Filter | undefined { + // TODO: On array fields, negating does not negate the combination, rather all terms + return _.find(appFilters, function(filter) { + if (!filter) return; + + if (fieldName === '_exists_' && esFilters.isExistsFilter(filter)) { + return filter.exists!.field === value; + } + + if (esFilters.isPhraseFilter(filter)) { + return ( + esFilters.getPhraseFilterField(filter) === fieldName && + esFilters.getPhraseFilterValue(filter) === value + ); + } + + if (esFilters.isScriptedPhraseFilter(filter)) { + return filter.meta.field === fieldName && filter.meta.script!.script.params.value === value; + } + }); +} + +function updateExistingFilter(existingFilter: esFilters.Filter, negate: boolean) { + existingFilter.meta.disabled = false; + if (existingFilter.meta.negate !== negate) { + existingFilter.meta.negate = !existingFilter.meta.negate; + } +} + +/** + * Generate filter objects, as a result of triggering a filter action on a + * specific index pattern field. + * + * @param {FilterManager} filterManager - The active filter manager to lookup for existing filters + * @param {Field | string} field - The field for which filters should be generated + * @param {any} values - One or more values to filter for. + * @param {string} operation - "-" to create a negated filter + * @param {string} index - Index string to generate filters for + * + * @returns {object} An array of filters to be added back to filterManager + */ +export function generateFilters( + filterManager: FilterManager, + field: Field | string, + values: any, + operation: string, + index: string +): esFilters.Filter[] { + values = Array.isArray(values) ? values : [values]; + const fieldObj = _.isObject(field) + ? field + : { + name: field, + }; + const fieldName = fieldObj.name; + const newFilters: esFilters.Filter[] = []; + const appFilters = filterManager.getAppFilters(); + + const negate = operation === '-'; + let filter; + + _.each(values, function(value) { + const existing = getExistingFilter(appFilters, fieldName, value); + + if (existing) { + updateExistingFilter(existing, negate); + filter = existing; + } else { + const tmpIndexPattern = { id: index }; + switch (fieldName) { + case '_exists_': + filter = esFilters.buildExistsFilter(fieldObj, tmpIndexPattern); + break; + default: + filter = esFilters.buildPhraseFilter(fieldObj, value, tmpIndexPattern); + break; + } + + filter.meta.negate = negate; + } + + newFilters.push(filter); + }); + + return newFilters; +} diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx b/x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx index 9cf2ddc3a22e3..d31e1024ebd40 100644 --- a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx +++ b/x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx @@ -100,7 +100,7 @@ describe('', () => { expect(center(wrapper).text()).toEqual('Page 6 of 28'); }); - test('autohide footer functions on mouseEnter + Leave', async () => { + test.skip('autohide footer functions on mouseEnter + Leave', async () => { const wrapper = getWrapper(); trigger(wrapper).simulate('click'); await tick(20); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx index 71807280ebcb4..e5ad39b814caa 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx @@ -140,10 +140,7 @@ const makeMapStateToProps = () => { }; export const NetworkHttpTable = compose>( - connect( - makeMapStateToProps, - { - updateNetworkTable: networkActions.updateNetworkTable, - } - ) + connect(makeMapStateToProps, { + updateNetworkTable: networkActions.updateNetworkTable, + }) )(NetworkHttpTableComponent); diff --git a/x-pack/legacy/plugins/siem/public/store/network/selectors.ts b/x-pack/legacy/plugins/siem/public/store/network/selectors.ts index 267a8039f9186..a33684472b279 100644 --- a/x-pack/legacy/plugins/siem/public/store/network/selectors.ts +++ b/x-pack/legacy/plugins/siem/public/store/network/selectors.ts @@ -79,11 +79,7 @@ const selectHttpByType = (state: State, networkType: NetworkType) => { ); }; -export const httpSelector = () => - createSelector( - selectHttpByType, - httpQueries => httpQueries - ); +export const httpSelector = () => createSelector(selectHttpByType, httpQueries => httpQueries); // IP Details Selectors export const ipDetailsFlowTargetSelector = () =>