grafana/public/app/features/dashboard/utils/getPanelMenu.ts
Josh Hunt 3c6e0e8ef8
Chore: ESlint import order (#44959)
* Add and configure eslint-plugin-import

* Fix the lint:ts npm command

* Autofix + prettier all the files

* Manually fix remaining files

* Move jquery code in jest-setup to external file to safely reorder imports

* Resolve issue caused by circular dependencies within Prometheus

* Update .betterer.results

* Fix missing // @ts-ignore

* ignore iconBundle.ts

* Fix missing // @ts-ignore
2022-04-22 14:33:13 +01:00

230 lines
5.7 KiB
TypeScript

import { PanelMenuItem } from '@grafana/data';
import { AngularComponent, getDataSourceSrv, locationService } from '@grafana/runtime';
import { PanelCtrl } from 'app/angular/panel/panel_ctrl';
import config from 'app/core/config';
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
import {
addLibraryPanel,
copyPanel,
duplicatePanel,
removePanel,
sharePanel,
unlinkLibraryPanel,
} from 'app/features/dashboard/utils/panel';
import { isPanelModelLibraryPanel } from 'app/features/library-panels/guard';
import { store } from 'app/store/store';
import { contextSrv } from '../../../core/services/context_srv';
import { getExploreUrl } from '../../../core/utils/explore';
import { navigateToExplore } from '../../explore/state/main';
import { getTimeSrv } from '../services/TimeSrv';
export function getPanelMenu(
dashboard: DashboardModel,
panel: PanelModel,
angularComponent?: AngularComponent | null
): PanelMenuItem[] {
const onViewPanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
locationService.partial({
viewPanel: panel.id,
});
};
const onEditPanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
locationService.partial({
editPanel: panel.id,
});
};
const onSharePanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
sharePanel(dashboard, panel);
};
const onAddLibraryPanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
addLibraryPanel(dashboard, panel);
};
const onUnlinkLibraryPanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
unlinkLibraryPanel(panel);
};
const onInspectPanel = (tab?: string) => {
locationService.partial({
inspect: panel.id,
inspectTab: tab,
});
};
const onMore = (event: React.MouseEvent<any>) => {
event.preventDefault();
};
const onDuplicatePanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
duplicatePanel(dashboard, panel);
};
const onCopyPanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
copyPanel(panel);
};
const onRemovePanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
removePanel(dashboard, panel, true);
};
const onNavigateToExplore = (event: React.MouseEvent<any>) => {
event.preventDefault();
const openInNewWindow =
event.ctrlKey || event.metaKey ? (url: string) => window.open(`${config.appSubUrl}${url}`) : undefined;
store.dispatch(navigateToExplore(panel, { getDataSourceSrv, getTimeSrv, getExploreUrl, openInNewWindow }) as any);
};
const menu: PanelMenuItem[] = [];
if (!panel.isEditing) {
menu.push({
text: 'View',
iconClassName: 'eye',
onClick: onViewPanel,
shortcut: 'v',
});
}
if (dashboard.canEditPanel(panel) && !panel.isEditing) {
menu.push({
text: 'Edit',
iconClassName: 'edit',
onClick: onEditPanel,
shortcut: 'e',
});
}
menu.push({
text: 'Share',
iconClassName: 'share-alt',
onClick: onSharePanel,
shortcut: 'p s',
});
if (contextSrv.hasAccessToExplore() && !(panel.plugin && panel.plugin.meta.skipDataQuery)) {
menu.push({
text: 'Explore',
iconClassName: 'compass',
shortcut: 'x',
onClick: onNavigateToExplore,
});
}
const inspectMenu: PanelMenuItem[] = [];
// Only show these inspect actions for data plugins
if (panel.plugin && !panel.plugin.meta.skipDataQuery) {
inspectMenu.push({
text: 'Data',
onClick: (e: React.MouseEvent<any>) => onInspectPanel('data'),
});
if (dashboard.meta.canEdit) {
inspectMenu.push({
text: 'Query',
onClick: (e: React.MouseEvent<any>) => onInspectPanel('query'),
});
}
}
inspectMenu.push({
text: 'Panel JSON',
onClick: (e: React.MouseEvent<any>) => onInspectPanel('json'),
});
menu.push({
type: 'submenu',
text: 'Inspect',
iconClassName: 'info-circle',
onClick: (e: React.MouseEvent<any>) => onInspectPanel(),
shortcut: 'i',
subMenu: inspectMenu,
});
const subMenu: PanelMenuItem[] = [];
if (dashboard.canEditPanel(panel) && !(panel.isViewing || panel.isEditing)) {
subMenu.push({
text: 'Duplicate',
onClick: onDuplicatePanel,
shortcut: 'p d',
});
subMenu.push({
text: 'Copy',
onClick: onCopyPanel,
});
if (isPanelModelLibraryPanel(panel)) {
subMenu.push({
text: 'Unlink library panel',
onClick: onUnlinkLibraryPanel,
});
} else {
subMenu.push({
text: 'Create library panel',
onClick: onAddLibraryPanel,
});
}
}
// add old angular panel options
if (angularComponent) {
const scope = angularComponent.getScope();
const panelCtrl: PanelCtrl = scope.$$childHead.ctrl;
const angularMenuItems = panelCtrl.getExtendedMenu();
for (const item of angularMenuItems) {
const reactItem: PanelMenuItem = {
text: item.text,
href: item.href,
shortcut: item.shortcut,
};
if (item.click) {
reactItem.onClick = () => {
scope.$eval(item.click, { ctrl: panelCtrl });
};
}
subMenu.push(reactItem);
}
}
if (!panel.isEditing && subMenu.length) {
menu.push({
type: 'submenu',
text: 'More...',
iconClassName: 'cube',
subMenu,
onClick: onMore,
});
}
if (dashboard.canEditPanel(panel) && !panel.isEditing && !panel.isViewing) {
menu.push({ type: 'divider', text: '' });
menu.push({
text: 'Remove',
iconClassName: 'trash-alt',
onClick: onRemovePanel,
shortcut: 'p r',
});
}
return menu;
}