From c367b7b41c6bd81188e94ad1f35f32544c1faf00 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Thu, 17 Aug 2023 09:30:49 -0600 Subject: [PATCH 01/32] Make dashboard drilldown options a separate component --- .../navigation_embeddable_link_editor.tsx | 31 ++++-- .../dashboard_drilldown_option_toggles.tsx | 63 +++++++++++++ .../public/components/index.tsx | 4 + .../public/components/types.ts | 9 ++ .../i18n/dashboard_drilldown_config.tsx | 29 ++++++ src/plugins/presentation_util/public/index.ts | 3 +- .../drilldowns/dashboard_drilldown/types.ts | 8 +- .../plugins/dashboard_enhanced/kibana.jsonc | 8 +- .../components/collect_config_container.tsx | 31 ++---- .../dashboard_drilldown_config.tsx | 94 ++++++------------- .../dashboard_drilldown_config/i18n.ts | 21 ----- 11 files changed, 172 insertions(+), 129 deletions(-) create mode 100644 src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx create mode 100644 src/plugins/presentation_util/public/i18n/dashboard_drilldown_config.tsx diff --git a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx index f02e37806e396..fde30de13ae19 100644 --- a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx +++ b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx @@ -27,6 +27,11 @@ import { EuiRadioGroupOption, } from '@elastic/eui'; import { DashboardContainer } from '@kbn/dashboard-plugin/public/dashboard_container'; +import { + withSuspense, + DashboardDrilldownOptions, + LazyDashboardDrilldownOptionToggles, +} from '@kbn/presentation-util-plugin/public'; import { NavigationLinkType, @@ -40,6 +45,8 @@ import { NavigationEmbeddableUnorderedLink } from '../../editor/open_link_editor import { ExternalLinkDestinationPicker } from '../external_link/external_link_destination_picker'; import { DashboardLinkDestinationPicker } from '../dashboard_link/dashboard_link_destination_picker'; +const DashboardDrilldownOptionToggles = withSuspense(LazyDashboardDrilldownOptionToggles, null); + export const NavigationEmbeddableLinkEditor = ({ link, onSave, @@ -57,6 +64,11 @@ export const NavigationEmbeddableLinkEditor = ({ const [defaultLinkLabel, setDefaultLinkLabel] = useState(); const [currentLinkLabel, setCurrentLinkLabel] = useState(link?.label ?? ''); const [linkDestination, setLinkDestination] = useState(link?.destination); + const [linkOptions, setLinkOptions] = useState({ + openInNewTab: false, + useCurrentDateRange: true, + useCurrentFilters: true, + }); const linkTypes: EuiRadioGroupOption[] = useMemo(() => { return ([DASHBOARD_LINK_TYPE, EXTERNAL_LINK_TYPE] as NavigationLinkType[]).map((type) => { @@ -172,15 +184,18 @@ export const NavigationEmbeddableLinkEditor = ({ onChange={(e) => setCurrentLinkLabel(e.target.value)} /> - - {/* TODO: As part of https://github.com/elastic/kibana/issues/154381, we should pull in the custom settings for each link type. - Refer to `x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_to_discover_drilldown/collect_config_container.tsx` - for the dashboard drilldown settings, for example. - - Open question: It probably makes sense to re-use these components so any changes made to the drilldown architecture - trickle down to the navigation embeddable - this would require some refactoring, though. Is this a goal for MVP? - */} + + {selectedLinkType === DASHBOARD_LINK_TYPE ? ( + setLinkOptions({ ...linkOptions, ...change })} + /> + ) : ( + <>Link config + )} + + diff --git a/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx b/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx new file mode 100644 index 0000000000000..582ad269c86e8 --- /dev/null +++ b/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx @@ -0,0 +1,63 @@ +/* + * 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. + */ + +import React from 'react'; +import { EuiFormRow, EuiSwitch } from '@elastic/eui'; +import { DashboardDrilldownOptions } from '../types'; +import { dashboardDrilldownConfigStrings } from '../../i18n/dashboard_drilldown_config'; + +interface DashboardDrilldownOptionsProps { + options: DashboardDrilldownOptions; + onOptionChange: (newOptions: Partial) => void; +} + +const DashboardDrilldownOptionToggles = ({ + options, + onOptionChange, +}: DashboardDrilldownOptionsProps) => { + console.log('options', options); + + return ( + <> + {options.useCurrentFilters !== undefined && ( + + onOptionChange({ useCurrentFilters: !options.useCurrentFilters })} + /> + + )} + {options.useCurrentDateRange !== undefined && ( + + onOptionChange({ useCurrentDateRange: !options.useCurrentDateRange })} + /> + + )} + {options.openInNewTab !== undefined && ( + + onOptionChange({ openInNewTab: !options.openInNewTab })} + /> + + )} + + ); +}; + +// required for dynamic import using React.lazy() +// eslint-disable-next-line import/no-default-export +export default DashboardDrilldownOptionToggles; diff --git a/src/plugins/presentation_util/public/components/index.tsx b/src/plugins/presentation_util/public/components/index.tsx index fb66c9c5b2be6..5419a2569ea27 100644 --- a/src/plugins/presentation_util/public/components/index.tsx +++ b/src/plugins/presentation_util/public/components/index.tsx @@ -42,6 +42,10 @@ export const LazyDataViewPicker = React.lazy(() => import('./data_view_picker/da export const LazyFieldPicker = React.lazy(() => import('./field_picker/field_picker')); +export const LazyDashboardDrilldownOptionToggles = React.lazy( + () => import('./dashboard_drilldown_options/dashboard_drilldown_option_toggles') +); + export { FloatingActions } from './floating_actions/floating_actions'; /** diff --git a/src/plugins/presentation_util/public/components/types.ts b/src/plugins/presentation_util/public/components/types.ts index 4b996b3297180..c6b269383f0aa 100644 --- a/src/plugins/presentation_util/public/components/types.ts +++ b/src/plugins/presentation_util/public/components/types.ts @@ -71,3 +71,12 @@ export interface ExpressionInputProps onEditorDidMount?: OnExpressionInputEditorDidMount; } + +/** + * Dashboard drilldown options, which are each controlled by a toggle + */ +export type DashboardDrilldownOptions = { + useCurrentFilters: boolean; + useCurrentDateRange: boolean; + openInNewTab: boolean; +}; diff --git a/src/plugins/presentation_util/public/i18n/dashboard_drilldown_config.tsx b/src/plugins/presentation_util/public/i18n/dashboard_drilldown_config.tsx new file mode 100644 index 0000000000000..2bb326cb6f841 --- /dev/null +++ b/src/plugins/presentation_util/public/i18n/dashboard_drilldown_config.tsx @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; + +export const dashboardDrilldownConfigStrings = { + component: { + getUseCurrentFiltersLabel: () => + i18n.translate( + 'presentationUtil.dashboardDrilldownConfig.components.useCurrentFiltersLabel', + { + defaultMessage: 'Use filters and query from origin dashboard', + } + ), + getUseCurrentDateRange: () => + i18n.translate('presentationUtil.dashboardDrilldownConfig.components.useCurrentDateRange', { + defaultMessage: 'Use date range from origin dashboard', + }), + getOpenInNewTab: () => + i18n.translate('presentationUtil.dashboardDrilldownConfig.components.openInNewTab', { + defaultMessage: 'Open dashboard in new tab', + }), + }, +}; diff --git a/src/plugins/presentation_util/public/index.ts b/src/plugins/presentation_util/public/index.ts index f5994b3da82e2..5d45a3cec2500 100644 --- a/src/plugins/presentation_util/public/index.ts +++ b/src/plugins/presentation_util/public/index.ts @@ -25,7 +25,7 @@ export type { export { PluginServices, PluginServiceProvider, PluginServiceRegistry } from './services/create'; export type { PresentationUtilPluginSetup, PresentationUtilPluginStart } from './types'; -export type { SaveModalDashboardProps } from './components/types'; +export type { SaveModalDashboardProps, DashboardDrilldownOptions } from './components/types'; export { LazyExpressionInput, @@ -33,6 +33,7 @@ export { LazyLabsFlyout, LazyDashboardPicker, LazySavedObjectSaveModalDashboard, + LazyDashboardDrilldownOptionToggles, withSuspense, LazyDataViewPicker, LazyFieldPicker, diff --git a/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts b/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts index ee68681ccc8f5..2a73a68100880 100644 --- a/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts +++ b/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts @@ -5,10 +5,8 @@ * 2.0. */ -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public/'; + export type DrilldownConfig = { dashboardId?: string; - useCurrentFilters: boolean; - useCurrentDateRange: boolean; - openInNewTab: boolean; -}; +} & DashboardDrilldownOptions; diff --git a/x-pack/plugins/dashboard_enhanced/kibana.jsonc b/x-pack/plugins/dashboard_enhanced/kibana.jsonc index 30b70b7c9067f..88bb64bb00503 100644 --- a/x-pack/plugins/dashboard_enhanced/kibana.jsonc +++ b/x-pack/plugins/dashboard_enhanced/kibana.jsonc @@ -6,10 +6,7 @@ "id": "dashboardEnhanced", "server": true, "browser": true, - "configPath": [ - "xpack", - "dashboardEnhanced" - ], + "configPath": ["xpack", "dashboardEnhanced"], "requiredPlugins": [ "dashboard", "data", @@ -23,7 +20,8 @@ "embeddableEnhanced", "kibanaReact", "kibanaUtils", - "imageEmbeddable" + "imageEmbeddable", + "presentationUtil" ] } } diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/collect_config_container.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/collect_config_container.tsx index 4a9818b3f23f5..682f879b86985 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/collect_config_container.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/collect_config_container.tsx @@ -14,6 +14,7 @@ import { DashboardDrilldownConfig } from './dashboard_drilldown_config'; import { txtDestinationDashboardNotFound } from './i18n'; import { Config } from '../types'; import { Params } from '../abstract_dashboard_drilldown'; +import { DrilldownConfig } from '../../../../../common/drilldowns/dashboard_drilldown/types'; const mergeDashboards = ( dashboards: Array>, @@ -80,13 +81,12 @@ export class CollectConfigContainer extends React.Component< return ( ) => { + onConfig({ ...config, ...changes }); + }} onDashboardSelect={(dashboardId) => { onConfig({ ...config, dashboardId }); if (this.state.error) { @@ -94,24 +94,7 @@ export class CollectConfigContainer extends React.Component< } }} onSearchChange={this.debouncedLoadDashboards} - onCurrentFiltersToggle={() => - onConfig({ - ...config, - useCurrentFilters: !config.useCurrentFilters, - }) - } - onKeepRangeToggle={() => - onConfig({ - ...config, - useCurrentDateRange: !config.useCurrentDateRange, - }) - } - onOpenInNewTab={() => - onConfig({ - ...config, - openInNewTab: !config.openInNewTab, - }) - } + dashboards={mergeDashboards(dashboards, selectedDashboard)} /> ); } diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx index d6e00f7de0edb..57923da0bbc4a 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx @@ -6,93 +6,57 @@ */ import React from 'react'; -import { EuiFormRow, EuiSwitch, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import { EuiFormRow, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { - txtChooseDestinationDashboard, - txtUseCurrentFilters, - txtUseCurrentDateRange, - txtOpenInNewTab, -} from './i18n'; + LazyDashboardDrilldownOptionToggles, + withSuspense, +} from '@kbn/presentation-util-plugin/public'; + +import { txtChooseDestinationDashboard } from './i18n'; +import { DrilldownConfig } from '../../../../../../common/drilldowns/dashboard_drilldown/types'; + +const DashboardDrilldownOptionToggles = withSuspense(LazyDashboardDrilldownOptionToggles, null); export interface DashboardDrilldownConfigProps { - activeDashboardId?: string; - dashboards: Array>; - currentFilters?: boolean; - keepRange?: boolean; - openInNewTab?: boolean; - onDashboardSelect: (dashboardId: string) => void; - onCurrentFiltersToggle?: () => void; - onKeepRangeToggle?: () => void; - onOpenInNewTab?: () => void; - onSearchChange: (searchString: string) => void; - isLoading: boolean; error?: string; + isLoading: boolean; + config: DrilldownConfig; + onSearchChange: (searchString: string) => void; + onDashboardSelect: (dashboardId: string) => void; + dashboards: Array>; + onConfigChange: (changes: Partial) => void; } export const DashboardDrilldownConfig: React.FC = ({ - activeDashboardId, + error, + config, dashboards, - currentFilters, - keepRange, - openInNewTab, - onDashboardSelect, - onCurrentFiltersToggle, - onKeepRangeToggle, - onOpenInNewTab, - onSearchChange, isLoading, - error, + onConfigChange, + onSearchChange, + onDashboardSelect, }: DashboardDrilldownConfigProps) => { - const selectedTitle = dashboards.find((item) => item.value === activeDashboardId)?.label || ''; + const selectedTitle = dashboards.find((item) => item.value === config.dashboardId)?.label || ''; return ( <> async - selectedOptions={ - activeDashboardId ? [{ label: selectedTitle, value: activeDashboardId }] : [] - } + fullWidth + isInvalid={!!error} options={dashboards} - onChange={([{ value = '' } = { value: '' }]) => onDashboardSelect(value)} - onSearchChange={onSearchChange} isLoading={isLoading} + onSearchChange={onSearchChange} singleSelection={{ asPlainText: true }} - fullWidth data-test-subj={'dashboardDrilldownSelectDashboard'} - isInvalid={!!error} + onChange={([{ value = '' } = { value: '' }]) => onDashboardSelect(value)} + selectedOptions={ + config.dashboardId ? [{ label: selectedTitle, value: config.dashboardId }] : [] + } /> - {!!onCurrentFiltersToggle && ( - - - - )} - {!!onKeepRangeToggle && ( - - - - )} - {!!onOpenInNewTab && ( - - - - )} + ); }; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/i18n.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/i18n.ts index cf822a6a72d7a..5ee0794076348 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/i18n.ts +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/i18n.ts @@ -13,24 +13,3 @@ export const txtChooseDestinationDashboard = i18n.translate( defaultMessage: 'Choose destination dashboard', } ); - -export const txtUseCurrentFilters = i18n.translate( - 'xpack.dashboard.components.DashboardDrilldownConfig.useCurrentFilters', - { - defaultMessage: 'Use filters and query from origin dashboard', - } -); - -export const txtUseCurrentDateRange = i18n.translate( - 'xpack.dashboard.components.DashboardDrilldownConfig.useCurrentDateRange', - { - defaultMessage: 'Use date range from origin dashboard', - } -); - -export const txtOpenInNewTab = i18n.translate( - 'xpack.dashboard.components.DashboardDrilldownConfig.openInNewTab', - { - defaultMessage: 'Open dashboard in new tab', - } -); From 461feb9b60f0a475b5ba600f76e2727480caa90a Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Thu, 17 Aug 2023 10:11:24 -0600 Subject: [PATCH 02/32] Fix linting --- .../dashboard_drilldown_option_toggles.tsx | 2 -- .../common/drilldowns/dashboard_drilldown/types.ts | 12 ------------ .../abstract_dashboard_drilldown.tsx | 3 +-- .../drilldowns/abstract_dashboard_drilldown/types.ts | 8 +++++--- 4 files changed, 6 insertions(+), 19 deletions(-) delete mode 100644 x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts diff --git a/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx b/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx index 582ad269c86e8..8674b5c39e530 100644 --- a/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx +++ b/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx @@ -20,8 +20,6 @@ const DashboardDrilldownOptionToggles = ({ options, onOptionChange, }: DashboardDrilldownOptionsProps) => { - console.log('options', options); - return ( <> {options.useCurrentFilters !== undefined && ( diff --git a/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts b/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts deleted file mode 100644 index 2a73a68100880..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts +++ /dev/null @@ -1,12 +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. - */ - -import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public/'; - -export type DrilldownConfig = { - dashboardId?: string; -} & DashboardDrilldownOptions; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx index 9305d515bdcef..b89f95b92e583 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx @@ -15,10 +15,9 @@ import { UiActionsEnhancedDrilldownDefinition as Drilldown, } from '@kbn/ui-actions-enhanced-plugin/public'; import { CollectConfigProps, StartServicesGetter } from '@kbn/kibana-utils-plugin/public'; -import { DrilldownConfig } from '../../../../common/drilldowns/dashboard_drilldown/types'; import { CollectConfigContainer } from './components'; import { txtGoToDashboard } from './i18n'; -import { Config } from './types'; +import { DrilldownConfig as Config } from './types'; export interface Params { start: StartServicesGetter<{ diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts index 599ecce6217e2..28f00cc88a527 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts @@ -5,9 +5,11 @@ * 2.0. */ +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public/'; import { UiActionsEnhancedBaseActionFactoryContext } from '@kbn/ui-actions-enhanced-plugin/public'; -import { DrilldownConfig } from '../../../../common'; - -export type Config = DrilldownConfig; export type FactoryContext = UiActionsEnhancedBaseActionFactoryContext; + +export type DrilldownConfig = { + dashboardId?: string; +} & DashboardDrilldownOptions; From f7e830904c6997cffe0ec2284d04f952c6831834 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Thu, 17 Aug 2023 11:41:49 -0600 Subject: [PATCH 03/32] Rename the component --- .../navigation_embeddable_link_editor.tsx | 18 ++++++++++++++---- ...les.tsx => dashboard_drilldown_options.tsx} | 4 ++-- .../public/components/index.tsx | 4 ++-- src/plugins/presentation_util/public/index.ts | 2 +- .../dashboard_drilldown_config.tsx | 8 ++++---- 5 files changed, 23 insertions(+), 13 deletions(-) rename src/plugins/presentation_util/public/components/dashboard_drilldown_options/{dashboard_drilldown_option_toggles.tsx => dashboard_drilldown_options.tsx} (95%) diff --git a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx index fde30de13ae19..94f70f8734a19 100644 --- a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx +++ b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx @@ -27,10 +27,14 @@ import { EuiRadioGroupOption, } from '@elastic/eui'; import { DashboardContainer } from '@kbn/dashboard-plugin/public/dashboard_container'; +import { + UrlDrilldownCollectConfig, + UrlDrilldownConfig, +} from '@kbn/ui-actions-enhanced-plugin/public'; import { withSuspense, DashboardDrilldownOptions, - LazyDashboardDrilldownOptionToggles, + LazyDashboardDrilldownOptionsComponent, } from '@kbn/presentation-util-plugin/public'; import { @@ -45,7 +49,10 @@ import { NavigationEmbeddableUnorderedLink } from '../../editor/open_link_editor import { ExternalLinkDestinationPicker } from '../external_link/external_link_destination_picker'; import { DashboardLinkDestinationPicker } from '../dashboard_link/dashboard_link_destination_picker'; -const DashboardDrilldownOptionToggles = withSuspense(LazyDashboardDrilldownOptionToggles, null); +const DashboardDrilldownOptionsComponent = withSuspense( + LazyDashboardDrilldownOptionsComponent, + null +); export const NavigationEmbeddableLinkEditor = ({ link, @@ -70,6 +77,8 @@ export const NavigationEmbeddableLinkEditor = ({ useCurrentFilters: true, }); + // | UrlDrilldownConfig + const linkTypes: EuiRadioGroupOption[] = useMemo(() => { return ([DASHBOARD_LINK_TYPE, EXTERNAL_LINK_TYPE] as NavigationLinkType[]).map((type) => { return { @@ -187,12 +196,13 @@ export const NavigationEmbeddableLinkEditor = ({ {selectedLinkType === DASHBOARD_LINK_TYPE ? ( - setLinkOptions({ ...linkOptions, ...change })} /> ) : ( - <>Link config + // + <>Config )} diff --git a/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx b/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_options.tsx similarity index 95% rename from src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx rename to src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_options.tsx index 8674b5c39e530..3f87a0f1bbda2 100644 --- a/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_option_toggles.tsx +++ b/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_options.tsx @@ -16,7 +16,7 @@ interface DashboardDrilldownOptionsProps { onOptionChange: (newOptions: Partial) => void; } -const DashboardDrilldownOptionToggles = ({ +const DashboardDrilldownOptionsComponent = ({ options, onOptionChange, }: DashboardDrilldownOptionsProps) => { @@ -58,4 +58,4 @@ const DashboardDrilldownOptionToggles = ({ // required for dynamic import using React.lazy() // eslint-disable-next-line import/no-default-export -export default DashboardDrilldownOptionToggles; +export default DashboardDrilldownOptionsComponent; diff --git a/src/plugins/presentation_util/public/components/index.tsx b/src/plugins/presentation_util/public/components/index.tsx index 5419a2569ea27..492ce1f1bb206 100644 --- a/src/plugins/presentation_util/public/components/index.tsx +++ b/src/plugins/presentation_util/public/components/index.tsx @@ -42,8 +42,8 @@ export const LazyDataViewPicker = React.lazy(() => import('./data_view_picker/da export const LazyFieldPicker = React.lazy(() => import('./field_picker/field_picker')); -export const LazyDashboardDrilldownOptionToggles = React.lazy( - () => import('./dashboard_drilldown_options/dashboard_drilldown_option_toggles') +export const LazyDashboardDrilldownOptionsComponent = React.lazy( + () => import('./dashboard_drilldown_options/dashboard_drilldown_options') ); export { FloatingActions } from './floating_actions/floating_actions'; diff --git a/src/plugins/presentation_util/public/index.ts b/src/plugins/presentation_util/public/index.ts index 5d45a3cec2500..eb874ff9ae6ce 100644 --- a/src/plugins/presentation_util/public/index.ts +++ b/src/plugins/presentation_util/public/index.ts @@ -33,11 +33,11 @@ export { LazyLabsFlyout, LazyDashboardPicker, LazySavedObjectSaveModalDashboard, - LazyDashboardDrilldownOptionToggles, withSuspense, LazyDataViewPicker, LazyFieldPicker, FloatingActions, + LazyDashboardDrilldownOptionsComponent, } from './components'; export { diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx index 57923da0bbc4a..c3f8c15f2955f 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx @@ -8,14 +8,14 @@ import React from 'react'; import { EuiFormRow, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { - LazyDashboardDrilldownOptionToggles, + LazyDashboardDrilldownOptionsComponent, withSuspense, } from '@kbn/presentation-util-plugin/public'; +import { DrilldownConfig } from '../../types'; import { txtChooseDestinationDashboard } from './i18n'; -import { DrilldownConfig } from '../../../../../../common/drilldowns/dashboard_drilldown/types'; -const DashboardDrilldownOptionToggles = withSuspense(LazyDashboardDrilldownOptionToggles, null); +const DashboardDrilldownOptions = withSuspense(LazyDashboardDrilldownOptionsComponent, null); export interface DashboardDrilldownConfigProps { error?: string; @@ -56,7 +56,7 @@ export const DashboardDrilldownConfig: React.FC = } /> - + ); }; From ec4b98e3d7ccdaa2b1e8eeb18c03448941c507d3 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Thu, 17 Aug 2023 13:57:13 -0600 Subject: [PATCH 04/32] Add URL options toggles --- .../navigation_embeddable_link_editor.tsx | 19 ++++--- .../url_drilldown/components/index.ts | 5 +- .../url_drilldown_collect_config/index.ts | 2 +- .../url_drilldown_collect_config/lazy.tsx | 15 +++++ .../url_drilldown_collect_config.tsx | 35 +++--------- .../url_drilldown_options.tsx | 56 +++++++++++++++++++ .../public/drilldowns/url_drilldown/index.ts | 9 ++- .../public/drilldowns/url_drilldown/types.ts | 7 ++- .../ui_actions_enhanced/public/index.ts | 2 + 9 files changed, 109 insertions(+), 41 deletions(-) create mode 100644 src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_options.tsx diff --git a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx index 94f70f8734a19..e8137fd9d78b1 100644 --- a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx +++ b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx @@ -7,7 +7,7 @@ */ import { v4 as uuidv4 } from 'uuid'; -import React, { useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { EuiForm, @@ -28,8 +28,8 @@ import { } from '@elastic/eui'; import { DashboardContainer } from '@kbn/dashboard-plugin/public/dashboard_container'; import { - UrlDrilldownCollectConfig, - UrlDrilldownConfig, + UrlDrilldownOptions, + UrlDrilldownOptionsComponent, } from '@kbn/ui-actions-enhanced-plugin/public'; import { withSuspense, @@ -71,13 +71,15 @@ export const NavigationEmbeddableLinkEditor = ({ const [defaultLinkLabel, setDefaultLinkLabel] = useState(); const [currentLinkLabel, setCurrentLinkLabel] = useState(link?.label ?? ''); const [linkDestination, setLinkDestination] = useState(link?.destination); - const [linkOptions, setLinkOptions] = useState({ + const [linkOptions, setLinkOptions] = useState({ openInNewTab: false, useCurrentDateRange: true, useCurrentFilters: true, }); - // | UrlDrilldownConfig + // useEffect(() => { + // console.log(linkOptions); + // }, [linkOptions]); const linkTypes: EuiRadioGroupOption[] = useMemo(() => { return ([DASHBOARD_LINK_TYPE, EXTERNAL_LINK_TYPE] as NavigationLinkType[]).map((type) => { @@ -197,12 +199,15 @@ export const NavigationEmbeddableLinkEditor = ({ {selectedLinkType === DASHBOARD_LINK_TYPE ? ( setLinkOptions({ ...linkOptions, ...change })} /> ) : ( // - <>Config + setLinkOptions({ ...linkOptions, ...change })} + /> )} diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/index.ts b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/index.ts index 4e73e9a43a9e2..b50b1fe96d46a 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/index.ts +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/index.ts @@ -6,4 +6,7 @@ * Side Public License, v 1. */ -export { UrlDrilldownCollectConfig } from './url_drilldown_collect_config'; +export { + UrlDrilldownCollectConfig, + UrlDrilldownOptionsComponent, +} from './url_drilldown_collect_config'; diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/index.ts b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/index.ts index fd96f908fda23..02a3097eb9d9e 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/index.ts +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/index.ts @@ -7,4 +7,4 @@ */ export type { UrlDrilldownCollectConfigProps } from './lazy'; -export { UrlDrilldownCollectConfig } from './lazy'; +export { UrlDrilldownCollectConfig, UrlDrilldownOptionsComponent } from './lazy'; diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/lazy.tsx b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/lazy.tsx index eb666d6151ece..cc2b6500de042 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/lazy.tsx +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/lazy.tsx @@ -7,6 +7,7 @@ */ import * as React from 'react'; +import { UrlDrilldownOptionsProps } from './url_drilldown_options'; import type { UrlDrilldownCollectConfigProps } from './url_drilldown_collect_config'; const UrlDrilldownCollectConfigLazy = React.lazy(() => @@ -24,3 +25,17 @@ export const UrlDrilldownCollectConfig: React.FC ); }; + +const UrlDrilldownOptionsComponentLazy = React.lazy(() => + import('./url_drilldown_options').then(({ UrlDrilldownOptionsComponent }) => ({ + default: UrlDrilldownOptionsComponent, + })) +); + +export const UrlDrilldownOptionsComponent: React.FC = (props) => { + return ( + + + + ); +}; diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_collect_config.tsx b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_collect_config.tsx index 0e4825dd58e50..0e5c2441b635e 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_collect_config.tsx +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_collect_config.tsx @@ -23,12 +23,10 @@ import './index.scss'; import { txtUrlTemplateSyntaxHelpLinkText, txtUrlTemplateLabel, - txtUrlTemplateOpenInNewTab, txtUrlTemplateAdditionalOptions, - txtUrlTemplateEncodeUrl, - txtUrlTemplateEncodeDescription, } from './i18n'; import { VariablePopover } from '../variable_popover'; +import { UrlDrilldownOptionsComponent } from './lazy'; export interface UrlDrilldownCollectConfigProps { config: UrlDrilldownConfig; @@ -114,31 +112,12 @@ export const UrlDrilldownCollectConfig: React.FC > - - onConfig({ ...config, openInNewTab: !config.openInNewTab })} - data-test-subj="urlDrilldownOpenInNewTab" - /> - - - - {txtUrlTemplateEncodeUrl} - - {txtUrlTemplateEncodeDescription} - - } - checked={config.encodeUrl ?? true} - onChange={() => onConfig({ ...config, encodeUrl: !(config.encodeUrl ?? true) })} - /> - + { + onConfig({ ...config, ...change }); + }} + /> diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_options.tsx b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_options.tsx new file mode 100644 index 0000000000000..e141c58fdb4eb --- /dev/null +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_options.tsx @@ -0,0 +1,56 @@ +/* + * 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. + */ + +import React from 'react'; +import { EuiFormRow, EuiSpacer, EuiSwitch, EuiTextColor } from '@elastic/eui'; +import { UrlDrilldownOptions } from '../../types'; +import { + txtUrlTemplateEncodeDescription, + txtUrlTemplateEncodeUrl, + txtUrlTemplateOpenInNewTab, +} from './i18n'; + +export interface UrlDrilldownOptionsProps { + options: UrlDrilldownOptions; + onOptionChange: (newOptions: Partial) => void; +} + +export const UrlDrilldownOptionsComponent = ({ + options, + onOptionChange, +}: UrlDrilldownOptionsProps) => { + return ( + <> + + onOptionChange({ openInNewTab: !options.openInNewTab })} + data-test-subj="urlDrilldownOpenInNewTab" + /> + + + + {txtUrlTemplateEncodeUrl} + + {txtUrlTemplateEncodeDescription} + + } + checked={options.encodeUrl ?? true} + onChange={() => onOptionChange({ encodeUrl: !(options.encodeUrl ?? true) })} + /> + + + ); +}; diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/index.ts b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/index.ts index 543546132a3a2..482f4a04f828d 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/index.ts +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/index.ts @@ -6,8 +6,13 @@ * Side Public License, v 1. */ -export type { UrlDrilldownConfig, UrlDrilldownGlobalScope, UrlDrilldownScope } from './types'; -export { UrlDrilldownCollectConfig } from './components'; +export type { + UrlDrilldownConfig, + UrlDrilldownGlobalScope, + UrlDrilldownOptions, + UrlDrilldownScope, +} from './types'; +export { UrlDrilldownCollectConfig, UrlDrilldownOptionsComponent } from './components'; export { validateUrlTemplate as urlDrilldownValidateUrlTemplate, validateUrl as urlDrilldownValidateUrl, diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts index 3566b6712c78d..1efc96352cf73 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts @@ -6,12 +6,15 @@ * Side Public License, v 1. */ -export type UrlDrilldownConfig = { - url: { format?: 'handlebars_v1'; template: string }; +export type UrlDrilldownOptions = { openInNewTab: boolean; encodeUrl?: boolean; }; +export type UrlDrilldownConfig = { + url: { format?: 'handlebars_v1'; template: string }; +} & UrlDrilldownOptions; + /** * URL drilldown has 3 sources for variables: global, context and event variables */ diff --git a/src/plugins/ui_actions_enhanced/public/index.ts b/src/plugins/ui_actions_enhanced/public/index.ts index b609c5807a562..abd1e1b01668f 100644 --- a/src/plugins/ui_actions_enhanced/public/index.ts +++ b/src/plugins/ui_actions_enhanced/public/index.ts @@ -44,11 +44,13 @@ export type { export type { UrlDrilldownConfig, UrlDrilldownGlobalScope, + UrlDrilldownOptions, UrlDrilldownScope, } from './drilldowns/url_drilldown'; export { urlDrilldownCompileUrl, UrlDrilldownCollectConfig, + UrlDrilldownOptionsComponent, urlDrilldownGlobalScopeProvider, urlDrilldownValidateUrl, urlDrilldownValidateUrlTemplate, From 3953b4f9df8604d95d14c2f003c58d8eded1a2e5 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Thu, 17 Aug 2023 15:34:47 -0600 Subject: [PATCH 05/32] Add `options` to links --- .../common/content_management/index.ts | 3 ++ .../content_management/v1/cm_services.ts | 19 ++++++++++++ .../common/content_management/v1/constants.ts | 17 ++++++++++ .../common/content_management/v1/index.ts | 3 ++ .../common/content_management/v1/types.ts | 5 +++ .../navigation_embeddable_link_editor.tsx | 31 ++++++++++++------- .../navigation_embeddable_panel_editor.tsx | 2 +- 7 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/plugins/navigation_embeddable/common/content_management/index.ts b/src/plugins/navigation_embeddable/common/content_management/index.ts index 7b26870c7ce53..05029ee9057e0 100644 --- a/src/plugins/navigation_embeddable/common/content_management/index.ts +++ b/src/plugins/navigation_embeddable/common/content_management/index.ts @@ -13,6 +13,7 @@ export type { NavigationEmbeddableContentType } from '../types'; export type { NavigationLinkType, NavigationLayoutType, + NavigationLinkOptions, NavigationEmbeddableLink, NavigationEmbeddableItem, NavigationEmbeddableCrudTypes, @@ -24,6 +25,8 @@ export { DASHBOARD_LINK_TYPE, NAV_VERTICAL_LAYOUT, NAV_HORIZONTAL_LAYOUT, + DEFAULT_URL_LINK_OPTIONS, + DEFAULT_DASHBOARD_LINK_OPTIONS, } from './latest'; export * as NavigationEmbeddableV1 from './v1'; diff --git a/src/plugins/navigation_embeddable/common/content_management/v1/cm_services.ts b/src/plugins/navigation_embeddable/common/content_management/v1/cm_services.ts index 3c9c7a1bb759c..29701247b2749 100644 --- a/src/plugins/navigation_embeddable/common/content_management/v1/cm_services.ts +++ b/src/plugins/navigation_embeddable/common/content_management/v1/cm_services.ts @@ -24,6 +24,25 @@ const navigationEmbeddableLinkSchema = schema.object({ destination: schema.string(), label: schema.maybe(schema.string()), order: schema.number(), + options: schema.maybe( + schema.oneOf([ + schema.object( + { + openInNewTab: schema.boolean(), + useCurrentFilters: schema.boolean(), + useCurrentDateRange: schema.boolean(), + }, + { unknowns: 'forbid' } + ), + schema.object( + { + openInNewTab: schema.boolean(), + encodeUrl: schema.maybe(schema.boolean()), + }, + { unknowns: 'forbid' } + ), + ]) + ), }); const navigationEmbeddableAttributesSchema = schema.object( diff --git a/src/plugins/navigation_embeddable/common/content_management/v1/constants.ts b/src/plugins/navigation_embeddable/common/content_management/v1/constants.ts index 70f1af5c0f69d..643a053ba6a98 100644 --- a/src/plugins/navigation_embeddable/common/content_management/v1/constants.ts +++ b/src/plugins/navigation_embeddable/common/content_management/v1/constants.ts @@ -6,12 +6,29 @@ * Side Public License, v 1. */ +import { UrlDrilldownOptions } from '@kbn/ui-actions-enhanced-plugin/public'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; + /** * Link types */ export const DASHBOARD_LINK_TYPE = 'dashboardLink'; export const EXTERNAL_LINK_TYPE = 'externalLink'; +/** + * Link options + */ +export const DEFAULT_DASHBOARD_LINK_OPTIONS: DashboardDrilldownOptions = { + openInNewTab: false, + useCurrentDateRange: true, + useCurrentFilters: true, +}; + +export const DEFAULT_URL_LINK_OPTIONS: UrlDrilldownOptions = { + encodeUrl: true, + openInNewTab: true, +}; + /** * Layout options */ diff --git a/src/plugins/navigation_embeddable/common/content_management/v1/index.ts b/src/plugins/navigation_embeddable/common/content_management/v1/index.ts index efda7e1cf696c..a8206fe23026c 100644 --- a/src/plugins/navigation_embeddable/common/content_management/v1/index.ts +++ b/src/plugins/navigation_embeddable/common/content_management/v1/index.ts @@ -11,6 +11,7 @@ export type { NavigationEmbeddableCrudTypes, NavigationEmbeddableAttributes, NavigationEmbeddableLink, + NavigationLinkOptions, NavigationLayoutType, NavigationLinkType, } from './types'; @@ -20,4 +21,6 @@ export { DASHBOARD_LINK_TYPE, NAV_VERTICAL_LAYOUT, NAV_HORIZONTAL_LAYOUT, + DEFAULT_URL_LINK_OPTIONS, + DEFAULT_DASHBOARD_LINK_OPTIONS, } from './constants'; diff --git a/src/plugins/navigation_embeddable/common/content_management/v1/types.ts b/src/plugins/navigation_embeddable/common/content_management/v1/types.ts index bb5c6c10c584b..9875b99946270 100644 --- a/src/plugins/navigation_embeddable/common/content_management/v1/types.ts +++ b/src/plugins/navigation_embeddable/common/content_management/v1/types.ts @@ -11,6 +11,8 @@ import type { SavedObjectCreateOptions, SavedObjectUpdateOptions, } from '@kbn/content-management-utils'; +import { UrlDrilldownOptions } from '@kbn/ui-actions-enhanced-plugin/public'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; import { NavigationEmbeddableContentType } from '../../types'; import { DASHBOARD_LINK_TYPE, @@ -35,12 +37,15 @@ export type NavigationEmbeddableCrudTypes = ContentManagementCrudTypes< */ export type NavigationLinkType = typeof DASHBOARD_LINK_TYPE | typeof EXTERNAL_LINK_TYPE; +export type NavigationLinkOptions = DashboardDrilldownOptions | UrlDrilldownOptions; + export interface NavigationEmbeddableLink { id: string; type: NavigationLinkType; destination: string; label?: string; order: number; + options?: NavigationLinkOptions; } export type NavigationLayoutType = typeof NAV_HORIZONTAL_LAYOUT | typeof NAV_VERTICAL_LAYOUT; diff --git a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx index e8137fd9d78b1..5efb76716274a 100644 --- a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx +++ b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx @@ -41,7 +41,10 @@ import { NavigationLinkType, EXTERNAL_LINK_TYPE, DASHBOARD_LINK_TYPE, + NavigationLinkOptions, NavigationEmbeddableLink, + DEFAULT_URL_LINK_OPTIONS, + DEFAULT_DASHBOARD_LINK_OPTIONS, } from '../../../common/content_management'; import { NavEmbeddableStrings } from '../navigation_embeddable_strings'; import { DashboardItem, NavigationLinkInfo } from '../../embeddable/types'; @@ -71,15 +74,9 @@ export const NavigationEmbeddableLinkEditor = ({ const [defaultLinkLabel, setDefaultLinkLabel] = useState(); const [currentLinkLabel, setCurrentLinkLabel] = useState(link?.label ?? ''); const [linkDestination, setLinkDestination] = useState(link?.destination); - const [linkOptions, setLinkOptions] = useState({ - openInNewTab: false, - useCurrentDateRange: true, - useCurrentFilters: true, - }); - - // useEffect(() => { - // console.log(linkOptions); - // }, [linkOptions]); + const [linkOptions, setLinkOptions] = useState( + link?.options ?? DEFAULT_DASHBOARD_LINK_OPTIONS + ); const linkTypes: EuiRadioGroupOption[] = useMemo(() => { return ([DASHBOARD_LINK_TYPE, EXTERNAL_LINK_TYPE] as NavigationLinkType[]).map((type) => { @@ -158,11 +155,17 @@ export const NavigationEmbeddableLinkEditor = ({ idSelected={selectedLinkType} onChange={(id) => { if (link?.type === id) { + setLinkOptions(link.options); setLinkDestination(link.destination); setCurrentLinkLabel(link.label ?? ''); } else { setLinkDestination(undefined); setCurrentLinkLabel(''); + if (id === DASHBOARD_LINK_TYPE) { + setLinkOptions(DEFAULT_DASHBOARD_LINK_OPTIONS); + } else { + setLinkOptions(DEFAULT_URL_LINK_OPTIONS); + } } setDefaultLinkLabel(undefined); setSelectedLinkType(id as NavigationLinkType); @@ -200,13 +203,16 @@ export const NavigationEmbeddableLinkEditor = ({ {selectedLinkType === DASHBOARD_LINK_TYPE ? ( setLinkOptions({ ...linkOptions, ...change })} + onOptionChange={(change) => + setLinkOptions({ ...(linkOptions as DashboardDrilldownOptions), ...change }) + } /> ) : ( - // setLinkOptions({ ...linkOptions, ...change })} + onOptionChange={(change) => + setLinkOptions({ ...(linkOptions as UrlDrilldownOptions), ...change }) + } /> )} @@ -230,6 +236,7 @@ export const NavigationEmbeddableLinkEditor = ({ type: selectedLinkType, id: link?.id ?? uuidv4(), destination: linkDestination, + options: linkOptions, }); onClose(); diff --git a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_panel_editor.tsx b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_panel_editor.tsx index 892b2f777d3c5..72f547446931b 100644 --- a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_panel_editor.tsx +++ b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_panel_editor.tsx @@ -205,7 +205,7 @@ const NavigationEmbeddablePanelEditor = ({ parentDashboard={parentDashboard} editLink={() => addOrEditLink(link)} deleteLink={() => deleteLink(link.id)} - dragHandleProps={provided.dragHandleProps} + dragHandleProps={provided.dragHandleProps ?? undefined} // casting `null` to `undefined` /> )} From c8d4ab5fecae06aee9fe9081f195a8be40417b39 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Mon, 21 Aug 2023 13:18:57 -0600 Subject: [PATCH 06/32] First draft of dashboard-to-dashboard links working --- .../locator/get_dashboard_locator_params.ts | 47 +++++++++++++ src/plugins/dashboard/public/index.ts | 1 + .../navigation_embeddable/kibana.jsonc | 9 ++- .../dashboard_link_component.tsx | 19 ++++- .../navigation_embeddable_link_editor.tsx | 2 +- .../public/services/link_service.ts | 70 +++++++++++++++++++ .../public/components/types.ts | 1 + .../abstract_dashboard_drilldown.tsx | 4 +- .../abstract_dashboard_drilldown/types.ts | 2 +- .../embeddable_to_dashboard_drilldown.tsx | 42 ++++------- 10 files changed, 155 insertions(+), 42 deletions(-) create mode 100644 src/plugins/dashboard/public/dashboard_app/locator/get_dashboard_locator_params.ts create mode 100644 src/plugins/navigation_embeddable/public/services/link_service.ts diff --git a/src/plugins/dashboard/public/dashboard_app/locator/get_dashboard_locator_params.ts b/src/plugins/dashboard/public/dashboard_app/locator/get_dashboard_locator_params.ts new file mode 100644 index 0000000000000..46c7acd79261e --- /dev/null +++ b/src/plugins/dashboard/public/dashboard_app/locator/get_dashboard_locator_params.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +import { isQuery, isTimeRange } from '@kbn/data-plugin/common'; +import { Filter, isFilterPinned, Query, TimeRange } from '@kbn/es-query'; +import { EmbeddableInput, IEmbeddable } from '@kbn/embeddable-plugin/public'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; + +import { DashboardAppLocatorParams } from './locator'; + +interface EmbeddableQueryInput extends EmbeddableInput { + query?: Query; + filters?: Filter[]; + timeRange?: TimeRange; +} + +export const getDashboardLocatorParams = ( + source: IEmbeddable, + options: DashboardDrilldownOptions +): Partial => { + const params: DashboardAppLocatorParams = {}; + + const input = source.getInput(); + if (isQuery(input.query) && options.useCurrentFilters) { + params.query = input.query; + } + + // if useCurrentDashboardDataRange is enabled, then preserve current time range + // if undefined is passed, then destination dashboard will figure out time range itself + // for brush event this time range would be overwritten + if (isTimeRange(input.timeRange) && options.useCurrentDateRange) { + params.timeRange = input.timeRange; + } + + // if useCurrentDashboardFilters enabled, then preserve all the filters (pinned, unpinned, and from controls) + // otherwise preserve only pinned + params.filters = options.useCurrentFilters + ? input.filters + : input.filters?.filter((f) => isFilterPinned(f)); + + return params; +}; diff --git a/src/plugins/dashboard/public/index.ts b/src/plugins/dashboard/public/index.ts index 0bfe5dfae8b4c..01395015d692e 100644 --- a/src/plugins/dashboard/public/index.ts +++ b/src/plugins/dashboard/public/index.ts @@ -30,6 +30,7 @@ export { type DashboardAppLocatorParams, cleanEmptyKeys, } from './dashboard_app/locator/locator'; +export { getDashboardLocatorParams } from './dashboard_app/locator/get_dashboard_locator_params'; export function plugin(initializerContext: PluginInitializerContext) { return new DashboardPlugin(initializerContext); diff --git a/src/plugins/navigation_embeddable/kibana.jsonc b/src/plugins/navigation_embeddable/kibana.jsonc index b74e4bbd6f330..8d90360be090e 100644 --- a/src/plugins/navigation_embeddable/kibana.jsonc +++ b/src/plugins/navigation_embeddable/kibana.jsonc @@ -12,12 +12,11 @@ "dashboard", "embeddable", "kibanaReact", - "presentationUtil" + "presentationUtil", + "uiActionsEnhanced", + "kibanaUtils" ], "optionalPlugins": ["triggersActionsUi"], - "requiredBundles": [ - "savedObjects" - ] + "requiredBundles": ["savedObjects"] } } - diff --git a/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx b/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx index 8259d98cce4b6..8da0ff0dbcdc3 100644 --- a/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx +++ b/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx @@ -11,14 +11,17 @@ import useAsync from 'react-use/lib/useAsync'; import React, { useMemo, useState } from 'react'; import { EuiButtonEmpty, EuiListGroupItem, EuiToolTip } from '@elastic/eui'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; import { DashboardContainer } from '@kbn/dashboard-plugin/public/dashboard_container'; import { - NavigationEmbeddableLink, - NavigationLayoutType, NAV_VERTICAL_LAYOUT, + NavigationLayoutType, + NavigationEmbeddableLink, + DEFAULT_DASHBOARD_LINK_OPTIONS, } from '../../../common/content_management'; import { fetchDashboard } from './dashboard_link_tools'; +import { clickLink } from '../../services/link_service'; import { DashboardLinkStrings } from './dashboard_link_strings'; import { useNavigationEmbeddable } from '../../embeddable/navigation_embeddable'; @@ -108,8 +111,18 @@ export const DashboardLinkComponent = ({ onClick={ link.destination === parentDashboardId ? undefined - : () => { + : (event) => { // TODO: As part of https://github.com/elastic/kibana/issues/154381, connect to drilldown + const options = link.options as DashboardDrilldownOptions; + clickLink(navEmbeddable, { + ...link, + options: { + ...DEFAULT_DASHBOARD_LINK_OPTIONS, + ...options, + openInNewTab: + options.openInNewTab || event.ctrlKey || event.metaKey || event.shiftKey, + }, + }); } } label={ diff --git a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx index 5efb76716274a..544be2e52d0d3 100644 --- a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx +++ b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx @@ -7,7 +7,7 @@ */ import { v4 as uuidv4 } from 'uuid'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { EuiForm, diff --git a/src/plugins/navigation_embeddable/public/services/link_service.ts b/src/plugins/navigation_embeddable/public/services/link_service.ts new file mode 100644 index 0000000000000..88e9314b31c3b --- /dev/null +++ b/src/plugins/navigation_embeddable/public/services/link_service.ts @@ -0,0 +1,70 @@ +/* + * 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. + */ + +import { + cleanEmptyKeys, + DashboardAppLocatorParams, + getDashboardLocatorParams, +} from '@kbn/dashboard-plugin/public'; +import { isFilterPinned } from '@kbn/es-query'; +import { KibanaLocation } from '@kbn/share-plugin/public'; +import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; + +import { + DASHBOARD_LINK_TYPE, + NavigationLinkOptions, + NavigationEmbeddableLink, + DEFAULT_DASHBOARD_LINK_OPTIONS, +} from '../../common/content_management'; +import { type NavigationEmbeddable } from '../embeddable'; +import { coreServices, dashboardServices } from './kibana_services'; + +export const clickLink = async ( + embeddable: NavigationEmbeddable, + link: NavigationEmbeddableLink & { options: NavigationLinkOptions } +) => { + if (link.type === DASHBOARD_LINK_TYPE) { + const params: DashboardAppLocatorParams = { + dashboardId: link.destination, + ...getDashboardLocatorParams( + embeddable, + (link.options as DashboardDrilldownOptions) ?? DEFAULT_DASHBOARD_LINK_OPTIONS + ), + }; + + console.log(params); + + const locator = dashboardServices.locator; // TODO: Make this a generic locator that is coming from the dashboard container through some sort of getter + if (locator) { + const { app, path, state }: KibanaLocation = + await locator.getLocation(params); + + if (link.options.openInNewTab) { + const url = coreServices.application.getUrlForApp(app, { + path: setStateToKbnUrl( + '_a', + cleanEmptyKeys({ + query: state.query, + filters: state.filters?.filter((f) => !isFilterPinned(f)), + }), + { useHash: false, storeInHashQuery: true }, + path + ), + absolute: true, + }); + window.open(url, '_blank'); + } else { + await coreServices.application.navigateToApp(app, { + path, + state, + }); + } + } + } +}; diff --git a/src/plugins/presentation_util/public/components/types.ts b/src/plugins/presentation_util/public/components/types.ts index c6b269383f0aa..b451cd776da19 100644 --- a/src/plugins/presentation_util/public/components/types.ts +++ b/src/plugins/presentation_util/public/components/types.ts @@ -75,6 +75,7 @@ export interface ExpressionInputProps /** * Dashboard drilldown options, which are each controlled by a toggle */ +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions export type DashboardDrilldownOptions = { useCurrentFilters: boolean; useCurrentDateRange: boolean; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx index b89f95b92e583..216402661ec35 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx @@ -55,9 +55,7 @@ export abstract class AbstractDashboardDrilldown >; - public readonly CollectConfig: React.FC< - CollectConfigProps - >; + public readonly CollectConfig: React.FC>; public readonly createConfig = () => ({ dashboardId: '', diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts index 28f00cc88a527..7cf7ea9ebb92c 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public/'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; import { UiActionsEnhancedBaseActionFactoryContext } from '@kbn/ui-actions-enhanced-plugin/public'; export type FactoryContext = UiActionsEnhancedBaseActionFactoryContext; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx index 468cbaf9940a9..0e8dc51944e2d 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx @@ -4,14 +4,16 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { type Filter, isFilterPinned, Query, TimeRange } from '@kbn/es-query'; +import { extractTimeRange, isFilterPinned } from '@kbn/es-query'; import type { KibanaLocation } from '@kbn/share-plugin/public'; -import { DashboardAppLocatorParams, cleanEmptyKeys } from '@kbn/dashboard-plugin/public'; +import { + cleanEmptyKeys, + DashboardAppLocatorParams, + getDashboardLocatorParams as getSourceParams, +} from '@kbn/dashboard-plugin/public'; import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public'; -import { APPLY_FILTER_TRIGGER, isQuery, isTimeRange } from '@kbn/data-plugin/public'; -import { extractTimeRange } from '@kbn/es-query'; +import { APPLY_FILTER_TRIGGER } from '@kbn/data-plugin/public'; import { ApplyGlobalFilterActionContext } from '@kbn/unified-search-plugin/public'; -import { IEmbeddable, EmbeddableInput } from '@kbn/embeddable-plugin/public'; import { EnhancedEmbeddableContext } from '@kbn/embeddable-enhanced-plugin/public'; import { IMAGE_CLICK_TRIGGER } from '@kbn/image-embeddable-plugin/public'; import { @@ -22,12 +24,6 @@ import { import { EMBEDDABLE_TO_DASHBOARD_DRILLDOWN } from './constants'; import { createExtract, createInject } from '../../../../common'; -interface EmbeddableQueryInput extends EmbeddableInput { - query?: Query; - filters?: Filter[]; - timeRange?: TimeRange; -} - type Context = EnhancedEmbeddableContext & ApplyGlobalFilterActionContext; export type Params = AbstractDashboardDrilldownParams; @@ -48,28 +44,16 @@ export class EmbeddableToDashboardDrilldown extends AbstractDashboardDrilldown { - const params: DashboardAppLocatorParams = { - dashboardId: config.dashboardId, - }; + let params: DashboardAppLocatorParams = { dashboardId: config.dashboardId }; if (context.embeddable) { - const embeddable = context.embeddable as IEmbeddable; - const input = embeddable.getInput(); - if (isQuery(input.query) && config.useCurrentFilters) params.query = input.query; - - // if useCurrentDashboardDataRange is enabled, then preserve current time range - // if undefined is passed, then destination dashboard will figure out time range itself - // for brush event this time range would be overwritten - if (isTimeRange(input.timeRange) && config.useCurrentDateRange) - params.timeRange = input.timeRange; - - // if useCurrentDashboardFilters enabled, then preserve all the filters (pinned, unpinned, and from controls) - // otherwise preserve only pinned - params.filters = config.useCurrentFilters - ? input.filters - : input.filters?.filter((f) => isFilterPinned(f)); + params = { + ...params, + ...getSourceParams(context.embeddable, config), + }; } + /** Get event params */ const { restOfFilters: filtersFromEvent, timeRange: timeRangeFromEvent } = extractTimeRange( context.filters, context.timeFieldName From 4712e57d60c27a4488adfc6503f760cfa4508395 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Mon, 21 Aug 2023 14:29:29 -0600 Subject: [PATCH 07/32] Fix linting --- .../locator/get_dashboard_locator_params.ts | 4 ++-- src/plugins/dashboard/public/index.ts | 2 +- .../common/content_management/v1/constants.ts | 4 ++-- .../common/content_management/v1/types.ts | 4 ++-- .../dashboard_link/dashboard_link_component.tsx | 9 ++++++--- .../editor/navigation_embeddable_link_editor.tsx | 8 +++----- .../public/services/link_service.ts | 8 +++----- src/plugins/navigation_embeddable/tsconfig.json | 4 ++++ src/plugins/presentation_util/common/index.ts | 10 ++++++++++ .../dashboard_drilldown_options.tsx | 4 ++-- .../presentation_util/public/components/types.ts | 10 ---------- src/plugins/presentation_util/public/index.ts | 2 +- src/plugins/ui_actions_enhanced/common/index.ts | 1 + src/plugins/ui_actions_enhanced/common/types.ts | 5 +++++ .../url_drilldown_collect_config.tsx | 10 +--------- .../url_drilldown_options.tsx | 2 +- .../public/drilldowns/url_drilldown/index.ts | 7 +------ .../public/drilldowns/url_drilldown/types.ts | 5 +---- src/plugins/ui_actions_enhanced/public/index.ts | 1 - .../dashboard_drilldown_config.tsx | 2 +- .../embeddable_to_dashboard_drilldown.tsx | 4 ++-- x-pack/plugins/dashboard_enhanced/tsconfig.json | 15 +++++---------- .../plugins/translations/translations/fr-FR.json | 3 --- .../plugins/translations/translations/ja-JP.json | 3 --- .../plugins/translations/translations/zh-CN.json | 3 --- 25 files changed, 54 insertions(+), 76 deletions(-) diff --git a/src/plugins/dashboard/public/dashboard_app/locator/get_dashboard_locator_params.ts b/src/plugins/dashboard/public/dashboard_app/locator/get_dashboard_locator_params.ts index 46c7acd79261e..a2b4371834d04 100644 --- a/src/plugins/dashboard/public/dashboard_app/locator/get_dashboard_locator_params.ts +++ b/src/plugins/dashboard/public/dashboard_app/locator/get_dashboard_locator_params.ts @@ -9,7 +9,7 @@ import { isQuery, isTimeRange } from '@kbn/data-plugin/common'; import { Filter, isFilterPinned, Query, TimeRange } from '@kbn/es-query'; import { EmbeddableInput, IEmbeddable } from '@kbn/embeddable-plugin/public'; -import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/common'; import { DashboardAppLocatorParams } from './locator'; @@ -19,7 +19,7 @@ interface EmbeddableQueryInput extends EmbeddableInput { timeRange?: TimeRange; } -export const getDashboardLocatorParams = ( +export const getEmbeddableParams = ( source: IEmbeddable, options: DashboardDrilldownOptions ): Partial => { diff --git a/src/plugins/dashboard/public/index.ts b/src/plugins/dashboard/public/index.ts index 01395015d692e..290f4b7c10f28 100644 --- a/src/plugins/dashboard/public/index.ts +++ b/src/plugins/dashboard/public/index.ts @@ -30,7 +30,7 @@ export { type DashboardAppLocatorParams, cleanEmptyKeys, } from './dashboard_app/locator/locator'; -export { getDashboardLocatorParams } from './dashboard_app/locator/get_dashboard_locator_params'; +export { getEmbeddableParams } from './dashboard_app/locator/get_dashboard_locator_params'; export function plugin(initializerContext: PluginInitializerContext) { return new DashboardPlugin(initializerContext); diff --git a/src/plugins/navigation_embeddable/common/content_management/v1/constants.ts b/src/plugins/navigation_embeddable/common/content_management/v1/constants.ts index 643a053ba6a98..f0cc649a18145 100644 --- a/src/plugins/navigation_embeddable/common/content_management/v1/constants.ts +++ b/src/plugins/navigation_embeddable/common/content_management/v1/constants.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import { UrlDrilldownOptions } from '@kbn/ui-actions-enhanced-plugin/public'; -import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; +import { UrlDrilldownOptions } from '@kbn/ui-actions-enhanced-plugin/common'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/common'; /** * Link types diff --git a/src/plugins/navigation_embeddable/common/content_management/v1/types.ts b/src/plugins/navigation_embeddable/common/content_management/v1/types.ts index 9875b99946270..b48e635d13921 100644 --- a/src/plugins/navigation_embeddable/common/content_management/v1/types.ts +++ b/src/plugins/navigation_embeddable/common/content_management/v1/types.ts @@ -11,8 +11,8 @@ import type { SavedObjectCreateOptions, SavedObjectUpdateOptions, } from '@kbn/content-management-utils'; -import { UrlDrilldownOptions } from '@kbn/ui-actions-enhanced-plugin/public'; -import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; +import { UrlDrilldownOptions } from '@kbn/ui-actions-enhanced-plugin/common'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/common'; import { NavigationEmbeddableContentType } from '../../types'; import { DASHBOARD_LINK_TYPE, diff --git a/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx b/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx index 8da0ff0dbcdc3..afa5a16b54a7b 100644 --- a/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx +++ b/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx @@ -11,7 +11,7 @@ import useAsync from 'react-use/lib/useAsync'; import React, { useMemo, useState } from 'react'; import { EuiButtonEmpty, EuiListGroupItem, EuiToolTip } from '@elastic/eui'; -import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/common'; import { DashboardContainer } from '@kbn/dashboard-plugin/public/dashboard_container'; import { @@ -110,15 +110,18 @@ export const DashboardLinkComponent = ({ })} onClick={ link.destination === parentDashboardId - ? undefined + ? undefined // no `onClick` event should exist if the link points to the current dashboard : (event) => { - // TODO: As part of https://github.com/elastic/kibana/issues/154381, connect to drilldown const options = link.options as DashboardDrilldownOptions; clickLink(navEmbeddable, { ...link, options: { ...DEFAULT_DASHBOARD_LINK_OPTIONS, ...options, + /** + * the app state should be sent via URL if either (a) the `openInNewTab` setting is `true` + * or if (b) the ctrl/shift/meta (command on Mac) key is pressed on click. + */ openInNewTab: options.openInNewTab || event.ctrlKey || event.metaKey || event.shiftKey, }, diff --git a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx index 544be2e52d0d3..0803cdec2678a 100644 --- a/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx +++ b/src/plugins/navigation_embeddable/public/components/editor/navigation_embeddable_link_editor.tsx @@ -26,16 +26,14 @@ import { EuiFlyoutHeader, EuiRadioGroupOption, } from '@elastic/eui'; +import { UrlDrilldownOptions } from '@kbn/ui-actions-enhanced-plugin/common'; import { DashboardContainer } from '@kbn/dashboard-plugin/public/dashboard_container'; -import { - UrlDrilldownOptions, - UrlDrilldownOptionsComponent, -} from '@kbn/ui-actions-enhanced-plugin/public'; +import { UrlDrilldownOptionsComponent } from '@kbn/ui-actions-enhanced-plugin/public'; import { withSuspense, - DashboardDrilldownOptions, LazyDashboardDrilldownOptionsComponent, } from '@kbn/presentation-util-plugin/public'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/common'; import { NavigationLinkType, diff --git a/src/plugins/navigation_embeddable/public/services/link_service.ts b/src/plugins/navigation_embeddable/public/services/link_service.ts index 88e9314b31c3b..f8cacfc95b68c 100644 --- a/src/plugins/navigation_embeddable/public/services/link_service.ts +++ b/src/plugins/navigation_embeddable/public/services/link_service.ts @@ -9,12 +9,12 @@ import { cleanEmptyKeys, DashboardAppLocatorParams, - getDashboardLocatorParams, + getEmbeddableParams, } from '@kbn/dashboard-plugin/public'; import { isFilterPinned } from '@kbn/es-query'; import { KibanaLocation } from '@kbn/share-plugin/public'; import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common'; -import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; +import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/common'; import { DASHBOARD_LINK_TYPE, @@ -32,14 +32,12 @@ export const clickLink = async ( if (link.type === DASHBOARD_LINK_TYPE) { const params: DashboardAppLocatorParams = { dashboardId: link.destination, - ...getDashboardLocatorParams( + ...getEmbeddableParams( embeddable, (link.options as DashboardDrilldownOptions) ?? DEFAULT_DASHBOARD_LINK_OPTIONS ), }; - console.log(params); - const locator = dashboardServices.locator; // TODO: Make this a generic locator that is coming from the dashboard container through some sort of getter if (locator) { const { app, path, state }: KibanaLocation = diff --git a/src/plugins/navigation_embeddable/tsconfig.json b/src/plugins/navigation_embeddable/tsconfig.json index ae66fa7cc3144..0126de49eaac2 100644 --- a/src/plugins/navigation_embeddable/tsconfig.json +++ b/src/plugins/navigation_embeddable/tsconfig.json @@ -20,6 +20,10 @@ "@kbn/saved-objects-plugin", "@kbn/core-saved-objects-server", "@kbn/saved-objects-plugin", + "@kbn/ui-actions-enhanced-plugin", + "@kbn/es-query", + "@kbn/share-plugin", + "@kbn/kibana-utils-plugin" ], "exclude": ["target/**/*"] } diff --git a/src/plugins/presentation_util/common/index.ts b/src/plugins/presentation_util/common/index.ts index 710292097d4cd..e39faec3b8cbd 100644 --- a/src/plugins/presentation_util/common/index.ts +++ b/src/plugins/presentation_util/common/index.ts @@ -45,3 +45,13 @@ export { encode, parseDataUrl, } from './lib'; + +/** + * Dashboard drilldown options, which are each controlled by a toggle + */ +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export type DashboardDrilldownOptions = { + useCurrentFilters: boolean; + useCurrentDateRange: boolean; + openInNewTab: boolean; +}; diff --git a/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_options.tsx b/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_options.tsx index 3f87a0f1bbda2..627593b6b2f31 100644 --- a/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_options.tsx +++ b/src/plugins/presentation_util/public/components/dashboard_drilldown_options/dashboard_drilldown_options.tsx @@ -8,10 +8,10 @@ import React from 'react'; import { EuiFormRow, EuiSwitch } from '@elastic/eui'; -import { DashboardDrilldownOptions } from '../types'; +import { DashboardDrilldownOptions } from '../../../common'; import { dashboardDrilldownConfigStrings } from '../../i18n/dashboard_drilldown_config'; -interface DashboardDrilldownOptionsProps { +export interface DashboardDrilldownOptionsProps { options: DashboardDrilldownOptions; onOptionChange: (newOptions: Partial) => void; } diff --git a/src/plugins/presentation_util/public/components/types.ts b/src/plugins/presentation_util/public/components/types.ts index b451cd776da19..4b996b3297180 100644 --- a/src/plugins/presentation_util/public/components/types.ts +++ b/src/plugins/presentation_util/public/components/types.ts @@ -71,13 +71,3 @@ export interface ExpressionInputProps onEditorDidMount?: OnExpressionInputEditorDidMount; } - -/** - * Dashboard drilldown options, which are each controlled by a toggle - */ -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export type DashboardDrilldownOptions = { - useCurrentFilters: boolean; - useCurrentDateRange: boolean; - openInNewTab: boolean; -}; diff --git a/src/plugins/presentation_util/public/index.ts b/src/plugins/presentation_util/public/index.ts index eb874ff9ae6ce..d5dbaf5fb761d 100644 --- a/src/plugins/presentation_util/public/index.ts +++ b/src/plugins/presentation_util/public/index.ts @@ -24,8 +24,8 @@ export type { } from './services/create'; export { PluginServices, PluginServiceProvider, PluginServiceRegistry } from './services/create'; +export type { SaveModalDashboardProps } from './components/types'; export type { PresentationUtilPluginSetup, PresentationUtilPluginStart } from './types'; -export type { SaveModalDashboardProps, DashboardDrilldownOptions } from './components/types'; export { LazyExpressionInput, diff --git a/src/plugins/ui_actions_enhanced/common/index.ts b/src/plugins/ui_actions_enhanced/common/index.ts index f92a61f3f7847..03a7380bf1ba7 100644 --- a/src/plugins/ui_actions_enhanced/common/index.ts +++ b/src/plugins/ui_actions_enhanced/common/index.ts @@ -11,4 +11,5 @@ export type { SerializedAction, SerializedEvent, DynamicActionsState, + UrlDrilldownOptions, } from './types'; diff --git a/src/plugins/ui_actions_enhanced/common/types.ts b/src/plugins/ui_actions_enhanced/common/types.ts index 5237b6f23ee2c..041be36fde43b 100644 --- a/src/plugins/ui_actions_enhanced/common/types.ts +++ b/src/plugins/ui_actions_enhanced/common/types.ts @@ -8,6 +8,11 @@ import type { SerializableRecord } from '@kbn/utility-types'; +export type UrlDrilldownOptions = { + openInNewTab: boolean; + encodeUrl?: boolean; +}; + export type BaseActionConfig = SerializableRecord; export type SerializedAction = { diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_collect_config.tsx b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_collect_config.tsx index 0e5c2441b635e..9287315b7ba65 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_collect_config.tsx +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_collect_config.tsx @@ -7,15 +7,7 @@ */ import React, { useRef } from 'react'; -import { - EuiFormRow, - EuiLink, - EuiSwitch, - EuiAccordion, - EuiSpacer, - EuiPanel, - EuiTextColor, -} from '@elastic/eui'; +import { EuiFormRow, EuiLink, EuiAccordion, EuiSpacer, EuiPanel } from '@elastic/eui'; import { monaco } from '@kbn/monaco'; import { UrlTemplateEditor, UrlTemplateEditorVariable } from '@kbn/kibana-react-plugin/public'; import { UrlDrilldownConfig } from '../../types'; diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_options.tsx b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_options.tsx index e141c58fdb4eb..f6373c0baf7b9 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_options.tsx +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/url_drilldown_options.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { EuiFormRow, EuiSpacer, EuiSwitch, EuiTextColor } from '@elastic/eui'; -import { UrlDrilldownOptions } from '../../types'; +import { UrlDrilldownOptions } from '../../../../../common'; import { txtUrlTemplateEncodeDescription, txtUrlTemplateEncodeUrl, diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/index.ts b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/index.ts index 482f4a04f828d..e3a9932b8c4e1 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/index.ts +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/index.ts @@ -6,12 +6,7 @@ * Side Public License, v 1. */ -export type { - UrlDrilldownConfig, - UrlDrilldownGlobalScope, - UrlDrilldownOptions, - UrlDrilldownScope, -} from './types'; +export type { UrlDrilldownConfig, UrlDrilldownGlobalScope, UrlDrilldownScope } from './types'; export { UrlDrilldownCollectConfig, UrlDrilldownOptionsComponent } from './components'; export { validateUrlTemplate as urlDrilldownValidateUrlTemplate, diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts index 1efc96352cf73..68fe64843d0cd 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts @@ -6,10 +6,7 @@ * Side Public License, v 1. */ -export type UrlDrilldownOptions = { - openInNewTab: boolean; - encodeUrl?: boolean; -}; +import { UrlDrilldownOptions } from '../../../common'; export type UrlDrilldownConfig = { url: { format?: 'handlebars_v1'; template: string }; diff --git a/src/plugins/ui_actions_enhanced/public/index.ts b/src/plugins/ui_actions_enhanced/public/index.ts index abd1e1b01668f..58dfd25b0fc7d 100644 --- a/src/plugins/ui_actions_enhanced/public/index.ts +++ b/src/plugins/ui_actions_enhanced/public/index.ts @@ -44,7 +44,6 @@ export type { export type { UrlDrilldownConfig, UrlDrilldownGlobalScope, - UrlDrilldownOptions, UrlDrilldownScope, } from './drilldowns/url_drilldown'; export { diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx index c3f8c15f2955f..37d2a2e7bafc5 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx @@ -8,8 +8,8 @@ import React from 'react'; import { EuiFormRow, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { - LazyDashboardDrilldownOptionsComponent, withSuspense, + LazyDashboardDrilldownOptionsComponent, } from '@kbn/presentation-util-plugin/public'; import { DrilldownConfig } from '../../types'; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx index 0e8dc51944e2d..375a47fdf1ae1 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx @@ -9,7 +9,7 @@ import type { KibanaLocation } from '@kbn/share-plugin/public'; import { cleanEmptyKeys, DashboardAppLocatorParams, - getDashboardLocatorParams as getSourceParams, + getEmbeddableParams, } from '@kbn/dashboard-plugin/public'; import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public'; import { APPLY_FILTER_TRIGGER } from '@kbn/data-plugin/public'; @@ -49,7 +49,7 @@ export class EmbeddableToDashboardDrilldown extends AbstractDashboardDrilldown Date: Tue, 22 Aug 2023 10:43:12 -0600 Subject: [PATCH 08/32] Another attempt at fixing CI --- .../dashboard_drilldown_persistable_state.ts | 6 +++--- .../common/drilldowns/dashboard_drilldown/index.ts | 1 - .../common/drilldowns/dashboard_drilldown/types.ts | 12 ++++++++++++ .../abstract_dashboard_drilldown.tsx | 5 +++-- .../components/collect_config_container.tsx | 6 +++--- .../dashboard_drilldown_config.tsx | 2 +- .../drilldowns/abstract_dashboard_drilldown/index.ts | 2 +- .../drilldowns/abstract_dashboard_drilldown/types.ts | 5 ----- .../embeddable_to_dashboard_drilldown.tsx | 4 ++-- 9 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts diff --git a/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/dashboard_drilldown_persistable_state.ts b/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/dashboard_drilldown_persistable_state.ts index fe71ebd65ea8f..aff6c1cabedca 100644 --- a/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/dashboard_drilldown_persistable_state.ts +++ b/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/dashboard_drilldown_persistable_state.ts @@ -8,7 +8,7 @@ import { SavedObjectReference } from '@kbn/core/types'; import { PersistableStateService } from '@kbn/kibana-utils-plugin/common'; import { SerializedAction, SerializedEvent } from '@kbn/ui-actions-enhanced-plugin/common'; -import { DrilldownConfig } from './types'; +import { DashboardDrilldownConfig } from './types'; type DashboardDrilldownPersistableState = PersistableStateService; @@ -34,7 +34,7 @@ export const createInject = ({ drilldownId: string; }): DashboardDrilldownPersistableState['inject'] => { return (state: SerializedEvent, references: SavedObjectReference[]) => { - const action = state.action as SerializedAction; + const action = state.action as SerializedAction; const refName = generateRefName(state, drilldownId); const ref = references.find((r) => r.name === refName); if (!ref) return state; @@ -49,7 +49,7 @@ export const createExtract = ({ drilldownId: string; }): DashboardDrilldownPersistableState['extract'] => { return (state: SerializedEvent) => { - const action = state.action as SerializedAction; + const action = state.action as SerializedAction; const references: SavedObjectReference[] = action.config.dashboardId ? [ { diff --git a/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/index.ts b/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/index.ts index fde3b5b06de2d..83d0ad0d464b7 100644 --- a/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/index.ts +++ b/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/index.ts @@ -7,4 +7,3 @@ export { createExtract, createInject } from './dashboard_drilldown_persistable_state'; export { EMBEDDABLE_TO_DASHBOARD_DRILLDOWN } from './constants'; -export type { DrilldownConfig } from './types'; diff --git a/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts b/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts new file mode 100644 index 0000000000000..b6004b84acbb6 --- /dev/null +++ b/x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/types.ts @@ -0,0 +1,12 @@ +/* + * 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 { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/common'; + +export type DashboardDrilldownConfig = { + dashboardId?: string; +} & DashboardDrilldownOptions; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx index 216402661ec35..26a638a695493 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx @@ -15,9 +15,10 @@ import { UiActionsEnhancedDrilldownDefinition as Drilldown, } from '@kbn/ui-actions-enhanced-plugin/public'; import { CollectConfigProps, StartServicesGetter } from '@kbn/kibana-utils-plugin/public'; -import { CollectConfigContainer } from './components'; + import { txtGoToDashboard } from './i18n'; -import { DrilldownConfig as Config } from './types'; +import { CollectConfigContainer } from './components'; +import { DashboardDrilldownConfig as Config } from '../../../../common/drilldowns/dashboard_drilldown/types'; export interface Params { start: StartServicesGetter<{ diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/collect_config_container.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/collect_config_container.tsx index 682f879b86985..c513da08f2a66 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/collect_config_container.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/collect_config_container.tsx @@ -12,9 +12,8 @@ import { SimpleSavedObject } from '@kbn/core/public'; import { CollectConfigProps } from '@kbn/kibana-utils-plugin/public'; import { DashboardDrilldownConfig } from './dashboard_drilldown_config'; import { txtDestinationDashboardNotFound } from './i18n'; -import { Config } from '../types'; import { Params } from '../abstract_dashboard_drilldown'; -import { DrilldownConfig } from '../../../../../common/drilldowns/dashboard_drilldown/types'; +import { DashboardDrilldownConfig as DrilldownConfig } from '../../../../../common/drilldowns/dashboard_drilldown/types'; const mergeDashboards = ( dashboards: Array>, @@ -36,7 +35,8 @@ const dashboardSavedObjectToMenuItem = ( label: savedObject.attributes.title, }); -export interface DashboardDrilldownCollectConfigProps extends CollectConfigProps { +export interface DashboardDrilldownCollectConfigProps + extends CollectConfigProps { params: Params; } diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx index 37d2a2e7bafc5..9bea5ed4c4288 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx @@ -12,8 +12,8 @@ import { LazyDashboardDrilldownOptionsComponent, } from '@kbn/presentation-util-plugin/public'; -import { DrilldownConfig } from '../../types'; import { txtChooseDestinationDashboard } from './i18n'; +import { DashboardDrilldownConfig as DrilldownConfig } from '../../../../../../common/drilldowns/dashboard_drilldown/types'; const DashboardDrilldownOptions = withSuspense(LazyDashboardDrilldownOptionsComponent, null); diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/index.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/index.ts index 3b76303bda388..de129baf9ea63 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/index.ts +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/index.ts @@ -7,4 +7,4 @@ export type { Params as AbstractDashboardDrilldownParams } from './abstract_dashboard_drilldown'; export { AbstractDashboardDrilldown } from './abstract_dashboard_drilldown'; -export type { Config as AbstractDashboardDrilldownConfig } from './types'; +// export type { DrilldownConfig as AbstractDashboardDrilldownConfig } from './types'; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts index 7cf7ea9ebb92c..2bae8ba4959c2 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts @@ -5,11 +5,6 @@ * 2.0. */ -import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/public'; import { UiActionsEnhancedBaseActionFactoryContext } from '@kbn/ui-actions-enhanced-plugin/public'; export type FactoryContext = UiActionsEnhancedBaseActionFactoryContext; - -export type DrilldownConfig = { - dashboardId?: string; -} & DashboardDrilldownOptions; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx index 375a47fdf1ae1..063eda7b9bab9 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx @@ -19,10 +19,10 @@ import { IMAGE_CLICK_TRIGGER } from '@kbn/image-embeddable-plugin/public'; import { AbstractDashboardDrilldown, AbstractDashboardDrilldownParams, - AbstractDashboardDrilldownConfig as Config, } from '../abstract_dashboard_drilldown'; import { EMBEDDABLE_TO_DASHBOARD_DRILLDOWN } from './constants'; import { createExtract, createInject } from '../../../../common'; +import { DashboardDrilldownConfig } from '../../../../common/drilldowns/dashboard_drilldown/types'; type Context = EnhancedEmbeddableContext & ApplyGlobalFilterActionContext; export type Params = AbstractDashboardDrilldownParams; @@ -40,7 +40,7 @@ export class EmbeddableToDashboardDrilldown extends AbstractDashboardDrilldown [APPLY_FILTER_TRIGGER, IMAGE_CLICK_TRIGGER]; protected async getLocation( - config: Config, + config: DashboardDrilldownConfig, context: Context, useUrlForState: boolean ): Promise { From fd57408960097b7a81a1dfbd79197188f9f86811 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Tue, 22 Aug 2023 17:15:58 -0600 Subject: [PATCH 09/32] First draft of external URLs working --- .../external_link/external_link_component.tsx | 15 +++++++-- .../external_link_destination_picker.tsx | 32 ++++++++++++------- .../url_drilldown_collect_config/i18n.ts | 2 +- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/plugins/navigation_embeddable/public/components/external_link/external_link_component.tsx b/src/plugins/navigation_embeddable/public/components/external_link/external_link_component.tsx index 52442cd307b0b..a6bee9497d168 100644 --- a/src/plugins/navigation_embeddable/public/components/external_link/external_link_component.tsx +++ b/src/plugins/navigation_embeddable/public/components/external_link/external_link_component.tsx @@ -9,6 +9,9 @@ import React from 'react'; import { EuiListGroupItem } from '@elastic/eui'; +import { UrlDrilldownOptions } from '@kbn/ui-actions-enhanced-plugin/common'; + +import { coreServices } from '../../services/kibana_services'; import { NavigationEmbeddableLink } from '../../../common/content_management'; export const ExternalLinkComponent = ({ link }: { link: NavigationEmbeddableLink }) => { @@ -19,8 +22,16 @@ export const ExternalLinkComponent = ({ link }: { link: NavigationEmbeddableLink className={'navigationLink'} id={`externalLink--${link.id}`} label={link.label || link.destination} - onClick={() => { - // TODO: As part of https://github.com/elastic/kibana/issues/154381, connect to drilldown + onClick={async () => { + const destination = + !link.options || (link.options as UrlDrilldownOptions)?.encodeUrl + ? encodeURI(link.destination) + : link.destination; + if (!link.options || link.options.openInNewTab) { + window.open(destination, '_blank', 'noopener'); + } else { + await coreServices.application.navigateToUrl(destination); + } }} /> ); diff --git a/src/plugins/navigation_embeddable/public/components/external_link/external_link_destination_picker.tsx b/src/plugins/navigation_embeddable/public/components/external_link/external_link_destination_picker.tsx index 4019e4c843faf..b9c4a8009bd22 100644 --- a/src/plugins/navigation_embeddable/public/components/external_link/external_link_destination_picker.tsx +++ b/src/plugins/navigation_embeddable/public/components/external_link/external_link_destination_picker.tsx @@ -11,10 +11,7 @@ import React, { useState } from 'react'; import { EuiFieldText } from '@elastic/eui'; import { ExternalLinkStrings } from './external_link_strings'; - -// TODO: As part of https://github.com/elastic/kibana/issues/154381, replace this regex URL check with more robust url validation -const isValidUrl = - /^https?:\/\/(?:www.)?[-a-zA-Z0-9@:%._+~#=]{1,256}.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)$/; +import { coreServices } from '../../services/kibana_services'; export const ExternalLinkDestinationPicker = ({ onDestinationPicked, @@ -29,8 +26,12 @@ export const ExternalLinkDestinationPicker = ({ useMount(() => { if (initialSelection) { - onDestinationPicked(initialSelection); - setValidUrl(isValidUrl.test(initialSelection)); + const url = coreServices.http.externalUrl.validateUrl(initialSelection); + if (url === null) { + setValidUrl(false); + } else { + onDestinationPicked(initialSelection); + } } }); @@ -42,12 +43,19 @@ export const ExternalLinkDestinationPicker = ({ placeholder={ExternalLinkStrings.getPlaceholder()} isInvalid={!validUrl} onChange={(e) => { - const url = e.target.value; - const isValid = isValidUrl.test(url); - setValidUrl(isValid); - setCurrentUrl(url); - if (isValid) { - onDestinationPicked(url); + setCurrentUrl(e.target.value); + try { + const url = coreServices.http.externalUrl.validateUrl(e.target.value); + /** We only allow URLs that (a) can be parsed via the validator and (b) are not internal */ + if (url === null || coreServices.http.externalUrl.isInternalUrl(url.href)) { + throw new Error('Invalid URL'); // This doesn't need to be translated because it will be caught below + } else { + setValidUrl(true); + onDestinationPicked(e.target.value); + } + } catch { + setValidUrl(false); + onDestinationPicked(undefined); } }} /> diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/i18n.ts b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/i18n.ts index dcb36cbab257a..48f5fe1fdc8b6 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/i18n.ts +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/components/url_drilldown_collect_config/i18n.ts @@ -57,7 +57,7 @@ export const txtUrlTemplatePreviewLinkText = i18n.translate( export const txtUrlTemplateOpenInNewTab = i18n.translate( 'uiActionsEnhanced.drilldowns.urlDrilldownCollectConfig.openInNewTabLabel', { - defaultMessage: 'Open in new window', + defaultMessage: 'Open URL in new tab', } ); From 185f5070b08924b5ee4dfc480e2d02628a502622 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Wed, 23 Aug 2023 09:38:52 -0600 Subject: [PATCH 10/32] Clean up + fix memory leak --- .../dashboard_link_component.tsx | 98 +++++++++++++------ .../public/services/link_service.ts | 68 ------------- 2 files changed, 69 insertions(+), 97 deletions(-) delete mode 100644 src/plugins/navigation_embeddable/public/services/link_service.ts diff --git a/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx b/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx index afa5a16b54a7b..b2d0b2d7d049f 100644 --- a/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx +++ b/src/plugins/navigation_embeddable/public/components/dashboard_link/dashboard_link_component.tsx @@ -8,8 +8,17 @@ import classNames from 'classnames'; import useAsync from 'react-use/lib/useAsync'; -import React, { useMemo, useState } from 'react'; +import useObservable from 'react-use/lib/useObservable'; +import React, { useCallback, useMemo, useState } from 'react'; +import { + cleanEmptyKeys, + DashboardAppLocatorParams, + getEmbeddableParams, +} from '@kbn/dashboard-plugin/public'; +import { isFilterPinned } from '@kbn/es-query'; +import { KibanaLocation } from '@kbn/share-plugin/public'; +import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common'; import { EuiButtonEmpty, EuiListGroupItem, EuiToolTip } from '@elastic/eui'; import { DashboardDrilldownOptions } from '@kbn/presentation-util-plugin/common'; import { DashboardContainer } from '@kbn/dashboard-plugin/public/dashboard_container'; @@ -21,9 +30,9 @@ import { DEFAULT_DASHBOARD_LINK_OPTIONS, } from '../../../common/content_management'; import { fetchDashboard } from './dashboard_link_tools'; -import { clickLink } from '../../services/link_service'; import { DashboardLinkStrings } from './dashboard_link_strings'; import { useNavigationEmbeddable } from '../../embeddable/navigation_embeddable'; +import { coreServices, dashboardServices } from '../../services/kibana_services'; export const DashboardLinkComponent = ({ link, @@ -36,13 +45,10 @@ export const DashboardLinkComponent = ({ const [error, setError] = useState(); const dashboardContainer = navEmbeddable.parent as DashboardContainer; - const parentDashboardTitle = dashboardContainer.select((state) => state.explicitInput.title); - const parentDashboardDescription = dashboardContainer.select( - (state) => state.explicitInput.description - ); - + const parentDashboardInput = useObservable(dashboardContainer.getInput$()); const parentDashboardId = dashboardContainer.select((state) => state.componentState.lastSavedId); + /** Fetch the dashboard that the link is pointing to */ const { loading: loadingDestinationDashboard, value: destinationDashboard } = useAsync(async () => { if (link.id !== parentDashboardId) { @@ -60,22 +66,23 @@ export const DashboardLinkComponent = ({ } }, [link, parentDashboardId]); + /** + * Returns the title and description of the dashboard that the link points to; note that, if the link points to + * the current dashboard, then we need to get the most up-to-date information via the `parentDashboardInput` - this + * will respond to changes so that the link label/tooltip remains in sync with the dashboard title/description. + */ const [dashboardTitle, dashboardDescription] = useMemo(() => { return link.destination === parentDashboardId - ? [parentDashboardTitle, parentDashboardDescription] + ? [parentDashboardInput?.title, parentDashboardInput?.description] : [destinationDashboard?.attributes.title, destinationDashboard?.attributes.description]; - }, [ - link.destination, - parentDashboardId, - parentDashboardTitle, - destinationDashboard, - parentDashboardDescription, - ]); + }, [link.destination, parentDashboardId, parentDashboardInput, destinationDashboard]); + /** Label of the `EuiListGroupItem` for the given link */ const linkLabel = useMemo(() => { return link.label || (dashboardTitle ?? DashboardLinkStrings.getDashboardErrorLabel()); }, [link, dashboardTitle]); + /** Tooltip info of the `EuiListGroupItem` for the given link */ const { tooltipTitle, tooltipMessage } = useMemo(() => { if (error) { return { @@ -89,6 +96,52 @@ export const DashboardLinkComponent = ({ }; }, [error, dashboardTitle, dashboardDescription]); + /** `onClick` action for navigating to the destination dashboard */ + const navigateToDashboard = useCallback( + async (modifiedClick: boolean) => { + const options: DashboardDrilldownOptions = { + ...DEFAULT_DASHBOARD_LINK_OPTIONS, + ...link.options, + }; + const params: DashboardAppLocatorParams = { + dashboardId: link.destination, + ...getEmbeddableParams(navEmbeddable, options), + }; + + const locator = dashboardServices.locator; // TODO: Make this a generic locator that is coming from the dashboard container through some sort of getter + if (locator) { + const { app, path, state }: KibanaLocation = + await locator.getLocation(params); + + /** + * the app state should be sent via URL if either (a) the `openInNewTab` setting is `true` + * or if (b) the ctrl/shift/meta (command on Mac) key is pressed on click. + */ + if (options.openInNewTab || modifiedClick) { + const url = coreServices.application.getUrlForApp(app, { + path: setStateToKbnUrl( + '_a', + cleanEmptyKeys({ + query: state.query, + filters: state.filters?.filter((f) => !isFilterPinned(f)), + }), + { useHash: false, storeInHashQuery: true }, + path + ), + absolute: true, + }); + window.open(url, '_blank'); + } else { + await coreServices.application.navigateToApp(app, { + path, + state, + }); + } + } + }, + [link, navEmbeddable] + ); + return loadingDestinationDashboard ? (