Skip to content

Commit

Permalink
upcoming: [M3-7303] - Replace Managed summary charts with Recharts (l…
Browse files Browse the repository at this point in the history
…inode#10001)

## Description 📝
Replace Managed summary charts with Recharts
- CPU Usage chart
- Network Transfer chart
- Disk I/O chart

## How to test 🧪
### Prerequisites
(How to setup test environment)
- Have an account that's Managed (you can do so via admin)

### Verification steps 
(How to verify changes)
- Go to `/managed/summary` and verify the updated UI and that there are no regressions in the graph, units, etc 
  - X and Y axis labels will not match exactly but the data from hovering over the graph should still be the same
  • Loading branch information
hana-akamai authored Jan 4, 2024
1 parent 98fac84 commit 6292d01
Show file tree
Hide file tree
Showing 16 changed files with 1,114 additions and 215 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Replace Managed summary charts with Recharts ([#10001](https://github.com/linode/manager/pull/10001))
138 changes: 0 additions & 138 deletions packages/manager/src/components/AreaChart.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { render } from '@testing-library/react';
import React from 'react';

import { AccessibleAreaChart } from './AccessibleAreaChart';

const data1 = [
{ 'Dataset 1': 10, timestamp: 1631026800000 },
{ 'Dataset 1': 20, timestamp: 1631030400000 },
{ 'Dataset 1': 30, timestamp: 1631034000000 },
];

describe('AccessibleAreaChart', () => {
it('renders a table with correct data', () => {
const { getAllByRole } = render(
<AccessibleAreaChart
ariaLabel="data filter"
data={data1}
dataKeys={['Dataset 1']}
timezone="America/New_York"
unit="%"
/>
);

// Check that the component renders
const table = getAllByRole('table')[0];
expect(table).toBeInTheDocument();

// Check that the table has the correct summary attribute
expect(table).toHaveAttribute(
'summary',
'This table contains the data for the data filter (Dataset 1)'
);

// Check that the table header is correct
const tableHeader = table.querySelector('thead > tr');
expect(tableHeader).toHaveTextContent('Time');
expect(tableHeader).toHaveTextContent('Dataset 1');

// Check that the table data is correct in the body
const tableBodyRows = table.querySelectorAll('tbody > tr');
expect(tableBodyRows.length).toEqual(3);

tableBodyRows.forEach((row, idx) => {
const value = data1[idx]['Dataset 1'].toFixed(2);

expect(row.querySelector('td:nth-child(2)')).toHaveTextContent(
value + '%'
);
});
});
});
68 changes: 68 additions & 0 deletions packages/manager/src/components/AreaChart/AccessibleAreaChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { visuallyHidden } from '@mui/utils';
import * as React from 'react';

import { Box } from 'src/components/Box';

import { getAccessibleTimestamp } from './utils';

export interface AccessibleAreaChartProps {
ariaLabel?: string;
data: any;
dataKeys: string[];
timezone: string;
unit: string;
}

/**
* This component is used to provide an accessible representation of the data
* It does not care about styles, it only cares about presenting the data in bare HTML tables,
* visually hidden from the user, yet available to screen readers.
*/
export const AccessibleAreaChart = (props: AccessibleAreaChartProps) => {
const { ariaLabel, data, dataKeys, timezone, unit } = props;

const tables = dataKeys.map((dataKey, tableID) => {
const TableHeader = (
<tr>
<th>Time</th>
<th>{dataKey}</th>
</tr>
);

const TableBody =
data &&
data.map((entry: any, idx: number) => {
const { [dataKey]: value, timestamp } = entry;

return (
<tr key={`accessible-graph-data-body-row-${idx}`}>
<td>
{timestamp
? getAccessibleTimestamp(Number(timestamp), timezone)
: 'timestamp unavailable'}
</td>
<td>
{value !== undefined
? Number(value).toFixed(2)
: 'value unavailable'}
{value !== undefined && unit}
</td>
</tr>
);
});

return (
<table
summary={`This table contains the data for the ${
ariaLabel && dataKey ? ariaLabel + ` (${dataKey})` : 'graph below'
}`}
key={`accessible-graph-data-table-${tableID}`}
>
<thead>{TableHeader}</thead>
<tbody>{TableBody}</tbody>
</table>
);
});

return <Box sx={visuallyHidden}>{tables}</Box>;
};
36 changes: 36 additions & 0 deletions packages/manager/src/components/AreaChart/AreaChart.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';

import { AreaChart } from './AreaChart';
import { timeData } from './utils';

import type { Meta, StoryObj } from '@storybook/react';

const meta: Meta<typeof AreaChart> = {
component: AreaChart,
title: 'Components/Graphs/AreaChart',
};

export default meta;

type Story = StoryObj<typeof AreaChart>;

export const Default: Story = {
args: {
areas: [
{
color: '#1CB35C',
dataKey: 'Public Outbound Traffic',
},
],
ariaLabel: 'Network Transfer History Graph',
data: timeData,
height: 190,
timezone: 'UTC',
unit: ` Kb/s`,
xAxis: {
tickFormat: 'LLL dd',
tickGap: 30,
},
},
render: (args) => <AreaChart {...args} />,
};
41 changes: 41 additions & 0 deletions packages/manager/src/components/AreaChart/AreaChart.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import * as React from 'react';

import { renderWithTheme } from 'src/utilities/testHelpers';

import { AreaChart } from './AreaChart';
import { timeData } from './utils';

const props = {
areas: [
{
color: '#1CB35C',
dataKey: 'Public Outbound Traffic',
},
],
ariaLabel: 'Network Transfer History Graph',
data: timeData,
height: 190,
timezone: 'UTC',
unit: ` Kb/s`,
xAxis: {
tickFormat: 'LLL dd',
tickGap: 30,
},
};

class ResizeObserver {
disconnect() {}
observe() {}
unobserve() {}
}

describe('AreaChart', () => {
window.ResizeObserver = ResizeObserver;
it('renders an AreaChart', () => {
const { container } = renderWithTheme(<AreaChart {...props} />);

expect(container.querySelector('recharts-responsive-container'))
.toBeVisible;
});
});
Loading

0 comments on commit 6292d01

Please sign in to comment.