Skip to content

Commit 2b75815

Browse files
author
Stacey Gammon
authored
Add href option in addition to onClick (#25233)
* Add href option in addition to onClick * Small modificationd and adding tests * Add missing import * Switch order of tests * Don't close panel menu again
1 parent dc2953a commit 2b75815

File tree

6 files changed

+103
-20
lines changed

6 files changed

+103
-20
lines changed

src/core_plugins/kibana/public/dashboard/panel/panel_header/panel_actions/get_edit_panel_action.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ export function getEditPanelAction() {
4040
isDisabled: ({ embeddable }) =>
4141
!embeddable || !embeddable.metadata || !embeddable.metadata.editUrl,
4242
isVisible: ({ containerState }) => containerState.viewMode === DashboardViewMode.EDIT,
43-
onClick: ({ embeddable }) => {
43+
getHref: ({ embeddable }) => {
4444
if (embeddable && embeddable.metadata.editUrl) {
45-
window.location.href = embeddable.metadata.editUrl;
45+
return embeddable.metadata.editUrl;
4646
}
4747
},
4848
}

src/ui/public/embeddable/context_menu_actions/build_eui_context_menu_panels.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,25 @@ function convertPanelActionToContextMenuItem({
140140
containerState: ContainerState;
141141
embeddable?: Embeddable;
142142
}): EuiContextMenuPanelItemDescriptor {
143-
return {
143+
const menuPanelItem: EuiContextMenuPanelItemDescriptor = {
144144
name: action.displayName,
145145
icon: action.icon,
146146
panel: _.get(action, 'childContextMenuPanel.id'),
147-
onClick: () => action.onClick({ embeddable, containerState }),
148147
disabled: action.isDisabled({ embeddable, containerState }),
149148
'data-test-subj': `dashboardPanelAction-${action.id}`,
150149
};
150+
151+
if (action.onClick) {
152+
menuPanelItem.onClick = () => {
153+
if (action.onClick) {
154+
action.onClick({ embeddable, containerState });
155+
}
156+
};
157+
}
158+
159+
if (action.getHref) {
160+
menuPanelItem.href = action.getHref({ embeddable, containerState });
161+
}
162+
163+
return menuPanelItem;
151164
}

src/ui/public/embeddable/context_menu_actions/context_menu_action.ts

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,6 @@ import { ContextMenuPanel } from './context_menu_panel';
2121
import { PanelActionAPI } from './types';
2222

2323
interface ContextMenuActionOptions {
24-
/**
25-
* An optional action to take when the action is clicked on. Either this or childContextMenuPanel should be
26-
* given.
27-
*/
28-
onClick?: (actionAPI: PanelActionAPI) => void;
29-
3024
/**
3125
* An optional child context menu to display when the action is clicked.
3226
*/
@@ -57,6 +51,21 @@ interface ContextMenuActionOptions {
5751
icon?: EuiContextMenuItemIcon;
5852
}
5953

54+
interface ContextMenuButtonOptions extends ContextMenuActionOptions {
55+
/**
56+
* An optional action to take when the action is clicked on. Either this or childContextMenuPanel should be
57+
* given.
58+
*/
59+
onClick?: (actionAPI: PanelActionAPI) => void;
60+
}
61+
62+
interface ContextMenuLinkOptions extends ContextMenuActionOptions {
63+
/**
64+
* An optional href to use as navigation when the action is clicked on.
65+
*/
66+
getHref?: (actionAPI: PanelActionAPI) => string;
67+
}
68+
6069
interface ContextMenuActionsConfig {
6170
id: string;
6271

@@ -94,6 +103,16 @@ export class ContextMenuAction {
94103
*/
95104
public readonly parentPanelId: string;
96105

106+
/**
107+
* @param {PanelActionAPI} panelActionAPI
108+
*/
109+
public readonly onClick?: (panelActionAPI: PanelActionAPI) => void;
110+
111+
/**
112+
* @param {PanelActionAPI} panelActionAPI
113+
*/
114+
public readonly getHref?: (panelActionAPI: PanelActionAPI) => string;
115+
97116
/**
98117
*
99118
* @param {string} config.id
@@ -103,17 +122,21 @@ export class ContextMenuAction {
103122
* @param {ContextMenuPanel} options.childContextMenuPanel - optional child panel to open when clicked.
104123
* @param {function} options.isDisabled - optionally set a custom disabled function
105124
* @param {function} options.isVisible - optionally set a custom isVisible function
125+
* @param {function} options.getHref
106126
* @param {Element} options.icon
107127
*/
108-
public constructor(config: ContextMenuActionsConfig, options: ContextMenuActionOptions = {}) {
128+
public constructor(
129+
config: ContextMenuActionsConfig,
130+
options: ContextMenuButtonOptions | ContextMenuLinkOptions = {}
131+
) {
109132
this.id = config.id;
110133
this.displayName = config.displayName;
111134
this.parentPanelId = config.parentPanelId;
112135

113136
this.icon = options.icon;
114137
this.childContextMenuPanel = options.childContextMenuPanel;
115138

116-
if (options.onClick) {
139+
if ('onClick' in options) {
117140
this.onClick = options.onClick;
118141
}
119142

@@ -124,13 +147,10 @@ export class ContextMenuAction {
124147
if (options.isVisible) {
125148
this.isVisible = options.isVisible;
126149
}
127-
}
128150

129-
/**
130-
* @param {PanelActionAPI} panelActionAPI
131-
*/
132-
public onClick(panelActionAPI: PanelActionAPI): void {
133-
return;
151+
if ('getHref' in options) {
152+
this.getHref = options.getHref;
153+
}
134154
}
135155

136156
/**

test/plugin_functional/plugins/sample_panel_action/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
function samplePanelAction(kibana) {
2121
return new kibana.Plugin({
2222
uiExports: {
23-
contextMenuActions: ['plugins/sample_panel_action/sample_panel_action'],
23+
contextMenuActions: [
24+
'plugins/sample_panel_action/sample_panel_action',
25+
'plugins/sample_panel_action/sample_panel_link',
26+
],
2427
},
2528
});
2629
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
import {
20+
ContextMenuAction,
21+
ContextMenuActionsRegistryProvider,
22+
} from 'ui/embeddable';
23+
24+
class SamplePanelLink extends ContextMenuAction {
25+
constructor() {
26+
super({
27+
displayName: 'Sample Panel Link',
28+
id: 'samplePanelLink',
29+
parentPanelId: 'mainMenu',
30+
});
31+
}
32+
getHref() {
33+
return 'https://example.com/kibana/test';
34+
}
35+
}
36+
37+
ContextMenuActionsRegistryProvider.register(() => new SamplePanelLink());

test/plugin_functional/test_suites/panel_actions/panel_actions.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* under the License.
1818
*/
1919

20+
import expect from 'expect.js';
21+
2022
export default function ({ getService, getPageObjects }) {
2123
const dashboardPanelActions = getService('dashboardPanelActions');
2224
const testSubjects = getService('testSubjects');
@@ -27,8 +29,16 @@ export default function ({ getService, getPageObjects }) {
2729
await PageObjects.dashboard.loadSavedDashboard('few panels');
2830
});
2931

30-
it('Sample action appears in context menu in view mode', async () => {
32+
it('allows to register links into the context menu', async () => {
3133
await dashboardPanelActions.openContextMenu();
34+
const actionElement = await testSubjects.find('dashboardPanelAction-samplePanelLink');
35+
const actionElementTag = await actionElement.getTagName();
36+
expect(actionElementTag).to.be('a');
37+
const actionElementLink = await actionElement.getProperty('href');
38+
expect(actionElementLink).to.be('https://example.com/kibana/test');
39+
});
40+
41+
it('Sample action appears in context menu in view mode', async () => {
3242
await testSubjects.existOrFail(
3343
'dashboardPanelAction-samplePanelAction'
3444
);

0 commit comments

Comments
 (0)