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

Ref: #3511
  • Loading branch information
Julien MEZIERE authored and JBWatenbergScality committed Sep 24, 2021
1 parent 8a8508d commit afd040f
Show file tree
Hide file tree
Showing 10 changed files with 408 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 afd040f

Please sign in to comment.