diff --git a/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts b/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts index 17f3199b75b15b..e45f18606e3fc4 100644 --- a/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts +++ b/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts @@ -18,20 +18,15 @@ */ import { find, template } from 'lodash'; -import { stringify } from 'query-string'; import $ from 'jquery'; -import rison from 'rison-node'; -import '../../doc_viewer'; - import openRowHtml from './table_row/open.html'; import detailsHtml from './table_row/details.html'; - -import { dispatchRenderComplete, url } from '../../../../../../kibana_utils/public'; +import { dispatchRenderComplete } from '../../../../../../kibana_utils/public'; import { DOC_HIDE_TIME_COLUMN_SETTING } from '../../../../../common'; import cellTemplateHtml from '../components/table_row/cell.html'; import truncateByHeightTemplateHtml from '../components/table_row/truncate_by_height.html'; -import { esFilters } from '../../../../../../data/public'; import { getServices } from '../../../../kibana_services'; +import { getContextUrl } from '../../../helpers/get_context_url'; const TAGS_WITH_WS = />\s+ { - const globalFilters: any = getServices().filterManager.getGlobalFilters(); - const appFilters: any = getServices().filterManager.getAppFilters(); - - const hash = stringify( - url.encodeQuery({ - _g: rison.encode({ - filters: globalFilters || [], - }), - _a: rison.encode({ - columns: $scope.columns, - filters: (appFilters || []).map(esFilters.disableFilter), - }), - }), - { encode: false, sort: false } + return getContextUrl( + $scope.row._id, + $scope.indexPattern.id, + $scope.columns, + getServices().filterManager ); - - return `#/context/${encodeURIComponent($scope.indexPattern.id)}/${encodeURIComponent( - $scope.row._id - )}?${hash}`; }; // create a tr element that lists the value for each *column* diff --git a/src/plugins/discover/public/application/helpers/get_context_url.test.ts b/src/plugins/discover/public/application/helpers/get_context_url.test.ts new file mode 100644 index 00000000000000..481ea6b1a5b4f4 --- /dev/null +++ b/src/plugins/discover/public/application/helpers/get_context_url.test.ts @@ -0,0 +1,41 @@ +/* + * 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 { getContextUrl } from './get_context_url'; +import { FilterManager } from '../../../../data/public/query/filter_manager'; +const filterManager = ({ + getGlobalFilters: () => [], + getAppFilters: () => [], +} as unknown) as FilterManager; + +describe('Get context url', () => { + test('returning a valid context url', async () => { + const url = await getContextUrl('docId', 'ipId', ['test1', 'test2'], filterManager); + expect(url).toMatchInlineSnapshot( + `"#/context/ipId/docId?_g=(filters:!())&_a=(columns:!(test1,test2),filters:!())"` + ); + }); + + test('returning a valid context url when docId contains whitespace', async () => { + const url = await getContextUrl('doc Id', 'ipId', ['test1', 'test2'], filterManager); + expect(url).toMatchInlineSnapshot( + `"#/context/ipId/doc%20Id?_g=(filters:!())&_a=(columns:!(test1,test2),filters:!())"` + ); + }); +}); diff --git a/src/plugins/discover/public/application/helpers/get_context_url.tsx b/src/plugins/discover/public/application/helpers/get_context_url.tsx new file mode 100644 index 00000000000000..b159341cbe28d5 --- /dev/null +++ b/src/plugins/discover/public/application/helpers/get_context_url.tsx @@ -0,0 +1,52 @@ +/* + * 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 { stringify } from 'query-string'; +import rison from 'rison-node'; +import { url } from '../../../../kibana_utils/common'; +import { esFilters, FilterManager } from '../../../../data/public'; + +/** + * Helper function to generate an URL to a document in Discover's context view + */ +export function getContextUrl( + documentId: string, + indexPatternId: string, + columns: string[], + filterManager: FilterManager +) { + const globalFilters = filterManager.getGlobalFilters(); + const appFilters = filterManager.getAppFilters(); + + const hash = stringify( + url.encodeQuery({ + _g: rison.encode({ + filters: globalFilters || [], + }), + _a: rison.encode({ + columns, + filters: (appFilters || []).map(esFilters.disableFilter), + }), + }), + { encode: false, sort: false } + ); + + return `#/context/${encodeURIComponent(indexPatternId)}/${encodeURIComponent( + documentId + )}?${hash}`; +}