diff --git a/packages/manager/.changeset/pr-10037-upcoming-features-1704490133740.md b/packages/manager/.changeset/pr-10037-upcoming-features-1704490133740.md new file mode 100644 index 00000000000..9a438c13061 --- /dev/null +++ b/packages/manager/.changeset/pr-10037-upcoming-features-1704490133740.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Replace Linode details Analytics tab with Recharts ([#10037](https://github.com/linode/manager/pull/10037)) diff --git a/packages/manager/src/components/AreaChart/AreaChart.stories.tsx b/packages/manager/src/components/AreaChart/AreaChart.stories.tsx index 806a14088bd..bd9f8fcf682 100644 --- a/packages/manager/src/components/AreaChart/AreaChart.stories.tsx +++ b/packages/manager/src/components/AreaChart/AreaChart.stories.tsx @@ -1,12 +1,22 @@ import React from 'react'; +import { tooltipValueFormatter } from 'src/components/AreaChart/utils'; +import { getMetrics } from 'src/utilities/statMetrics'; + import { AreaChart } from './AreaChart'; -import { timeData } from './utils'; +import { customLegendData, timeData } from './utils'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryFn, StoryObj } from '@storybook/react'; const meta: Meta = { component: AreaChart, + decorators: [ + (Story: StoryFn) => ( +
+ +
+ ), + ], title: 'Components/Graphs/AreaChart', }; @@ -24,7 +34,38 @@ export const Default: Story = { ], ariaLabel: 'Network Transfer History Graph', data: timeData, - height: 190, + height: 300, + showLegend: true, + timezone: 'UTC', + unit: ` Kb/s`, + xAxis: { + tickFormat: 'LLL dd', + tickGap: 30, + }, + }, + render: (args) => , +}; + +export const CustomLegend: Story = { + args: { + areas: [ + { + color: '#1CB35C', + dataKey: 'Public Outbound Traffic', + }, + ], + ariaLabel: 'Network Transfer History Graph', + data: timeData, + height: 360, + legendRows: [ + { + data: getMetrics(customLegendData), + format: (value: number) => tooltipValueFormatter(value, ' Kb/s'), + legendColor: 'lightGreen', + legendTitle: 'Public Outbound Traffic', + }, + ], + showLegend: true, timezone: 'UTC', unit: ` Kb/s`, xAxis: { diff --git a/packages/manager/src/components/AreaChart/AreaChart.tsx b/packages/manager/src/components/AreaChart/AreaChart.tsx index 70f3670756a..5e860b6d241 100644 --- a/packages/manager/src/components/AreaChart/AreaChart.tsx +++ b/packages/manager/src/components/AreaChart/AreaChart.tsx @@ -15,7 +15,10 @@ import { } from 'recharts'; import { AccessibleAreaChart } from 'src/components/AreaChart/AccessibleAreaChart'; +import { MetricsDisplayRow } from 'src/components/LineGraph/MetricsDisplay'; +import MetricsDisplay from 'src/components/LineGraph/MetricsDisplay'; import { Paper } from 'src/components/Paper'; +import { StyledBottomLegend } from 'src/features/NodeBalancers/NodeBalancerDetail/NodeBalancerSummary/TablesPanel'; import { tooltipLabelFormatter, tooltipValueFormatter } from './utils'; @@ -34,6 +37,7 @@ interface AreaChartProps { ariaLabel: string; data: any; height: number; + legendRows?: Omit; showLegend?: boolean; timezone: string; unit: string; @@ -56,6 +60,7 @@ export const AreaChart = (props: AreaChartProps) => { ariaLabel, data, height, + legendRows, showLegend, timezone, unit, @@ -100,6 +105,25 @@ export const AreaChart = (props: AreaChartProps) => { return null; }; + const CustomLegend = () => { + if (legendRows) { + const legendRowsWithClickHandler = legendRows.map((legendRow) => ({ + ...legendRow, + handleLegendClick: () => handleLegendClick(legendRow.legendTitle), + })); + + return ( + + + + ); + } + return null; + }; + const accessibleDataKeys = areas.map((area) => area.dataKey); return ( @@ -132,7 +156,7 @@ export const AreaChart = (props: AreaChartProps) => { }} content={} /> - {showLegend && ( + {showLegend && !legendRows && ( ( @@ -146,6 +170,14 @@ export const AreaChart = (props: AreaChartProps) => { onClick={(props) => handleLegendClick(props.dataKey)} /> )} + {showLegend && legendRows && ( + } + /> + )} {areas.map(({ color, dataKey }) => ( + DateTime.fromMillis(timestamp, { zone: timezone }).toLocaleString( + DateTime.DATETIME_SHORT + ); + +export const tooltipLabelFormatter = (timestamp: number, timezone: string) => + DateTime.fromMillis(timestamp, { zone: timezone }).toLocaleString( + DateTime.DATETIME_MED + ); + +export const tooltipValueFormatter = (value: number, unit: string) => + `${roundTo(value)}${unit}`; + +export const timeData: LinodeNetworkTimeData[] = [ { 'Public Outbound Traffic': 5.434939999999999, timestamp: 1703304000000, @@ -509,15 +524,131 @@ export const timeData = [ }, ]; -export const getAccessibleTimestamp = (timestamp: number, timezone: string) => - DateTime.fromMillis(timestamp, { zone: timezone }).toLocaleString( - DateTime.DATETIME_SHORT - ); - -export const tooltipLabelFormatter = (timestamp: number, timezone: string) => - DateTime.fromMillis(timestamp, { zone: timezone }).toLocaleString( - DateTime.DATETIME_MED - ); - -export const tooltipValueFormatter = (value: number, unit: string) => - `${roundTo(value)}${unit}`; +export const customLegendData = [ + [1703304000000, 5.434939999999999], + [1703311200000, 5.48299], + [1703318400000, 5.65558], + [1703325600000, 4.76884], + [1703332800000, 6.4184399999999995], + [1703340000000, 5.62116], + [1703347200000, 5.07858], + [1703354400000, 5.00401], + [1703361600000, 6.556310000000001], + [1703368800000, 5.0976300000000005], + [1703376000000, 4.8704], + [1703383200000, 5.489439999999999], + [1703390400000, 4.55057], + [1703397600000, 5.61529], + [1703404800000, 5.217], + [1703412000000, 5.11331], + [1703419200000, 5.46411], + [1703426400000, 4.7774399999999995], + [1703433600000, 5.02865], + [1703440800000, 6.32617], + [1703448000000, 4.93639], + [1703455200000, 5.915970000000001], + [1703462400000, 5.27855], + [1703469600000, 4.93147], + [1703476800000, 5.0265699999999995], + [1703484000000, 4.87472], + [1703491200000, 4.92317], + [1703498400000, 5.582979999999999], + [1703505600000, 4.59687], + [1703512800000, 5.0703000000000005], + [1703520000000, 5.48172], + [1703527200000, 5.71833], + [1703534400000, 5.80666], + [1703541600000, 7.650729999999999], + [1703548800000, 6.09863], + [1703556000000, 4.88399], + [1703563200000, 6.38346], + [1703570400000, 5.52181], + [1703577600000, 6.409890000000001], + [1703584800000, 6.24504], + [1703592000000, 6.706390000000001], + [1703599200000, 6.55377], + [1703606400000, 5.45406], + [1703613600000, 5.48203], + [1703620800000, 6.31843], + [1703628000000, 5.257149999999999], + [1703635200000, 5.693689999999999], + [1703642400000, 6.15741], + [1703649600000, 6.1616], + [1703656800000, 5.59863], + [1703664000000, 5.09122], + [1703671200000, 5.93977], + [1703678400000, 5.08668], + [1703685600000, 6.441350000000001], + [1703692800000, 5.36822], + [1703700000000, 28.10246], + [1703707200000, 5.84647], + [1703714400000, 5.9009], + [1703721600000, 5.97372], + [1703728800000, 7.28458], + [1703736000000, 6.96537], + [1703743200000, 4.5504], + [1703750400000, 4.5921], + [1703757600000, 6.516850000000001], + [1703764800000, 5.257359999999999], + [1703772000000, 5.79805], + [1703779200000, 5.2665], + [1703786400000, 6.34178], + [1703793600000, 5.37263], + [1703800800000, 6.46444], + [1703808000000, 5.16033], + [1703815200000, 4.85757], + [1703822400000, 6.5664299999999995], + [1703829600000, 6.73556], + [1703836800000, 5.29416], + [1703844000000, 5.54825], + [1703851200000, 5.0805], + [1703858400000, 6.29611], + [1703865600000, 5.98415], + [1703872800000, 6.11128], + [1703880000000, 6.23872], + [1703887200000, 5.773029999999999], + [1703894400000, 6.229100000000001], + [1703901600000, 7.26283], + [1703908800000, 4.83416], + [1703916000000, 6.2334700000000005], + [1703923200000, 5.019939999999999], + [1703930400000, 5.516310000000001], + [1703937600000, 6.84012], + [1703944800000, 4.83355], + [1703952000000, 5.28805], + [1703959200000, 5.223], + [1703966400000, 5.01722], + [1703973600000, 4.8092299999999994], + [1703980800000, 5.91444], + [1703988000000, 5.9965399999999995], + [1703995200000, 5.3739799999999995], + [1704002400000, 5.932720000000001], + [1704009600000, 5.38283], + [1704016800000, 6.44168], + [1704024000000, 4.90296], + [1704031200000, 4.883109999999999], + [1704038400000, 5.21804], + [1704045600000, 5.63115], + [1704052800000, 6.74491], + [1704060000000, 5.04914], + [1704067200000, 5.44395], + [1704074400000, 4.781350000000001], + [1704081600000, 5.3388100000000005], + [1704088800000, 5.9689499999999995], + [1704096000000, 5.15655], + [1704103200000, 6.12438], + [1704110400000, 4.669560000000001], + [1704117600000, 4.63611], + [1704124800000, 5.66633], + [1704132000000, 5.86619], + [1704139200000, 5.7318500000000006], + [1704146400000, 5.75463], + [1704153600000, 5.652810000000001], + [1704160800000, 5.0788400000000005], + [1704168000000, 6.32605], + [1704175200000, 9.19674], + [1704182400000, 10.7236], + [1704189600000, 11.021540000000002], + [1704196800000, 8.08084], + [1704204000000, 5.6375], +]; diff --git a/packages/manager/src/components/LineGraph/MetricDisplay.styles.ts b/packages/manager/src/components/LineGraph/MetricDisplay.styles.ts index 6d7a3d7ef5d..ed4f14d9978 100644 --- a/packages/manager/src/components/LineGraph/MetricDisplay.styles.ts +++ b/packages/manager/src/components/LineGraph/MetricDisplay.styles.ts @@ -1,56 +1,45 @@ -import { Theme } from '@mui/material/styles'; -import { makeStyles } from 'tss-react/mui'; +import { styled } from '@mui/material/styles'; -export const useMetricsDiaplyStyles = makeStyles()((theme: Theme) => ({ - blue: { - '&:before': { - backgroundColor: theme.graphs.blue, - }, - }, - darkGreen: { - '&:before': { - backgroundColor: theme.graphs.network.inbound, - }, - }, - green: { - '&:before': { - backgroundColor: theme.graphs.green, - }, - }, - legend: { - '& > div': { - '&:before': { - content: '""', - display: 'inline-block', - height: 20, - marginRight: theme.spacing(1), - width: 20, - }, - alignItems: 'center', - display: 'flex', - }, - }, - lightGreen: { - '&:before': { - backgroundColor: theme.graphs.network.outbound, - }, - }, - purple: { +import { Button } from 'src/components/Button/Button'; +import { Table } from 'src/components/Table'; +import { TableCell } from 'src/components/TableCell'; +import { omittedProps } from 'src/utilities/omittedProps'; + +export const StyledTable = styled(Table, { + label: 'StyledTable', +})(({ theme }) => ({ + border: `1px solid ${theme.borderColors.borderTable}`, +})); + +export const StyledTableCell = styled(TableCell, { + label: 'StyledTableCell', +})(({ theme }) => ({ + '& > button': { '&:before': { - backgroundColor: theme.graphs.purple, + content: '""', + display: 'inline-block', + height: 20, + marginRight: theme.spacing(1), + width: 20, }, - }, - red: { - '&:before': { - backgroundColor: theme.graphs.red, + alignItems: 'center', + display: 'flex', + justifyContent: 'flex-start', + [theme.breakpoints.down('sm')]: { + padding: 0, }, }, - root: { - border: `1px solid ${theme.borderColors.borderTable}`, - }, - yellow: { +})); + +export const StyledButton = styled(Button, { + label: 'StyledButton', + shouldForwardProp: omittedProps(['legendColor', 'hidden']), +})<{ legendColor?: string }>(({ hidden, legendColor, theme }) => ({ + ...(legendColor && { '&:before': { - backgroundColor: theme.graphs.yellow, + backgroundColor: hidden + ? theme.color.disabledText + : theme.graphs[legendColor], }, - }, + }), })); diff --git a/packages/manager/src/components/LineGraph/MetricsDisplay.test.tsx b/packages/manager/src/components/LineGraph/MetricsDisplay.test.tsx index 971d12eee40..531f1755d8d 100644 --- a/packages/manager/src/components/LineGraph/MetricsDisplay.test.tsx +++ b/packages/manager/src/components/LineGraph/MetricsDisplay.test.tsx @@ -23,6 +23,7 @@ describe('CPUMetrics', () => { { data: mockMetrics, format: formatPercentage, + handleLegendClick: vi.fn(), legendColor: 'blue', legendTitle: 'Legend Title', }, @@ -40,6 +41,7 @@ describe('CPUMetrics', () => { { data: mockMetrics, format: formatPercentage, + handleLegendClick: vi.fn(), legendColor: 'blue', legendTitle: 'Legend Title', }, @@ -59,6 +61,7 @@ describe('CPUMetrics', () => { { data: mockMetrics, format: formatPercentage, + handleLegendClick: vi.fn(), legendColor: 'blue', legendTitle: 'Legend Title', }, @@ -77,6 +80,7 @@ describe('CPUMetrics', () => { { data: mockMetrics, format: formatPercentage, + handleLegendClick: vi.fn(), legendColor: 'blue', legendTitle: 'Legend Title', }, @@ -96,12 +100,14 @@ describe('CPUMetrics', () => { { data: mockMetrics, format: formatPercentage, + handleLegendClick: vi.fn(), legendColor: 'blue', legendTitle: 'Legend Title 1', }, { data: { average: 90, last: 100, length: 0, max: 80, total: 110 }, format: formatPercentage, + handleLegendClick: vi.fn(), legendColor: 'red', legendTitle: 'Legend Title 2', }, diff --git a/packages/manager/src/components/LineGraph/MetricsDisplay.tsx b/packages/manager/src/components/LineGraph/MetricsDisplay.tsx index d2eb78b23c7..2053aa4aa46 100644 --- a/packages/manager/src/components/LineGraph/MetricsDisplay.tsx +++ b/packages/manager/src/components/LineGraph/MetricsDisplay.tsx @@ -1,21 +1,27 @@ import * as React from 'react'; -import { Table } from 'src/components/Table'; import { TableBody } from 'src/components/TableBody'; import { TableCell } from 'src/components/TableCell'; import { TableHead } from 'src/components/TableHead'; import { TableRow } from 'src/components/TableRow'; import { Typography } from 'src/components/Typography'; import { Metrics } from 'src/utilities/statMetrics'; -import { useMetricsDiaplyStyles } from './MetricDisplay.styles'; + +import { + StyledButton, + StyledTable, + StyledTableCell, +} from './MetricDisplay.styles'; interface Props { + hiddenRows?: string[]; rows: MetricsDisplayRow[]; } -interface MetricsDisplayRow { +export interface MetricsDisplayRow { data: Metrics; format: (n: number) => string; + handleLegendClick?: () => void; legendColor: | 'blue' | 'darkGreen' @@ -27,21 +33,19 @@ interface MetricsDisplayRow { legendTitle: string; } -export const MetricsDisplay = ({ rows }: Props) => { +export const MetricsDisplay = ({ hiddenRows, rows }: Props) => { const rowHeaders = ['Max', 'Avg', 'Last']; - const { classes } = useMetricsDiaplyStyles(); + const sxProps = { + borderTop: 'none !important', + }; return ( - - - - {''} + + + + {''} {rowHeaders.map((section, idx) => ( - + {section} ))} @@ -49,17 +53,28 @@ export const MetricsDisplay = ({ rows }: Props) => { {rows.map((row) => { - const { data, format, legendColor, legendTitle } = row; + const { + data, + format, + handleLegendClick, + legendColor, + legendTitle, + } = row; + const hidden = hiddenRows?.includes(legendTitle); + return ( - -
+
-
+ + {metricsBySection(data).map((section, idx) => { return ( { ); })}
-
+ ); }; diff --git a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/NetworkingSummaryPanel/TransferHistory.tsx b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/NetworkingSummaryPanel/TransferHistory.tsx index f6ee3c0755b..65f1854c8fa 100644 --- a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/NetworkingSummaryPanel/TransferHistory.tsx +++ b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/NetworkingSummaryPanel/TransferHistory.tsx @@ -8,6 +8,7 @@ import * as React from 'react'; import PendingIcon from 'src/assets/icons/pending.svg'; import { AreaChart } from 'src/components/AreaChart/AreaChart'; +import { LinodeNetworkTimeData, Point } from 'src/components/AreaChart/types'; import { Box } from 'src/components/Box'; import { CircleProgress } from 'src/components/CircleProgress'; import { ErrorState } from 'src/components/ErrorState/ErrorState'; @@ -156,15 +157,18 @@ export const TransferHistory = React.memo((props: Props) => { // @TODO recharts: remove conditional code and delete old chart when we decide recharts is stable if (flags?.recharts) { - const timeData = combinedData.reduce((acc: any, point: any) => { - acc.push({ - 'Public Outbound Traffic': convertNetworkData - ? convertNetworkData(point[1]) - : point[1], - timestamp: point[0], - }); - return acc; - }, []); + const timeData = combinedData.reduce( + (acc: LinodeNetworkTimeData[], point: Point) => { + acc.push({ + 'Public Outbound Traffic': convertNetworkData + ? convertNetworkData(point[1]) + : point[1], + timestamp: point[0], + }); + return acc; + }, + [] + ); return ( diff --git a/packages/manager/src/features/Linodes/LinodesDetail/LinodeSummary/LinodeSummary.tsx b/packages/manager/src/features/Linodes/LinodesDetail/LinodeSummary/LinodeSummary.tsx index db5c03cb702..00e00353e50 100644 --- a/packages/manager/src/features/Linodes/LinodesDetail/LinodeSummary/LinodeSummary.tsx +++ b/packages/manager/src/features/Linodes/LinodesDetail/LinodeSummary/LinodeSummary.tsx @@ -6,11 +6,19 @@ import { useParams } from 'react-router-dom'; import { debounce } from 'throttle-debounce'; import PendingIcon from 'src/assets/icons/pending.svg'; +import { AreaChart } from 'src/components/AreaChart/AreaChart'; +import { + CPUTimeData, + DiskIOTimeData, + Point, +} from 'src/components/AreaChart/types'; +import { Box } from 'src/components/Box'; import Select, { Item } from 'src/components/EnhancedSelect/Select'; import { ErrorState } from 'src/components/ErrorState/ErrorState'; import { LineGraph } from 'src/components/LineGraph/LineGraph'; -import { Typography } from 'src/components/Typography'; import { Paper } from 'src/components/Paper'; +import { Typography } from 'src/components/Typography'; +import { useFlags } from 'src/hooks/useFlags'; import { useWindowDimensions } from 'src/hooks/useWindowDimensions'; import { STATS_NOT_READY_API_MESSAGE, @@ -28,10 +36,11 @@ import { } from 'src/utilities/statMetrics'; import { NetworkGraphs } from './NetworkGraphs'; -import type { ChartProps } from './NetworkGraphs'; import { StatsPanel } from './StatsPanel'; import { getDateOptions } from './helpers'; +import type { ChartProps } from './NetworkGraphs'; + setUpCharts(); interface Props { @@ -40,12 +49,14 @@ interface Props { } const chartHeight = 160; +const rechartsHeight = 300; const LinodeSummary: React.FC = (props) => { const { isBareMetalInstance, linodeCreated } = props; const { linodeId } = useParams<{ linodeId: string }>(); const id = Number(linodeId); const theme = useTheme(); + const flags = useFlags(); const { data: profile } = useProfile(); const timezone = profile?.timezone || DateTime.local().zoneName; @@ -106,9 +117,50 @@ const LinodeSummary: React.FC = (props) => { const renderCPUChart = () => { const data = stats?.data.cpu ?? []; - const metrics = getMetrics(data); + // @TODO recharts: remove conditional code and delete old chart when we decide recharts is stable + if (flags.recharts) { + const timeData = data.reduce((acc: CPUTimeData[], point: Point) => { + acc.push({ + 'CPU %': point[1], + timestamp: point[0], + }); + return acc; + }, []); + + return ( + + + + ); + } + return ( = (props) => { io: stats?.data.io.io ?? [], swap: stats?.data.io.swap ?? [], }; + const timeData: DiskIOTimeData[] = []; + + // @TODO recharts: remove conditional code and delete old chart when we decide recharts is stable + if (flags.recharts) { + for (let i = 0; i < data.io.length; i++) { + timeData.push({ + 'I/O Rate': data.io[i][1], + 'Swap Rate': data.swap[i][1], + timestamp: data.io[i][0], + }); + } + + return ( + + + + ); + } return ( = (props) => { }; return ( - - + + + + + {!isBareMetalInstance ? ( - + + + + + + - {!isBareMetalInstance ? ( - - - - - - - - - ) : null} - - - + ) : null} + + ); }; @@ -287,16 +391,21 @@ const StyledSelect = styled(Select, { label: 'StyledSelect' })({ maxWidth: 150, }); -const StyledGrid = styled(Grid, { label: 'StyledGrid' })(({ theme }) => ({ +const StyledGrid = styled(Grid, { + label: 'StyledGrid', + shouldForwardProp: (prop) => prop !== 'recharts', +})<{ recharts?: boolean }>(({ recharts, theme }) => ({ '& h2': { fontSize: '1rem', }, '&.MuiGrid-item': { padding: theme.spacing(2), }, - backgroundColor: theme.bg.offWhite, + backgroundColor: recharts ? theme.bg.white : theme.bg.offWhite, border: `solid 1px ${theme.borderColors.divider}`, marginBottom: theme.spacing(2), + padding: theme.spacing(3), + paddingBottom: theme.spacing(2), [theme.breakpoints.up(1100)]: { '&:first-of-type': { marginRight: theme.spacing(2), diff --git a/packages/manager/src/features/Linodes/LinodesDetail/LinodeSummary/NetworkGraphs.tsx b/packages/manager/src/features/Linodes/LinodesDetail/LinodeSummary/NetworkGraphs.tsx index d8a7c619b89..620f97a9f79 100644 --- a/packages/manager/src/features/Linodes/LinodesDetail/LinodeSummary/NetworkGraphs.tsx +++ b/packages/manager/src/features/Linodes/LinodesDetail/LinodeSummary/NetworkGraphs.tsx @@ -1,9 +1,12 @@ import { Stats } from '@linode/api-v4/lib/linodes'; import Grid from '@mui/material/Unstable_Grid2'; -import { styled, useTheme, Theme } from '@mui/material/styles'; +import { Theme, styled, useTheme } from '@mui/material/styles'; import { map, pathOr } from 'ramda'; import * as React from 'react'; +import { AreaChart } from 'src/components/AreaChart/AreaChart'; +import { NetworkTimeData } from 'src/components/AreaChart/types'; +import { Box } from 'src/components/Box'; import { LineGraph } from 'src/components/LineGraph/LineGraph'; import { convertNetworkToUnit, @@ -11,12 +14,14 @@ import { formatNetworkTooltip, generateNetworkUnits, } from 'src/features/Longview/shared/utilities'; +import { useFlags } from 'src/hooks/useFlags'; import { Metrics, getMetrics, getTotalTraffic, } from 'src/utilities/statMetrics'; import { readableBytes } from 'src/utilities/unitConversions'; + import { StatsPanel } from './StatsPanel'; export interface TotalTrafficProps { @@ -68,6 +73,7 @@ export const NetworkGraphs = (props: Props) => { const { rangeSelection, stats, ...rest } = props; const theme = useTheme(); + const flags = useFlags(); const v4Data: NetworkStats = { privateIn: pathOr([], ['data', 'netv4', 'private_in'], stats), @@ -135,7 +141,7 @@ export const NetworkGraphs = (props: Props) => { return ( - + ( { {...rest} /> - + ( { unit, } = props; + const flags = useFlags(); + const format = formatBitsPerSecond; const convertNetworkData = (value: number) => { @@ -216,18 +224,93 @@ const Graph = (props: GraphProps) => { const convertedPublicOut = data.publicOut; const convertedPrivateIn = data.privateIn; const convertedPrivateOut = data.privateOut; + const timeData: NetworkTimeData[] = []; + + for (let i = 0; i < data.publicIn.length; i++) { + timeData.push({ + 'Private In': convertNetworkData(data.privateIn[i][1]), + 'Private Out': convertNetworkData(data.privateOut[i][1]), + 'Public In': convertNetworkData(data.publicIn[i][1]), + 'Public Out': convertNetworkData(data.publicOut[i][1]), + timestamp: data.publicIn[i][0], + }); + } + + // @TODO recharts: remove conditional code and delete old chart when we decide recharts is stable + if (flags.recharts) { + return ( + + + + ); + } return ( { ); }; -const StyledGrid = styled(Grid, { label: 'StyledGrid' })(({ theme }) => ({ +const StyledGrid = styled(Grid, { + label: 'StyledGrid', + shouldForwardProp: (prop) => prop !== 'recharts', +})<{ recharts?: boolean }>(({ recharts, theme }) => ({ '& h2': { fontSize: '1rem', }, '&.MuiGrid-item': { padding: theme.spacing(2), }, - backgroundColor: theme.bg.offWhite, + backgroundColor: recharts ? theme.bg.white : theme.bg.offWhite, border: `solid 1px ${theme.borderColors.divider}`, + padding: theme.spacing(3), + paddingBottom: theme.spacing(2), [theme.breakpoints.down(1100)]: { '&:first-of-type': { marginBottom: theme.spacing(2), diff --git a/packages/manager/src/features/Longview/LongviewDetail/DetailTabs/Apache/ApacheGraphs.tsx b/packages/manager/src/features/Longview/LongviewDetail/DetailTabs/Apache/ApacheGraphs.tsx index 00dd43d9064..23003a9d17e 100644 --- a/packages/manager/src/features/Longview/LongviewDetail/DetailTabs/Apache/ApacheGraphs.tsx +++ b/packages/manager/src/features/Longview/LongviewDetail/DetailTabs/Apache/ApacheGraphs.tsx @@ -113,7 +113,7 @@ export const ApacheGraphs = React.memo((props: Props) => { { { { { const metrics = getMetrics(data); - let timeData = []; // @TODO recharts: remove conditional code and delete old chart when we decide recharts is stable if (flags.recharts) { - timeData = data.reduce((acc: any, point: any) => { - acc.push({ - Connections: point[1], - timestamp: point[0], - }); - return acc; - }, []); + const timeData = data.reduce( + (acc: NodeBalancerConnectionsTimeData[], point: Point) => { + acc.push({ + Connections: point[1], + timestamp: point[0], + }); + return acc; + }, + [] + ); + + return ( + + + + ); } return ( - - {flags.recharts ? ( - - - - ) : ( - - - - )} + <> + + + { ]} /> - + ); }; @@ -200,55 +215,72 @@ export const TablesPanel = () => { return ; } + if (flags.recharts) { + return ( + + + + ); + } + return ( - {flags.recharts ? ( - - - - ) : ( - - )} + ({ backgroundColor: theme.bg.offWhite, diff --git a/packages/manager/src/foundations/themes/dark.ts b/packages/manager/src/foundations/themes/dark.ts index 474bceb6910..96398e4a4d6 100644 --- a/packages/manager/src/foundations/themes/dark.ts +++ b/packages/manager/src/foundations/themes/dark.ts @@ -608,15 +608,13 @@ export const darkTheme: ThemeOptions = { user: `rgb(81, 166, 245)`, wait: `rgb(145, 199, 237)`, }, + darkGreen: `rgb(16, 162, 29)`, diskIO: { read: `rgb(255, 196, 105)`, swap: `rgb(238, 44, 44)`, write: `rgb(255, 179, 77)`, }, - network: { - inbound: `rgb(16, 162, 29)`, - outbound: `rgb(49, 206, 62)`, - }, + lightGreen: `rgb(49, 206, 62)`, purple: `rgb(217, 176, 217)`, red: `rgb(255, 99, 60)`, yellow: `rgb(255, 220, 125)`, diff --git a/packages/manager/src/foundations/themes/light.ts b/packages/manager/src/foundations/themes/light.ts index d5058dbb5a4..3a39ec7e4e0 100644 --- a/packages/manager/src/foundations/themes/light.ts +++ b/packages/manager/src/foundations/themes/light.ts @@ -1397,6 +1397,7 @@ export const lightTheme: ThemeOptions = { user: `rgba(81, 166, 245, ${graphTransparency})`, wait: `rgba(145, 199, 237, ${graphTransparency})`, }, + darkGreen: `rgba(16, 162, 29, ${graphTransparency})`, diskIO: { read: `rgba(255, 196, 105, ${graphTransparency})`, swap: `rgba(238, 44, 44, ${graphTransparency})`, @@ -1404,6 +1405,7 @@ export const lightTheme: ThemeOptions = { }, green: `rgba(91, 215, 101, ${graphTransparency})`, inodes: `rgba(224, 138, 146, ${graphTransparency})`, + lightGreen: `rgba(49, 206, 62, ${graphTransparency})`, load: `rgba(255, 220, 77, ${graphTransparency})`, memory: { buffers: `rgba(142, 56, 142, ${graphTransparency})`, @@ -1411,10 +1413,6 @@ export const lightTheme: ThemeOptions = { swap: `rgba(238, 44, 44, ${graphTransparency})`, used: `rgba(236, 200, 236, ${graphTransparency})`, }, - network: { - inbound: `rgba(16, 162, 29, ${graphTransparency})`, - outbound: `rgba(49, 206, 62, ${graphTransparency})`, - }, orange: `rgba(255, 179, 77, ${graphTransparency})`, processCount: `rgba(113, 86, 245, ${graphTransparency})`, purple: `rgba(217, 176, 217, ${graphTransparency})`,