Skip to content

Commit

Permalink
[SecuritySolution] Fix minimize amd maximize panel actions (elastic#1…
Browse files Browse the repository at this point in the history
…56518)

## Summary

Issues: elastic#155857 |
elastic#156253

This PR fixed minimize amd maximize panel actions in Security Dashboard
view.

https://user-images.githubusercontent.com/6295984/235910244-1cca8dda-cd4c-40b7-977a-69fa00021f81.mov

### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: Pablo Machado <[email protected]>
(cherry picked from commit c278f4e)
  • Loading branch information
angorayc committed May 3, 2023
1 parent df0d097 commit 70eb80b
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
import { render } from '@testing-library/react';
import React from 'react';
import { DashboardViewPromptState } from '../hooks/use_dashboard_view_prompt_state';
import { StatusPropmpt } from './status_prompt';
import { StatusPrompt } from './status_prompt';

describe('StatusPropmpt', () => {
describe('StatusPrompt', () => {
it('hides by default', () => {
const { queryByTestId } = render(<StatusPropmpt currentState={null} />);
const { queryByTestId } = render(<StatusPrompt currentState={null} />);
expect(queryByTestId(`dashboardViewEmptyDefault`)).not.toBeInTheDocument();
});

it('shows when No Read Permission', () => {
const { queryByTestId } = render(
<StatusPropmpt currentState={DashboardViewPromptState.NoReadPermission} />
<StatusPrompt currentState={DashboardViewPromptState.NoReadPermission} />
);

expect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { EuiPageTemplate } from '@elastic/eui';
import type { DashboardViewPromptState } from '../hooks/use_dashboard_view_prompt_state';
import { useDashboardViewPromptState } from '../hooks/use_dashboard_view_prompt_state';

const StatusPropmptComponent = ({
const StatusPromptComponent = ({
currentState,
}: {
currentState: DashboardViewPromptState | null;
Expand All @@ -21,5 +21,5 @@ const StatusPropmptComponent = ({
</EuiPageTemplate>
) : null;
};
StatusPropmptComponent.displayName = 'StatusPropmptComponent';
export const StatusPropmpt = React.memo(StatusPropmptComponent);
StatusPromptComponent.displayName = 'StatusPromptComponent';
export const StatusPrompt = React.memo(StatusPromptComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { render } from '@testing-library/react';
import React from 'react';
import { Router } from 'react-router-dom';
import { DashboardView } from '.';
import { useCapabilities } from '../../../common/lib/kibana';
import { TestProviders } from '../../../common/mock';

jest.mock('react-router-dom', () => {
const actual = jest.requireActual('react-router-dom');
return {
...actual,
useParams: jest.fn().mockReturnValue({ detailName: 'mockSavedObjectId' }),
};
});

jest.mock('../../../common/lib/kibana', () => {
const actual = jest.requireActual('../../../common/lib/kibana');
return {
...actual,
useCapabilities: jest.fn().mockReturnValue({ show: true, showWriteControls: true }),
};
});

jest.mock('../../../common/components/dashboards/dashboard_renderer', () => ({
DashboardRenderer: jest
.fn()
.mockImplementation((props) => (
<div data-test-subj={`dashboard-view-${props.savedObjectId}`} />
)),
}));

type Action = 'PUSH' | 'POP' | 'REPLACE';
const pop: Action = 'POP';
const location = {
pathname: '/network',
search: '',
state: '',
hash: '',
};
const mockHistory = {
length: 2,
location,
action: pop,
push: jest.fn(),
replace: jest.fn(),
go: jest.fn(),
goBack: jest.fn(),
goForward: jest.fn(),
block: jest.fn(),
createHref: jest.fn(),
listen: jest.fn(),
};

describe('DashboardView', () => {
beforeEach(() => {
(useCapabilities as unknown as jest.Mock).mockReturnValue({
show: true,
showWriteControls: true,
});
});
test('render when no error state', () => {
const { queryByTestId } = render(
<Router history={mockHistory}>
<DashboardView />
</Router>,
{ wrapper: TestProviders }
);

expect(queryByTestId(`dashboard-view-mockSavedObjectId`)).toBeInTheDocument();
});

test('render a prompt when error state exists', () => {
(useCapabilities as unknown as jest.Mock).mockReturnValue({
show: false,
showWriteControls: true,
});
const { queryByTestId } = render(
<Router history={mockHistory}>
<DashboardView />
</Router>,
{ wrapper: TestProviders }
);

expect(queryByTestId(`dashboard-view-mockSavedObjectId`)).not.toBeInTheDocument();
expect(queryByTestId(`dashboard-view-error-prompt-wrapper`)).toBeInTheDocument();
});

test('render dashboard view with height', () => {
const { queryByTestId } = render(
<Router history={mockHistory}>
<DashboardView />
</Router>,
{ wrapper: TestProviders }
);

expect(queryByTestId(`dashboard-view-wrapper`)).toHaveStyle({
'min-height': `calc(100vh - 140px)`,
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import type { DashboardCapabilities } from '@kbn/dashboard-plugin/common/types';
import { useParams } from 'react-router-dom';

import { pick } from 'lodash/fp';
import { EuiLoadingSpinner } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
import { SecurityPageName } from '../../../../common/constants';
import { SpyRoute } from '../../../common/utils/route/spy_routes';
import { useCapabilities } from '../../../common/lib/kibana';
import { DashboardViewPromptState } from '../../hooks/use_dashboard_view_prompt_state';
import { DashboardRenderer } from '../../../common/components/dashboards/dashboard_renderer';
import { StatusPropmpt } from '../../components/status_prompt';
import { StatusPrompt } from '../../components/status_prompt';
import { SiemSearchBar } from '../../../common/components/search_bar';
import { SecuritySolutionPageWrapper } from '../../../common/components/page_wrapper';
import { FiltersGlobal } from '../../../common/components/filters_global';
Expand All @@ -33,6 +33,8 @@ import { EditDashboardButton } from '../../components/edit_dashboard_button';

type DashboardDetails = Record<string, string>;

const dashboardViewFlexGroupStyle = { minHeight: `calc(100vh - 140px)` };

const DashboardViewComponent: React.FC = () => {
const { fromStr, toStr, from, to } = useDeepEqualSelector((state) =>
pick(['fromStr', 'toStr', 'from', 'to'], inputsSelectors.globalTimeRangeSelector(state))
Expand Down Expand Up @@ -76,34 +78,47 @@ const DashboardViewComponent: React.FC = () => {
</FiltersGlobal>
)}
<SecuritySolutionPageWrapper>
<HeaderPage border title={dashboardDetails?.title ?? <EuiLoadingSpinner size="m" />}>
{showWriteControls && dashboardExists && (
<EditDashboardButton
filters={filters}
query={query}
savedObjectId={savedObjectId}
timeRange={timeRange}
/>
<EuiFlexGroup
direction="column"
style={dashboardViewFlexGroupStyle}
gutterSize="none"
data-test-subj="dashboard-view-wrapper"
>
<EuiFlexItem grow={false}>
<HeaderPage border title={dashboardDetails?.title ?? <EuiLoadingSpinner size="m" />}>
{showWriteControls && dashboardExists && (
<EditDashboardButton
filters={filters}
query={query}
savedObjectId={savedObjectId}
timeRange={timeRange}
/>
)}
</HeaderPage>
</EuiFlexItem>
{!errorState && (
<EuiFlexItem grow>
<DashboardRenderer
query={query}
filters={filters}
canReadDashboard={canReadDashboard}
id={`dashboard-view-${savedObjectId}`}
onDashboardContainerLoaded={onDashboardContainerLoaded}
savedObjectId={savedObjectId}
timeRange={timeRange}
/>
</EuiFlexItem>
)}
</HeaderPage>

{!errorState && (
<DashboardRenderer
query={query}
filters={filters}
canReadDashboard={canReadDashboard}
id={`dashboard-view-${savedObjectId}`}
onDashboardContainerLoaded={onDashboardContainerLoaded}
savedObjectId={savedObjectId}
timeRange={timeRange}
{errorState && (
<EuiFlexItem data-test-subj="dashboard-view-error-prompt-wrapper" grow>
<StatusPrompt currentState={errorState} />
</EuiFlexItem>
)}
<SpyRoute
pageName={SecurityPageName.dashboards}
state={{ dashboardName: dashboardDetails?.title }}
/>
)}

<StatusPropmpt currentState={errorState} />
<SpyRoute
pageName={SecurityPageName.dashboards}
state={{ dashboardName: dashboardDetails?.title }}
/>
</EuiFlexGroup>
</SecuritySolutionPageWrapper>
</>
);
Expand Down

0 comments on commit 70eb80b

Please sign in to comment.