From ce293db41b33f3a3ad1bfca1e36e2b556f76ece4 Mon Sep 17 00:00:00 2001 From: Yngrid Coello Date: Mon, 18 Dec 2023 18:08:54 +0100 Subject: [PATCH] [Dataset quality] Open in Log explorer action (#173272) Closes https://github.com/elastic/kibana/issues/170236. ### Changes This PR focuses on adding an action per dataset + namespace to navigate to Observability log explorer. At the same time I took the opportunity to update `Open in discover` link to include the controls present in `Observability Log Explorer` state (atm just `namespace`) 1. Extracted `getRouterLinkProps` to a new package for reusability. 2. New `Actions` column was added to table. 3. `LogExplorerLink ` component was introduced, to reuse the navigation logic between the table and the flyout. 4. `getDiscoverFiltersFromState` was added to combine state filters and controls into discover state when navigating to discover #### Demo https://github.com/elastic/kibana/assets/1313018/a3f38615-d8ae-432b-ba7b-05a6901f870c --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 1 + package.json | 1 + packages/kbn-router-utils/README.md | 34 +++++++++++ packages/kbn-router-utils/index.ts | 9 +++ packages/kbn-router-utils/jest.config.js | 13 ++++ packages/kbn-router-utils/kibana.jsonc | 5 ++ packages/kbn-router-utils/package.json | 6 ++ .../src/get_router_link_props/index.ts | 17 +++++- packages/kbn-router-utils/tsconfig.json | 19 ++++++ tsconfig.base.json | 2 + .../data_streams_stats/data_stream_stat.ts | 5 +- .../components/dataset_quality/columns.tsx | 31 +++++++--- .../public/components/log_explorer_link.tsx | 54 +++++++++++++++++ x-pack/plugins/dataset_quality/tsconfig.json | 4 +- .../sub_components/esql_selector.tsx | 2 +- .../public/controller/public_state.ts | 10 +--- .../log_explorer/public/controller/types.ts | 20 ++++--- x-pack/plugins/log_explorer/public/index.ts | 1 + .../utils/convert_discover_app_state.ts | 60 +++++++++++++++++++ x-pack/plugins/log_explorer/tsconfig.json | 3 +- .../public/components/discover_link.tsx | 9 ++- .../public/components/onboarding_link.tsx | 2 +- .../public/utils/get_router_link_props.ts | 35 ----------- .../observability_log_explorer/tsconfig.json | 3 +- yarn.lock | 4 ++ 25 files changed, 280 insertions(+), 70 deletions(-) create mode 100644 packages/kbn-router-utils/README.md create mode 100644 packages/kbn-router-utils/index.ts create mode 100644 packages/kbn-router-utils/jest.config.js create mode 100644 packages/kbn-router-utils/kibana.jsonc create mode 100644 packages/kbn-router-utils/package.json rename x-pack/plugins/log_explorer/public/utils/get_router_link_props.ts => packages/kbn-router-utils/src/get_router_link_props/index.ts (57%) create mode 100644 packages/kbn-router-utils/tsconfig.json create mode 100644 x-pack/plugins/dataset_quality/public/components/log_explorer_link.tsx delete mode 100644 x-pack/plugins/observability_log_explorer/public/utils/get_router_link_props.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2054c0a69c966..c89b584cfafb1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -627,6 +627,7 @@ x-pack/test/plugin_functional/plugins/resolver_test @elastic/security-solution examples/response_stream @elastic/ml-ui packages/kbn-rison @elastic/kibana-operations x-pack/plugins/rollup @elastic/platform-deployment-management +packages/kbn-router-utils @elastic/obs-ux-logs-team examples/routing_example @elastic/kibana-core packages/kbn-rrule @elastic/response-ops packages/kbn-rule-data-utils @elastic/security-detections-response @elastic/response-ops @elastic/obs-ux-management-team diff --git a/package.json b/package.json index 74fd129541df2..443dd5dbe8293 100644 --- a/package.json +++ b/package.json @@ -629,6 +629,7 @@ "@kbn/response-stream-plugin": "link:examples/response_stream", "@kbn/rison": "link:packages/kbn-rison", "@kbn/rollup-plugin": "link:x-pack/plugins/rollup", + "@kbn/router-utils": "link:packages/kbn-router-utils", "@kbn/routing-example-plugin": "link:examples/routing_example", "@kbn/rrule": "link:packages/kbn-rrule", "@kbn/rule-data-utils": "link:packages/kbn-rule-data-utils", diff --git a/packages/kbn-router-utils/README.md b/packages/kbn-router-utils/README.md new file mode 100644 index 0000000000000..e5dcb4cdb4fe4 --- /dev/null +++ b/packages/kbn-router-utils/README.md @@ -0,0 +1,34 @@ +# @kbn/router-utils + +This package provides util functions when working with the router. + +## getRouterLinkProps + +Useful to generate link component properties for HTML elements, this link properties will allow them to behave as native links and handle events such as open in a new tab, or client-side navigation without refreshing the whole page. + +### Example + +We want a button to both navigate to Discover client-side or open on a new window. + +```ts +const DiscoverLink = (discoverLinkParams) => { + const discoverUrl = discover.locator?.getRedirectUrl(discoverLinkParams); + + const navigateToDiscover = () => { + discover.locator?.navigate(discoverLinkParams); + }; + + const linkProps = getRouterLinkProps({ + href: discoverUrl, + onClick: navigateToDiscover, + }); + + return ( + <> + + {discoverLinkTitle} + + + ); +}; +``` diff --git a/packages/kbn-router-utils/index.ts b/packages/kbn-router-utils/index.ts new file mode 100644 index 0000000000000..f5ed5ed7e7604 --- /dev/null +++ b/packages/kbn-router-utils/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { getRouterLinkProps } from './src/get_router_link_props'; diff --git a/packages/kbn-router-utils/jest.config.js b/packages/kbn-router-utils/jest.config.js new file mode 100644 index 0000000000000..32497360f9419 --- /dev/null +++ b/packages/kbn-router-utils/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/packages/kbn-router-utils'], +}; diff --git a/packages/kbn-router-utils/kibana.jsonc b/packages/kbn-router-utils/kibana.jsonc new file mode 100644 index 0000000000000..c255dacb11c70 --- /dev/null +++ b/packages/kbn-router-utils/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/router-utils", + "owner": "@elastic/obs-ux-logs-team" +} diff --git a/packages/kbn-router-utils/package.json b/packages/kbn-router-utils/package.json new file mode 100644 index 0000000000000..d84ddd2c06bc2 --- /dev/null +++ b/packages/kbn-router-utils/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/router-utils", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" +} \ No newline at end of file diff --git a/x-pack/plugins/log_explorer/public/utils/get_router_link_props.ts b/packages/kbn-router-utils/src/get_router_link_props/index.ts similarity index 57% rename from x-pack/plugins/log_explorer/public/utils/get_router_link_props.ts rename to packages/kbn-router-utils/src/get_router_link_props/index.ts index a325df1a7e86f..f3def2e88650b 100644 --- a/x-pack/plugins/log_explorer/public/utils/get_router_link_props.ts +++ b/packages/kbn-router-utils/src/get_router_link_props/index.ts @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ interface GetRouterLinkPropsDeps { @@ -15,6 +16,18 @@ const isModifiedEvent = (event: React.MouseEvent) => const isLeftClickEvent = (event: React.MouseEvent) => event.button === 0; +/** + * + * getRouterLinkProps is an util that enable HTML elements, such buttons, to + * behave as links. + * @example + * const linkProps = getRouterLinkProps({ href: 'https://my-link', onClick: () => {console.log('click event')} }); + * My custom link + * @param href target url + * @param onClick onClick callback + * @returns An object that contains an href and a guardedClick handler that will + * manage behaviours such as leftClickEvent and event with modifiers (Ctrl, Shift, etc) + */ export const getRouterLinkProps = ({ href, onClick }: GetRouterLinkPropsDeps) => { const guardedClickHandler = (event: React.MouseEvent) => { if (event.defaultPrevented) { diff --git a/packages/kbn-router-utils/tsconfig.json b/packages/kbn-router-utils/tsconfig.json new file mode 100644 index 0000000000000..87f865132f4b4 --- /dev/null +++ b/packages/kbn-router-utils/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index e9afdd6428292..0d8e90ade3aeb 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1248,6 +1248,8 @@ "@kbn/rison/*": ["packages/kbn-rison/*"], "@kbn/rollup-plugin": ["x-pack/plugins/rollup"], "@kbn/rollup-plugin/*": ["x-pack/plugins/rollup/*"], + "@kbn/router-utils": ["packages/kbn-router-utils"], + "@kbn/router-utils/*": ["packages/kbn-router-utils/*"], "@kbn/routing-example-plugin": ["examples/routing_example"], "@kbn/routing-example-plugin/*": ["examples/routing_example/*"], "@kbn/rrule": ["packages/kbn-rrule"], diff --git a/x-pack/plugins/dataset_quality/common/data_streams_stats/data_stream_stat.ts b/x-pack/plugins/dataset_quality/common/data_streams_stats/data_stream_stat.ts index 88b6ed8d5c68b..0f48ae45aac7e 100644 --- a/x-pack/plugins/dataset_quality/common/data_streams_stats/data_stream_stat.ts +++ b/x-pack/plugins/dataset_quality/common/data_streams_stats/data_stream_stat.ts @@ -9,6 +9,7 @@ import { Integration } from './integration'; import { DataStreamStatType, IntegrationType } from './types'; export class DataStreamStat { + rawName: string; name: DataStreamStatType['name']; namespace: string; title: string; @@ -19,6 +20,7 @@ export class DataStreamStat { degradedDocs?: number; private constructor(dataStreamStat: DataStreamStat) { + this.rawName = dataStreamStat.name; this.name = dataStreamStat.name; this.title = dataStreamStat.title ?? dataStreamStat.name; this.namespace = dataStreamStat.namespace; @@ -33,7 +35,8 @@ export class DataStreamStat { const [_type, dataset, namespace] = dataStreamStat.name.split('-'); const dataStreamStatProps = { - name: dataStreamStat.name, + rawName: dataStreamStat.name, + name: dataset, title: dataStreamStat.integration?.datasets?.[dataset] ?? dataset, namespace, size: dataStreamStat.size, diff --git a/x-pack/plugins/dataset_quality/public/components/dataset_quality/columns.tsx b/x-pack/plugins/dataset_quality/public/components/dataset_quality/columns.tsx index d7b46f71531fe..cdda4dfa004b1 100644 --- a/x-pack/plugins/dataset_quality/public/components/dataset_quality/columns.tsx +++ b/x-pack/plugins/dataset_quality/public/components/dataset_quality/columns.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import React from 'react'; import { EuiBadge, EuiBasicTableColumn, @@ -16,17 +15,19 @@ import { EuiSkeletonRectangle, EuiToolTip, } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { PackageIcon } from '@kbn/fleet-plugin/public'; -import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; +import { PackageIcon } from '@kbn/fleet-plugin/public'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; import { DEGRADED_QUALITY_MINIMUM_PERCENTAGE, POOR_QUALITY_MINIMUM_PERCENTAGE, } from '../../../common/constants'; import { DataStreamStat } from '../../../common/data_streams_stats/data_stream_stat'; import loggingIcon from '../../icons/logging.svg'; +import { LogExplorerLink } from '../log_explorer_link'; import { QualityIndicator, QualityPercentageIndicator } from '../quality_indicator'; const nameColumnName = i18n.translate('xpack.datasetQuality.nameColumnName', { @@ -45,6 +46,17 @@ const degradedDocsColumnName = i18n.translate('xpack.datasetQuality.degradedDocs defaultMessage: 'Degraded Docs', }); +const lastActivityColumnName = i18n.translate('xpack.datasetQuality.lastActivityColumnName', { + defaultMessage: 'Last Activity', +}); + +const actionsColumnName = i18n.translate('xpack.datasetQuality.actionsColumnName', { + defaultMessage: 'Actions', +}); +const openActionName = i18n.translate('xpack.datasetQuality.openActionName', { + defaultMessage: 'Open', +}); + const degradedDocsDescription = (minimimPercentage: number) => i18n.translate('xpack.datasetQuality.degradedDocsQualityDescription', { defaultMessage: 'greater than {minimimPercentage}%', @@ -84,10 +96,6 @@ const degradedDocsColumnTooltip = ( /> ); -const lastActivityColumnName = i18n.translate('xpack.datasetQuality.lastActivityColumnName', { - defaultMessage: 'Last Activity', -}); - export const getDatasetQualitTableColumns = ({ fieldFormats, loadingDegradedStats, @@ -170,5 +178,12 @@ export const getDatasetQualitTableColumns = ({ .convert(timestamp), sortable: true, }, + { + name: actionsColumnName, + render: (dataStreamStat: DataStreamStat) => ( + + ), + width: '100px', + }, ]; }; diff --git a/x-pack/plugins/dataset_quality/public/components/log_explorer_link.tsx b/x-pack/plugins/dataset_quality/public/components/log_explorer_link.tsx new file mode 100644 index 0000000000000..11227d0a6bd3a --- /dev/null +++ b/x-pack/plugins/dataset_quality/public/components/log_explorer_link.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiLink } from '@elastic/eui'; +import React from 'react'; +import { getRouterLinkProps } from '@kbn/router-utils'; +import { + SingleDatasetLocatorParams, + SINGLE_DATASET_LOCATOR_ID, +} from '@kbn/deeplinks-observability'; +import { DataStreamStat } from '../../common/data_streams_stats/data_stream_stat'; +import { useKibanaContextForPlugin } from '../utils'; + +export const LogExplorerLink = React.memo( + ({ dataStreamStat, title }: { dataStreamStat: DataStreamStat; title: string }) => { + const { + services: { share }, + } = useKibanaContextForPlugin(); + const params: SingleDatasetLocatorParams = { + dataset: dataStreamStat.name, + timeRange: { + from: 'now-1d', + to: 'now', + }, + integration: dataStreamStat.integration?.name, + filterControls: { + namespace: { + mode: 'include', + values: [dataStreamStat.namespace], + }, + }, + }; + + const singleDatasetLocator = + share.url.locators.get(SINGLE_DATASET_LOCATOR_ID); + + const urlToLogExplorer = singleDatasetLocator?.getRedirectUrl(params); + + const navigateToLogExplorer = () => { + singleDatasetLocator?.navigate(params) as Promise; + }; + + const logExplorerLinkProps = getRouterLinkProps({ + href: urlToLogExplorer, + onClick: navigateToLogExplorer, + }); + + return {title}; + } +); diff --git a/x-pack/plugins/dataset_quality/tsconfig.json b/x-pack/plugins/dataset_quality/tsconfig.json index 5d1bf785b81ad..65f77bac100aa 100644 --- a/x-pack/plugins/dataset_quality/tsconfig.json +++ b/x-pack/plugins/dataset_quality/tsconfig.json @@ -25,7 +25,9 @@ "@kbn/field-types", "@kbn/io-ts-utils", "@kbn/observability-plugin", - "@kbn/es-types" + "@kbn/es-types", + "@kbn/deeplinks-observability", + "@kbn/router-utils", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/log_explorer/public/components/dataset_selector/sub_components/esql_selector.tsx b/x-pack/plugins/log_explorer/public/components/dataset_selector/sub_components/esql_selector.tsx index fec07114d939d..65ca1f1fd22e8 100644 --- a/x-pack/plugins/log_explorer/public/components/dataset_selector/sub_components/esql_selector.tsx +++ b/x-pack/plugins/log_explorer/public/components/dataset_selector/sub_components/esql_selector.tsx @@ -7,7 +7,7 @@ import { EuiBadge, EuiButton, EuiHorizontalRule } from '@elastic/eui'; import React from 'react'; -import { getRouterLinkProps } from '../../../utils/get_router_link_props'; +import { getRouterLinkProps } from '@kbn/router-utils'; import { DiscoverEsqlUrlProps } from '../../../hooks/use_esql'; import { technicalPreview, tryEsql } from '../constants'; diff --git a/x-pack/plugins/log_explorer/public/controller/public_state.ts b/x-pack/plugins/log_explorer/public/controller/public_state.ts index 04c12160a8809..5f4aad892bcb9 100644 --- a/x-pack/plugins/log_explorer/public/controller/public_state.ts +++ b/x-pack/plugins/log_explorer/public/controller/public_state.ts @@ -15,11 +15,7 @@ import { DEFAULT_CONTEXT, LogExplorerControllerContext, } from '../state_machines/log_explorer_controller'; -import { - LogExplorerPublicState, - LogExplorerPublicStateUpdate, - OptionsListControlOption, -} from './types'; +import { LogExplorerPublicState, LogExplorerPublicStateUpdate, OptionsListControl } from './types'; export const getPublicStateFromContext = ( context: LogExplorerControllerContext @@ -80,7 +76,7 @@ const getPublicControlsStateFromControlPanels = ( const getOptionsListPublicControlStateFromControlPanel = ( optionsListControlPanel: ControlPanels[string] -): OptionsListControlOption => ({ +): OptionsListControl => ({ mode: optionsListControlPanel.explicitInput.exclude ? 'exclude' : 'include', selection: optionsListControlPanel.explicitInput.existsSelected ? { type: 'exists' } @@ -113,7 +109,7 @@ const getControlPanelsFromPublicControlsState = ( const getControlPanelFromOptionsListPublicControlState = ( controlId: string, - publicControlState: OptionsListControlOption + publicControlState: OptionsListControl ): ControlPanels[string] => { const defaultControlPanelConfig = controlPanelConfigs[controlId]; diff --git a/x-pack/plugins/log_explorer/public/controller/types.ts b/x-pack/plugins/log_explorer/public/controller/types.ts index 50eb259d38cb3..5947051ad2518 100644 --- a/x-pack/plugins/log_explorer/public/controller/types.ts +++ b/x-pack/plugins/log_explorer/public/controller/types.ts @@ -41,19 +41,21 @@ export type LogExplorerDiscoverServices = Pick< }; export interface OptionsListControlOption { + type: 'options'; + selectedOptions: string[]; +} + +export interface OptionsListControlExists { + type: 'exists'; +} + +export interface OptionsListControl { mode: 'include' | 'exclude'; - selection: - | { - type: 'options'; - selectedOptions: string[]; - } - | { - type: 'exists'; - }; + selection: OptionsListControlOption | OptionsListControlExists; } export interface ControlOptions { - [availableControlsPanels.NAMESPACE]?: OptionsListControlOption; + [availableControlsPanels.NAMESPACE]?: OptionsListControl; } // we might want to wrap this into an object that has a "state value" laster diff --git a/x-pack/plugins/log_explorer/public/index.ts b/x-pack/plugins/log_explorer/public/index.ts index 005b5cca07a14..efd337234ffc6 100644 --- a/x-pack/plugins/log_explorer/public/index.ts +++ b/x-pack/plugins/log_explorer/public/index.ts @@ -21,6 +21,7 @@ export type { LogExplorerPluginSetup, LogExplorerPluginStart } from './types'; export { getDiscoverColumnsFromDisplayOptions, getDiscoverGridFromDisplayOptions, + getDiscoverFiltersFromState, } from './utils/convert_discover_app_state'; export function plugin(context: PluginInitializerContext) { diff --git a/x-pack/plugins/log_explorer/public/utils/convert_discover_app_state.ts b/x-pack/plugins/log_explorer/public/utils/convert_discover_app_state.ts index dea02a0bec002..90d51f75e8c7c 100644 --- a/x-pack/plugins/log_explorer/public/utils/convert_discover_app_state.ts +++ b/x-pack/plugins/log_explorer/public/utils/convert_discover_app_state.ts @@ -7,6 +7,8 @@ import { QueryState } from '@kbn/data-plugin/public'; import { DiscoverAppState } from '@kbn/discover-plugin/public'; +import { ExistsFilter, Filter, FILTERS, PhrasesFilter } from '@kbn/es-query'; +import { PhraseFilterValue } from '@kbn/es-query/src/filters/build_filters'; import { cloneDeep } from 'lodash'; import { ChartDisplayOptions, @@ -14,6 +16,7 @@ import { GridColumnDisplayOptions, GridRowsDisplayOptions, } from '../../common'; +import { ControlOptions, OptionsListControlOption } from '../controller'; export const getGridColumnDisplayOptionsFromDiscoverAppState = ( discoverAppState: DiscoverAppState @@ -71,3 +74,60 @@ export const getDiscoverGridFromDisplayOptions = ( return gridColumns; }, {}), }); + +const createDiscoverPhrasesFilter = ({ + key, + values, + negate, +}: { + values: PhraseFilterValue[]; + key: string; + negate?: boolean; +}): PhrasesFilter => + ({ + meta: { + key, + negate, + type: FILTERS.PHRASES, + params: values, + }, + query: { + bool: { + should: values.map((value) => ({ match_phrase: { [key]: value.toString() } })), + minimum_should_match: 1, + }, + }, + } as PhrasesFilter); + +const createDiscoverExistsFilter = ({ + key, + negate, +}: { + key: string; + negate?: boolean; +}): ExistsFilter => ({ + meta: { + key, + negate, + type: FILTERS.EXISTS, + }, + query: { exists: { field: key } }, +}); + +export const getDiscoverFiltersFromState = (filters: Filter[] = [], controls?: ControlOptions) => [ + ...filters, + ...(controls + ? (Object.keys(controls) as Array).map((key) => + controls[key as keyof ControlOptions]?.selection.type === 'exists' + ? createDiscoverExistsFilter({ + key, + negate: controls[key]?.mode === 'exclude', + }) + : createDiscoverPhrasesFilter({ + key, + values: (controls[key]?.selection as OptionsListControlOption).selectedOptions, + negate: controls[key]?.mode === 'exclude', + }) + ) + : []), +]; diff --git a/x-pack/plugins/log_explorer/tsconfig.json b/x-pack/plugins/log_explorer/tsconfig.json index 15f3a94065197..05cdd888eba1f 100644 --- a/x-pack/plugins/log_explorer/tsconfig.json +++ b/x-pack/plugins/log_explorer/tsconfig.json @@ -35,12 +35,13 @@ "@kbn/kibana-utils-plugin", "@kbn/navigation-plugin", "@kbn/react-field", + "@kbn/router-utils", "@kbn/share-plugin", "@kbn/unified-data-table", "@kbn/unified-doc-viewer", "@kbn/unified-field-list", "@kbn/unified-search-plugin", - "@kbn/xstate-utils" + "@kbn/xstate-utils", ], "exclude": [ "target/**/*" diff --git a/x-pack/plugins/observability_log_explorer/public/components/discover_link.tsx b/x-pack/plugins/observability_log_explorer/public/components/discover_link.tsx index 2d12de11731c0..d2195124bc292 100644 --- a/x-pack/plugins/observability_log_explorer/public/components/discover_link.tsx +++ b/x-pack/plugins/observability_log_explorer/public/components/discover_link.tsx @@ -9,7 +9,11 @@ import { EuiHeaderLink } from '@elastic/eui'; import { DiscoverAppLocatorParams } from '@kbn/discover-plugin/common'; import { DiscoverStart } from '@kbn/discover-plugin/public'; import { hydrateDatasetSelection } from '@kbn/log-explorer-plugin/common'; -import { getDiscoverColumnsFromDisplayOptions } from '@kbn/log-explorer-plugin/public'; +import { + getDiscoverColumnsFromDisplayOptions, + getDiscoverFiltersFromState, +} from '@kbn/log-explorer-plugin/public'; +import { getRouterLinkProps } from '@kbn/router-utils'; import { MatchedStateFromActor } from '@kbn/xstate-utils'; import { useActor } from '@xstate/react'; import React, { useMemo } from 'react'; @@ -18,7 +22,6 @@ import { ObservabilityLogExplorerService, useObservabilityLogExplorerPageStateContext, } from '../state_machines/observability_log_explorer/src'; -import { getRouterLinkProps } from '../utils/get_router_link_props'; import { useKibanaContextForPlugin } from '../utils/use_kibana'; export const ConnectedDiscoverLink = React.memo(() => { @@ -54,7 +57,7 @@ export const DiscoverLinkForValidState = React.memo( () => ({ breakdownField: logExplorerState.chart.breakdownField ?? undefined, columns: getDiscoverColumnsFromDisplayOptions(logExplorerState), - filters: logExplorerState.filters, + filters: getDiscoverFiltersFromState(logExplorerState.filters, logExplorerState.controls), query: logExplorerState.query, refreshInterval: logExplorerState.refreshInterval, timeRange: logExplorerState.time, diff --git a/x-pack/plugins/observability_log_explorer/public/components/onboarding_link.tsx b/x-pack/plugins/observability_log_explorer/public/components/onboarding_link.tsx index abdc585c22768..261405c766024 100644 --- a/x-pack/plugins/observability_log_explorer/public/components/onboarding_link.tsx +++ b/x-pack/plugins/observability_log_explorer/public/components/onboarding_link.tsx @@ -10,10 +10,10 @@ import { ObservabilityOnboardingLocatorParams, OBSERVABILITY_ONBOARDING_LOCATOR, } from '@kbn/deeplinks-observability/locators'; +import { getRouterLinkProps } from '@kbn/router-utils'; import { BrowserUrlService } from '@kbn/share-plugin/public'; import React from 'react'; import { onboardingLinkTitle } from '../../common/translations'; -import { getRouterLinkProps } from '../utils/get_router_link_props'; import { useKibanaContextForPlugin } from '../utils/use_kibana'; export const ConnectedOnboardingLink = React.memo(() => { diff --git a/x-pack/plugins/observability_log_explorer/public/utils/get_router_link_props.ts b/x-pack/plugins/observability_log_explorer/public/utils/get_router_link_props.ts deleted file mode 100644 index a325df1a7e86f..0000000000000 --- a/x-pack/plugins/observability_log_explorer/public/utils/get_router_link_props.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -interface GetRouterLinkPropsDeps { - href?: string; - onClick(): void; -} - -const isModifiedEvent = (event: React.MouseEvent) => - !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); - -const isLeftClickEvent = (event: React.MouseEvent) => event.button === 0; - -export const getRouterLinkProps = ({ href, onClick }: GetRouterLinkPropsDeps) => { - const guardedClickHandler = (event: React.MouseEvent) => { - if (event.defaultPrevented) { - return; - } - - if (isModifiedEvent(event) || !isLeftClickEvent(event)) { - return; - } - - // Prevent regular link behavior, which causes a browser refresh. - event.preventDefault(); - - onClick(); - }; - - return { href, onClick: guardedClickHandler }; -}; diff --git a/x-pack/plugins/observability_log_explorer/tsconfig.json b/x-pack/plugins/observability_log_explorer/tsconfig.json index be61fb9926a8c..0c03040b4203b 100644 --- a/x-pack/plugins/observability_log_explorer/tsconfig.json +++ b/x-pack/plugins/observability_log_explorer/tsconfig.json @@ -35,7 +35,8 @@ "@kbn/shared-ux-router", "@kbn/shared-ux-utility", "@kbn/ui-theme", - "@kbn/xstate-utils" + "@kbn/xstate-utils", + "@kbn/router-utils", ], "exclude": [ "target/**/*" diff --git a/yarn.lock b/yarn.lock index a1831fd6a1865..b5c49b37d930a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5431,6 +5431,10 @@ version "0.0.0" uid "" +"@kbn/router-utils@link:packages/kbn-router-utils": + version "0.0.0" + uid "" + "@kbn/routing-example-plugin@link:examples/routing_example": version "0.0.0" uid ""