mirror of
https://github.com/grafana/grafana.git
synced 2024-11-25 02:10:45 -06:00
Fix panel paste button in nav toolbar (#90143)
fix panel paste button in nav toolbar
This commit is contained in:
parent
22df2d9b06
commit
f88bf474bd
@ -1,4 +1,4 @@
|
|||||||
import { CoreApp, LoadingState, getDefaultTimeRange } from '@grafana/data';
|
import { CoreApp, LoadingState, getDefaultTimeRange, store } from '@grafana/data';
|
||||||
import { locationService } from '@grafana/runtime';
|
import { locationService } from '@grafana/runtime';
|
||||||
import {
|
import {
|
||||||
sceneGraph,
|
sceneGraph,
|
||||||
@ -14,6 +14,7 @@ import {
|
|||||||
} from '@grafana/scenes';
|
} from '@grafana/scenes';
|
||||||
import { Dashboard, DashboardCursorSync, LibraryPanel } from '@grafana/schema';
|
import { Dashboard, DashboardCursorSync, LibraryPanel } from '@grafana/schema';
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
|
import { LS_PANEL_COPY_KEY } from 'app/core/constants';
|
||||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||||
import { VariablesChanged } from 'app/features/variables/types';
|
import { VariablesChanged } from 'app/features/variables/types';
|
||||||
|
|
||||||
@ -620,7 +621,7 @@ describe('DashboardScene', () => {
|
|||||||
|
|
||||||
scene.copyPanel(vizPanel);
|
scene.copyPanel(vizPanel);
|
||||||
|
|
||||||
expect(scene.state.hasCopiedPanel).toBe(false);
|
expect(store.exists(LS_PANEL_COPY_KEY)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should fail to copy a library panel if it does not have a grid item parent', () => {
|
it('Should fail to copy a library panel if it does not have a grid item parent', () => {
|
||||||
@ -638,14 +639,14 @@ describe('DashboardScene', () => {
|
|||||||
|
|
||||||
scene.copyPanel(libVizPanel.state.panel as VizPanel);
|
scene.copyPanel(libVizPanel.state.panel as VizPanel);
|
||||||
|
|
||||||
expect(scene.state.hasCopiedPanel).toBe(false);
|
expect(store.exists(LS_PANEL_COPY_KEY)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should copy a panel', () => {
|
it('Should copy a panel', () => {
|
||||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as DashboardGridItem).state.body;
|
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as DashboardGridItem).state.body;
|
||||||
scene.copyPanel(vizPanel as VizPanel);
|
scene.copyPanel(vizPanel as VizPanel);
|
||||||
|
|
||||||
expect(scene.state.hasCopiedPanel).toBe(true);
|
expect(store.exists(LS_PANEL_COPY_KEY)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should copy a library viz panel', () => {
|
it('Should copy a library viz panel', () => {
|
||||||
@ -654,11 +655,11 @@ describe('DashboardScene', () => {
|
|||||||
|
|
||||||
scene.copyPanel(libVizPanel.state.panel as VizPanel);
|
scene.copyPanel(libVizPanel.state.panel as VizPanel);
|
||||||
|
|
||||||
expect(scene.state.hasCopiedPanel).toBe(true);
|
expect(store.exists(LS_PANEL_COPY_KEY)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should paste a panel', () => {
|
it('Should paste a panel', () => {
|
||||||
scene.setState({ hasCopiedPanel: true });
|
store.set(LS_PANEL_COPY_KEY, JSON.stringify({ key: 'panel-7' }));
|
||||||
jest.spyOn(JSON, 'parse').mockReturnThis();
|
jest.spyOn(JSON, 'parse').mockReturnThis();
|
||||||
jest.mocked(buildGridItemForPanel).mockReturnValue(
|
jest.mocked(buildGridItemForPanel).mockReturnValue(
|
||||||
new DashboardGridItem({
|
new DashboardGridItem({
|
||||||
@ -680,11 +681,11 @@ describe('DashboardScene', () => {
|
|||||||
expect(body.state.children.length).toBe(6);
|
expect(body.state.children.length).toBe(6);
|
||||||
expect(gridItem.state.body!.state.key).toBe('panel-7');
|
expect(gridItem.state.body!.state.key).toBe('panel-7');
|
||||||
expect(gridItem.state.y).toBe(0);
|
expect(gridItem.state.y).toBe(0);
|
||||||
expect(scene.state.hasCopiedPanel).toBe(false);
|
expect(store.exists(LS_PANEL_COPY_KEY)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should paste a library viz panel', () => {
|
it('Should paste a library viz panel', () => {
|
||||||
scene.setState({ hasCopiedPanel: true });
|
store.set(LS_PANEL_COPY_KEY, JSON.stringify({ key: 'panel-7' }));
|
||||||
jest.spyOn(JSON, 'parse').mockReturnValue({ libraryPanel: { uid: 'uid', name: 'libraryPanel' } });
|
jest.spyOn(JSON, 'parse').mockReturnValue({ libraryPanel: { uid: 'uid', name: 'libraryPanel' } });
|
||||||
jest.mocked(buildGridItemForLibPanel).mockReturnValue(
|
jest.mocked(buildGridItemForLibPanel).mockReturnValue(
|
||||||
new DashboardGridItem({
|
new DashboardGridItem({
|
||||||
@ -709,7 +710,7 @@ describe('DashboardScene', () => {
|
|||||||
expect(libVizPanel.state.panelKey).toBe('panel-7');
|
expect(libVizPanel.state.panelKey).toBe('panel-7');
|
||||||
expect(libVizPanel.state.panel?.state.key).toBe('panel-7');
|
expect(libVizPanel.state.panel?.state.key).toBe('panel-7');
|
||||||
expect(gridItem.state.y).toBe(0);
|
expect(gridItem.state.y).toBe(0);
|
||||||
expect(scene.state.hasCopiedPanel).toBe(false);
|
expect(store.exists(LS_PANEL_COPY_KEY)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should remove a panel', () => {
|
it('Should remove a panel', () => {
|
||||||
|
@ -121,8 +121,6 @@ export interface DashboardSceneState extends SceneObjectState {
|
|||||||
editPanel?: PanelEditor;
|
editPanel?: PanelEditor;
|
||||||
/** Scene object that handles the current drawer or modal */
|
/** Scene object that handles the current drawer or modal */
|
||||||
overlay?: SceneObject;
|
overlay?: SceneObject;
|
||||||
/** True when a user copies a panel in the dashboard */
|
|
||||||
hasCopiedPanel?: boolean;
|
|
||||||
/** The dashboard doesn't have panels */
|
/** The dashboard doesn't have panels */
|
||||||
isEmpty?: boolean;
|
isEmpty?: boolean;
|
||||||
/** Scene object that handles the scopes selector */
|
/** Scene object that handles the scopes selector */
|
||||||
@ -172,7 +170,6 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
|||||||
editable: true,
|
editable: true,
|
||||||
body: state.body ?? new SceneFlexLayout({ children: [] }),
|
body: state.body ?? new SceneFlexLayout({ children: [] }),
|
||||||
links: state.links ?? [],
|
links: state.links ?? [],
|
||||||
hasCopiedPanel: store.exists(LS_PANEL_COPY_KEY),
|
|
||||||
scopes: state.uid && config.featureToggles.scopeFilters ? new ScopesScene() : undefined,
|
scopes: state.uid && config.featureToggles.scopeFilters ? new ScopesScene() : undefined,
|
||||||
...state,
|
...state,
|
||||||
});
|
});
|
||||||
@ -648,7 +645,6 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
|||||||
|
|
||||||
store.set(LS_PANEL_COPY_KEY, JSON.stringify(jsonData));
|
store.set(LS_PANEL_COPY_KEY, JSON.stringify(jsonData));
|
||||||
appEvents.emit(AppEvents.alertSuccess, ['Panel copied. Use **Paste panel** toolbar action to paste.']);
|
appEvents.emit(AppEvents.alertSuccess, ['Panel copied. Use **Paste panel** toolbar action to paste.']);
|
||||||
this.setState({ hasCopiedPanel: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public pastePanel() {
|
public pastePanel() {
|
||||||
@ -703,7 +699,6 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
|||||||
children: [gridItem, ...sceneGridLayout.state.children],
|
children: [gridItem, ...sceneGridLayout.state.children],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({ hasCopiedPanel: false });
|
|
||||||
store.delete(LS_PANEL_COPY_KEY);
|
store.delete(LS_PANEL_COPY_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { css } from '@emotion/css';
|
|||||||
import { useEffect, useId, useState } from 'react';
|
import { useEffect, useId, useState } from 'react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2, store } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { config, locationService } from '@grafana/runtime';
|
import { config, locationService } from '@grafana/runtime';
|
||||||
import {
|
import {
|
||||||
@ -18,6 +18,7 @@ import {
|
|||||||
} from '@grafana/ui';
|
} from '@grafana/ui';
|
||||||
import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate';
|
import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate';
|
||||||
import { NavToolbarSeparator } from 'app/core/components/AppChrome/NavToolbar/NavToolbarSeparator';
|
import { NavToolbarSeparator } from 'app/core/components/AppChrome/NavToolbar/NavToolbarSeparator';
|
||||||
|
import { LS_PANEL_COPY_KEY } from 'app/core/constants';
|
||||||
import { contextSrv } from 'app/core/core';
|
import { contextSrv } from 'app/core/core';
|
||||||
import { Trans, t } from 'app/core/internationalization';
|
import { Trans, t } from 'app/core/internationalization';
|
||||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||||
@ -51,17 +52,7 @@ NavToolbarActions.displayName = 'NavToolbarActions';
|
|||||||
* This part is split into a separate component to help test this
|
* This part is split into a separate component to help test this
|
||||||
*/
|
*/
|
||||||
export function ToolbarActions({ dashboard }: Props) {
|
export function ToolbarActions({ dashboard }: Props) {
|
||||||
const {
|
const { isEditing, viewPanelScene, isDirty, uid, meta, editview, editPanel, editable } = dashboard.useState();
|
||||||
isEditing,
|
|
||||||
viewPanelScene,
|
|
||||||
isDirty,
|
|
||||||
uid,
|
|
||||||
meta,
|
|
||||||
editview,
|
|
||||||
editPanel,
|
|
||||||
editable,
|
|
||||||
hasCopiedPanel: copiedPanel,
|
|
||||||
} = dashboard.useState();
|
|
||||||
const { isPlaying } = playlistSrv.useState();
|
const { isPlaying } = playlistSrv.useState();
|
||||||
const [isAddPanelMenuOpen, setIsAddPanelMenuOpen] = useState(false);
|
const [isAddPanelMenuOpen, setIsAddPanelMenuOpen] = useState(false);
|
||||||
|
|
||||||
@ -72,7 +63,7 @@ export function ToolbarActions({ dashboard }: Props) {
|
|||||||
const isViewingPanel = Boolean(viewPanelScene);
|
const isViewingPanel = Boolean(viewPanelScene);
|
||||||
const isEditedPanelDirty = useVizManagerDirty(editPanel);
|
const isEditedPanelDirty = useVizManagerDirty(editPanel);
|
||||||
const isEditingLibraryPanel = useEditingLibraryPanel(editPanel);
|
const isEditingLibraryPanel = useEditingLibraryPanel(editPanel);
|
||||||
const hasCopiedPanel = Boolean(copiedPanel);
|
const hasCopiedPanel = store.exists(LS_PANEL_COPY_KEY);
|
||||||
// Means we are not in settings view, fullscreen panel or edit panel
|
// Means we are not in settings view, fullscreen panel or edit panel
|
||||||
const isShowingDashboard = !editview && !isViewingPanel && !isEditingPanel;
|
const isShowingDashboard = !editview && !isViewingPanel && !isEditingPanel;
|
||||||
const isEditingAndShowingDashboard = isEditing && isShowingDashboard;
|
const isEditingAndShowingDashboard = isEditing && isShowingDashboard;
|
||||||
|
Loading…
Reference in New Issue
Block a user