Dashboards: Fix edit button visibility to respect editable flag in new layouts (#115372)
Dashboard in `editable: false` mode
This commit is contained in:
@@ -1,11 +1,21 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { SceneVariableSet, ScopesVariable, TextBoxVariable } from '@grafana/scenes';
|
||||
import { playlistSrv } from 'app/features/playlist/PlaylistSrv';
|
||||
|
||||
import { DashboardControls, DashboardControlsState } from './DashboardControls';
|
||||
import { DashboardScene } from './DashboardScene';
|
||||
|
||||
jest.mock('app/features/playlist/PlaylistSrv', () => ({
|
||||
playlistSrv: {
|
||||
useState: jest.fn().mockReturnValue({ isPlaying: false }),
|
||||
state: { isPlaying: false },
|
||||
stop: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('DashboardControls', () => {
|
||||
describe('Given a standard scene', () => {
|
||||
it('should initialize with default values', () => {
|
||||
@@ -221,8 +231,85 @@ describe('DashboardControls', () => {
|
||||
expect(setState).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('DashboardControlActions editable flag', () => {
|
||||
const originalFeatureToggles = { ...config.featureToggles };
|
||||
|
||||
beforeEach(() => {
|
||||
config.featureToggles.dashboardNewLayouts = true;
|
||||
jest.mocked(playlistSrv.useState).mockReturnValue({ isPlaying: false });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
config.featureToggles = originalFeatureToggles;
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should show EditDashboardSwitch when editable is true', async () => {
|
||||
const controls = buildTestSceneWithEditable({ editable: true, canEdit: true });
|
||||
render(<controls.Component model={controls} />);
|
||||
|
||||
expect(await screen.findByRole('button', { name: /edit/i })).toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: /make editable/i })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show MakeDashboardEditableButton when editable is false', async () => {
|
||||
const controls = buildTestSceneWithEditable({ editable: false, canEdit: false, canMakeEditable: true });
|
||||
render(<controls.Component model={controls} />);
|
||||
|
||||
expect(await screen.findByRole('button', { name: /make editable/i })).toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: /^edit$/i })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show edit buttons when canEditDashboard returns false', async () => {
|
||||
const controls = buildTestSceneWithEditable({
|
||||
editable: true,
|
||||
canEdit: false,
|
||||
canMakeEditable: false,
|
||||
isSnapshot: true,
|
||||
});
|
||||
render(<controls.Component model={controls} />);
|
||||
|
||||
expect(screen.queryByRole('button', { name: /edit/i })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: /make editable/i })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show edit buttons when playlist is playing', async () => {
|
||||
jest.mocked(playlistSrv.useState).mockReturnValue({ isPlaying: true });
|
||||
|
||||
const controls = buildTestSceneWithEditable({ editable: true, canEdit: true });
|
||||
render(<controls.Component model={controls} />);
|
||||
|
||||
expect(screen.queryByRole('button', { name: /^edit$/i })).not.toBeInTheDocument();
|
||||
expect(await screen.findByTestId(selectors.pages.Dashboard.DashNav.playlistControls.stop)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function buildTestSceneWithEditable(options: {
|
||||
editable: boolean;
|
||||
canEdit?: boolean;
|
||||
canMakeEditable?: boolean;
|
||||
isSnapshot?: boolean;
|
||||
}): DashboardControls {
|
||||
const { editable, canEdit = true, canMakeEditable = false, isSnapshot = false } = options;
|
||||
|
||||
const dashboard = new DashboardScene({
|
||||
uid: 'test-uid',
|
||||
editable,
|
||||
meta: {
|
||||
canEdit,
|
||||
canMakeEditable,
|
||||
isSnapshot,
|
||||
},
|
||||
controls: new DashboardControls({}),
|
||||
});
|
||||
|
||||
dashboard.activate();
|
||||
|
||||
return dashboard.state.controls as DashboardControls;
|
||||
}
|
||||
|
||||
function buildTestScene(state?: Partial<DashboardControlsState>): DashboardControls {
|
||||
const variable = new TextBoxVariable({
|
||||
name: 'A',
|
||||
|
||||
@@ -31,6 +31,7 @@ import { VariableControls } from './VariableControls';
|
||||
import { DashboardControlsButton } from './dashboard-controls-menu/DashboardControlsMenuButton';
|
||||
import { hasDashboardControls, useHasDashboardControls } from './dashboard-controls-menu/utils';
|
||||
import { EditDashboardSwitch } from './new-toolbar/actions/EditDashboardSwitch';
|
||||
import { MakeDashboardEditableButton } from './new-toolbar/actions/MakeDashboardEditableButton';
|
||||
import { SaveDashboard } from './new-toolbar/actions/SaveDashboard';
|
||||
import { ShareDashboardButton } from './new-toolbar/actions/ShareDashboardButton';
|
||||
|
||||
@@ -191,7 +192,7 @@ function DashboardControlsRenderer({ model }: SceneComponentProps<DashboardContr
|
||||
}
|
||||
|
||||
function DashboardControlActions({ dashboard }: { dashboard: DashboardScene }) {
|
||||
const { isEditing, editPanel, uid, meta } = dashboard.useState();
|
||||
const { isEditing, editPanel, uid, meta, editable } = dashboard.useState();
|
||||
const { isPlaying } = playlistSrv.useState();
|
||||
|
||||
if (editPanel) {
|
||||
@@ -201,13 +202,17 @@ function DashboardControlActions({ dashboard }: { dashboard: DashboardScene }) {
|
||||
const canEditDashboard = dashboard.canEditDashboard();
|
||||
const hasUid = Boolean(uid);
|
||||
const isSnapshot = Boolean(meta.isSnapshot);
|
||||
const isEditable = Boolean(editable);
|
||||
const showShareButton = hasUid && !isSnapshot && !isPlaying;
|
||||
|
||||
return (
|
||||
<>
|
||||
{showShareButton && <ShareDashboardButton dashboard={dashboard} />}
|
||||
{isEditing && <SaveDashboard dashboard={dashboard} />}
|
||||
{!isPlaying && canEditDashboard && <EditDashboardSwitch dashboard={dashboard} />}
|
||||
{!isPlaying && canEditDashboard && isEditable && <EditDashboardSwitch dashboard={dashboard} />}
|
||||
{!isPlaying && canEditDashboard && !isEditable && !isEditing && (
|
||||
<MakeDashboardEditableButton dashboard={dashboard} />
|
||||
)}
|
||||
{isPlaying && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
|
||||
-1
@@ -17,7 +17,6 @@ export const MakeDashboardEditableButton = ({ dashboard }: ToolbarActionProps) =
|
||||
}}
|
||||
tooltip={t('dashboard.toolbar.new.enter-edit-mode.tooltip', 'This dashboard was marked as read only')}
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
data-testid={selectors.components.NavToolbar.editDashboard.editButton}
|
||||
>
|
||||
<Trans i18nKey="dashboard.toolbar.new.enter-edit-mode.label">Make editable</Trans>
|
||||
|
||||
Reference in New Issue
Block a user