diff --git a/public/app/features/dashboard/utils/getPanelMenu.test.ts b/public/app/features/dashboard/utils/getPanelMenu.test.ts index 0d52d187b7f..d7a3d4c858b 100644 --- a/public/app/features/dashboard/utils/getPanelMenu.test.ts +++ b/public/app/features/dashboard/utils/getPanelMenu.test.ts @@ -70,6 +70,10 @@ describe('getPanelMenu', () => { "onClick": [Function], "text": "Copy", }, + Object { + "onClick": [Function], + "text": "To global panel", + }, ], "text": "More...", "type": "submenu", diff --git a/public/app/features/dashboard/utils/getPanelMenu.ts b/public/app/features/dashboard/utils/getPanelMenu.ts index 0d4148fdabb..2d8b926bfee 100644 --- a/public/app/features/dashboard/utils/getPanelMenu.ts +++ b/public/app/features/dashboard/utils/getPanelMenu.ts @@ -1,7 +1,15 @@ import { store } from 'app/store/store'; import { AngularComponent, getDataSourceSrv, locationService } from '@grafana/runtime'; import { PanelMenuItem } from '@grafana/data'; -import { copyPanel, duplicatePanel, removePanel, sharePanel } from 'app/features/dashboard/utils/panel'; +import { + addLibraryPanel, + copyPanel, + duplicatePanel, + removePanel, + sharePanel, + unlinkLibraryPanel, +} from 'app/features/dashboard/utils/panel'; +import { isPanelModelLibraryPanel } from 'app/features/library-panels/guard'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { contextSrv } from '../../../core/services/context_srv'; @@ -35,6 +43,16 @@ export function getPanelMenu( sharePanel(dashboard, panel); }; + const onAddLibraryPanel = (event: React.MouseEvent) => { + event.preventDefault(); + addLibraryPanel(dashboard, panel); + }; + + const onUnlinkLibraryPanel = (event: React.MouseEvent) => { + event.preventDefault(); + unlinkLibraryPanel(panel); + }; + const onInspectPanel = (tab?: string) => { locationService.partial({ inspect: panel.id, @@ -148,6 +166,18 @@ export function getPanelMenu( text: 'Copy', onClick: onCopyPanel, }); + + if (isPanelModelLibraryPanel(panel)) { + subMenu.push({ + text: 'Unlink global panel', + onClick: onUnlinkLibraryPanel, + }); + } else { + subMenu.push({ + text: 'To global panel', + onClick: onAddLibraryPanel, + }); + } } // add old angular panel options diff --git a/public/app/features/dashboard/utils/panel.ts b/public/app/features/dashboard/utils/panel.ts index c39594c01f0..5bd9d101c8a 100644 --- a/public/app/features/dashboard/utils/panel.ts +++ b/public/app/features/dashboard/utils/panel.ts @@ -19,6 +19,8 @@ import { DEPRECATED_PANELS, LS_PANEL_COPY_KEY, PANEL_BORDER } from 'app/core/con import { ShareModal } from 'app/features/dashboard/components/ShareModal'; import { ShowConfirmModalEvent, ShowModalReactEvent } from '../../../types/events'; +import { AddLibraryPanelModal } from 'app/features/library-panels/components/AddLibraryPanelModal/AddLibraryPanelModal'; +import { UnlinkModal } from 'app/features/library-panels/components/UnlinkModal/UnlinkModal'; export const removePanel = (dashboard: DashboardModel, panel: PanelModel, ask: boolean) => { // confirm deletion @@ -71,6 +73,34 @@ export const sharePanel = (dashboard: DashboardModel, panel: PanelModel) => { ); }; +export const addLibraryPanel = (dashboard: DashboardModel, panel: PanelModel) => { + appEvents.publish( + new ShowModalReactEvent({ + component: AddLibraryPanelModal, + props: { + panel, + initialFolderId: dashboard.meta.folderId, + isOpen: true, + }, + }) + ); +}; + +export const unlinkLibraryPanel = (panel: PanelModel) => { + appEvents.publish( + new ShowModalReactEvent({ + component: UnlinkModal, + props: { + onConfirm: () => { + delete panel.libraryPanel; + panel.render(); + }, + isOpen: true, + }, + }) + ); +}; + export const refreshPanel = (panel: PanelModel) => { panel.refresh(); };