Skip to content

Commit

Permalink
ui/dashboard: Add network plane health in Network panel
Browse files Browse the repository at this point in the history
		Remove the ServiceItem from DashboardServices and create the HealthItem component with it
		Add DashboardPlane component containing 2 HealthItems
		Add tests for the new DashbordPlane component
		history.push replaced by history.replace in the HealthItem component
		useless comment removed in HealthItem component
Ref:	#3511
  • Loading branch information
Julien MEZIERE committed Sep 17, 2021
1 parent cba3846 commit 4fd1f63
Show file tree
Hide file tree
Showing 10 changed files with 405 additions and 154 deletions.
2 changes: 1 addition & 1 deletion shell-ui/src/alerts/alertHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const getVolumesAlertSelectors = (): FilterLabels => {

export const getNetworksAlertSelectors = (): FilterLabels => {
return {
alertname: ['ControlPlaneNetworkDegraded', 'WorkloadPlaneNetworkDegraded'],
alertname: ['NetworkDegraded'],
};
};

Expand Down
37 changes: 37 additions & 0 deletions ui/src/components/DashboardNetwork.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import styled from 'styled-components';
import { useIntl } from 'react-intl';

import { spacing } from '@scality/core-ui/dist/style/theme';
import { PageSubtitle } from '../components/style/CommonLayoutStyle';

import DashboardPlane from './DashboardPlane';

export const NetworkContainer = styled.div`
padding: ${spacing.sp2} ${spacing.sp4};
display: flex;
flex-direction: column;
flex-grow: 1;
`;

export const PanelActions = styled.div`
display: flex;
padding: ${spacing.sp4};
align-items: center;
justify-content: space-between;
`;

const DashboardNetwork = () => {
const intl = useIntl();

return (
<NetworkContainer>
<PanelActions>
<PageSubtitle>{intl.formatMessage({ id: 'network' })}</PageSubtitle>
</PanelActions>
<DashboardPlane />
</NetworkContainer>
);
};

export default DashboardNetwork;
62 changes: 62 additions & 0 deletions ui/src/components/DashboardPlane.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react';
import { useIntl } from 'react-intl';
import styled from 'styled-components';
import {
useAlertLibrary,
useHighestSeverityAlerts,
highestAlertToStatus,
} from '../containers/AlertProvider';
import { PageSubtitle } from './style/CommonLayoutStyle';
import { PanelActions, NetworkContainer } from './DashboardNetwork';
import HealthItem from './HealthItem.js';
import { spacing } from '@scality/core-ui/dist/style/theme';

const PlanesContainer = styled.div`
padding-left: ${spacing.sp8};
display: flex;
flex-direction: row;
`;

const PlaneContainer = styled.div`
display: flex;
flex-direction: row;
margin-right: ${spacing.sp40};
`;

const DashboardPlane = () => {
const intl = useIntl();
const alertsLibrary = useAlertLibrary();

const planesHighestSecurityAlert = useHighestSeverityAlerts(
alertsLibrary.getNetworksAlertSelectors(),
);
const planesStatus = highestAlertToStatus(planesHighestSecurityAlert);

return (
<NetworkContainer>
<PanelActions>
<PageSubtitle>Planes</PageSubtitle>
</PanelActions>
<PlanesContainer>
<PlaneContainer>
<HealthItem
label={intl.formatMessage({ id: 'control_plane' })}
status={planesStatus}
alerts={planesHighestSecurityAlert}
showArrow={false}
/>
</PlaneContainer>
<PlaneContainer>
<HealthItem
label={intl.formatMessage({ id: 'workload_plane' })}
status={planesStatus}
alerts={planesHighestSecurityAlert}
showArrow={false}
/>
</PlaneContainer>
</PlanesContainer>
</NetworkContainer>
);
};

export default DashboardPlane;
102 changes: 102 additions & 0 deletions ui/src/components/DashboardPlane.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//@flow
import React from 'react';
import { screen } from '@testing-library/react';
import DashboardPlane from './DashboardPlane';
import { render } from './__TEST__/util';
import type { Alert } from '../services/alertUtils';
import { useHighestSeverityAlerts } from '../containers/AlertProvider';
import {
STATUS_WARNING,
STATUS_CRITICAL,
STATUS_HEALTH,
} from '../constants.js';

const alertsCritical = [
{
id: 'alert1',
severity: STATUS_CRITICAL,
startsAt: '2021-07-28T10:36:24.293Z',
},
];
const alertsWarning = [
{
id: 'alert2',
severity: STATUS_WARNING,
startsAt: '2021-07-28T10:36:24.293Z',
},
];
const noAlerts = [];

jest.mock('../containers/AlertProvider', () => ({
__esModule: true,
default: ({ children }) => <>{children}</>,
useHighestSeverityAlerts: jest.fn(),
useAlertLibrary: () => ({
getNetworksAlertSelectors: () => {},
}),
highestAlertToStatus: (alerts?: Alert[]): string => {
return (alerts?.[0] && ((alerts[0].severity: any): string)) || 'healthy';
},
}));

jest.mock('../containers/ConfigProvider', () => ({
__esModule: true,
default: ({ children }) => <>{children}</>,
useLinkOpener: () => ({
openLink: jest.fn(),
}),
useDiscoveredViews: () => [
{
app: {
kind: '',
name: '',
version: '',
url: '',
appHistoryBasePath: '',
},
isFederated: true,
view: { path: '/alerts' },
},
],
}));

const NB_ITEMS = 2;

describe("the dashboard network's plane panel", () => {
test("displays the network's plane panel and display 2 green statuses when no alerts are present", async () => {
// Have to any type jest.fn function to avoid Flow warning for mockImplementation()
(useHighestSeverityAlerts: any).mockImplementation(() => noAlerts);
render(<DashboardPlane />);
expect(screen.getAllByLabelText(`status ${STATUS_HEALTH}`)).toHaveLength(
NB_ITEMS,
);
});

test('displays 2 warning statuses when warning alerts are present as well as link to the alerts page', async () => {
// Have to any type jest.fn function to avoid Flow warning for mockImplementation()
(useHighestSeverityAlerts: any).mockImplementation(() => alertsWarning);

// Render
render(<DashboardPlane />);

// Verify
expect(screen.getAllByLabelText(`status ${STATUS_WARNING}`)).toHaveLength(
NB_ITEMS,
);
expect(screen.getAllByTestId('alert-link')).toHaveLength(NB_ITEMS);
});

test('displays 2 critical statuses when warning alerts are present as well as link to the alerts page', async () => {
// Have to any type jest.fn function to avoid Flow warning for mockImplementation()
(useHighestSeverityAlerts: any).mockImplementation(() => alertsCritical);

// Render
render(<DashboardPlane />);

// Verify
expect(screen.getAllByLabelText(`status ${STATUS_CRITICAL}`)).toHaveLength(
NB_ITEMS,
);
expect(screen.getAllByTestId('alert-link')).toHaveLength(NB_ITEMS);
});
});
Loading

0 comments on commit 4fd1f63

Please sign in to comment.