-
Notifications
You must be signed in to change notification settings - Fork 383
upcoming: [M3-9785, M3-9788, M3-10040] - Added NodeBalacer Table and replace Linodes with Resources and remove "Label" text from Subnet and Linode Column #12232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4616c72
4c0cdbb
ce0d7b2
1ce71d6
6d83546
1922e5e
6756f29
24adfb3
4322931
e3657fa
b3d1a5f
5a814be
d95fa86
e4aa66a
d13e78f
6cee89d
f7f6019
4ebb83a
d9062f2
4bcf611
248984e
044c845
2786be8
b6bb539
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@linode/manager": Upcoming Features | ||
--- | ||
|
||
Add NodeBalancer Table under VPC Subnets Table and rename "Linodes" column to "Resources" ([#12232](https://github.com/linode/manager/pull/12232)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { waitFor, waitForElementToBeRemoved } from '@testing-library/react'; | ||
import * as React from 'react'; | ||
import { afterAll, afterEach, beforeAll, describe, it } from 'vitest'; | ||
|
||
import { | ||
firewallFactory, | ||
subnetAssignedNodebalancerDataFactory, | ||
} from 'src/factories'; | ||
import { makeResourcePage } from 'src/mocks/serverHandlers'; | ||
import { http, HttpResponse, server } from 'src/mocks/testServer'; | ||
import { | ||
mockMatchMedia, | ||
renderWithTheme, | ||
wrapWithTableBody, | ||
} from 'src/utilities/testHelpers'; | ||
|
||
import { SubnetNodeBalancerRow } from './SubnetNodebalancerRow'; | ||
|
||
const LOADING_TEST_ID = 'circle-progress'; | ||
|
||
beforeAll(() => mockMatchMedia()); | ||
afterEach(() => server.resetHandlers()); | ||
afterAll(() => server.close()); | ||
|
||
describe('SubnetNodeBalancerRow', () => { | ||
const nodebalancer = { | ||
id: 123, | ||
label: 'test-nodebalancer', | ||
}; | ||
|
||
const configs = [ | ||
{ nodes_status: { up: 3, down: 1 } }, | ||
{ nodes_status: { up: 2, down: 2 } }, | ||
]; | ||
|
||
const firewalls = makeResourcePage( | ||
firewallFactory.buildList(1, { label: 'mock-firewall' }) | ||
); | ||
|
||
const subnetNodebalancer = subnetAssignedNodebalancerDataFactory.build({ | ||
id: nodebalancer.id, | ||
ipv4_range: '192.168.99.0/30', | ||
}); | ||
|
||
it('renders loading state', async () => { | ||
const { getByTestId } = renderWithTheme( | ||
wrapWithTableBody( | ||
<SubnetNodeBalancerRow | ||
ipv4={subnetNodebalancer.ipv4_range} | ||
nodeBalancerId={subnetNodebalancer.id} | ||
/> | ||
) | ||
); | ||
|
||
expect(getByTestId(LOADING_TEST_ID)).toBeInTheDocument(); | ||
Check warning on line 55 in packages/manager/src/features/VPCs/VPCDetail/SubnetNodebalancerRow.test.tsx
|
||
await waitForElementToBeRemoved(() => getByTestId(LOADING_TEST_ID)); | ||
Check warning on line 56 in packages/manager/src/features/VPCs/VPCDetail/SubnetNodebalancerRow.test.tsx
|
||
}); | ||
|
||
it('renders nodebalancer row with data', async () => { | ||
server.use( | ||
http.get('*/nodebalancers/:id', () => { | ||
return HttpResponse.json(nodebalancer); | ||
}), | ||
http.get('*/nodebalancers/:id/configs', () => { | ||
return HttpResponse.json(configs); | ||
}), | ||
http.get('*/nodebalancers/:id/firewalls', () => { | ||
return HttpResponse.json(firewalls); | ||
}) | ||
); | ||
|
||
const { getByText, getByRole } = renderWithTheme( | ||
wrapWithTableBody( | ||
<SubnetNodeBalancerRow | ||
ipv4={subnetNodebalancer.ipv4_range} | ||
nodeBalancerId={nodebalancer.id} | ||
/> | ||
) | ||
); | ||
|
||
await waitFor(() => { | ||
expect(getByText(nodebalancer.label)).toBeInTheDocument(); | ||
Check warning on line 82 in packages/manager/src/features/VPCs/VPCDetail/SubnetNodebalancerRow.test.tsx
|
||
}); | ||
|
||
expect(getByText(subnetNodebalancer.ipv4_range)).toBeInTheDocument(); | ||
Check warning on line 85 in packages/manager/src/features/VPCs/VPCDetail/SubnetNodebalancerRow.test.tsx
|
||
expect(getByText('mock-firewall')).toBeInTheDocument(); | ||
Check warning on line 86 in packages/manager/src/features/VPCs/VPCDetail/SubnetNodebalancerRow.test.tsx
|
||
|
||
const nodebalancerLink = getByRole('link', { | ||
name: nodebalancer.label, | ||
}); | ||
|
||
expect(nodebalancerLink).toHaveAttribute( | ||
'href', | ||
`/nodebalancers/${nodebalancer.id}/summary` | ||
); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import { | ||
useAllNodeBalancerConfigsQuery, | ||
useNodeBalancerQuery, | ||
useNodeBalancersFirewallsQuery, | ||
} from '@linode/queries'; | ||
import { Box, CircleProgress, Hidden } from '@linode/ui'; | ||
import ErrorOutline from '@mui/icons-material/ErrorOutline'; | ||
import { Typography } from '@mui/material'; | ||
import * as React from 'react'; | ||
|
||
import { Link } from 'src/components/Link'; | ||
import { StatusIcon } from 'src/components/StatusIcon/StatusIcon'; | ||
import { TableCell } from 'src/components/TableCell'; | ||
import { TableRow } from 'src/components/TableRow'; | ||
|
||
interface Props { | ||
hover?: boolean; | ||
ipv4: string; | ||
nodeBalancerId: number; | ||
} | ||
|
||
export const SubnetNodeBalancerRow = ({ | ||
nodeBalancerId, | ||
hover = false, | ||
ipv4, | ||
}: Props) => { | ||
const { | ||
data: nodebalancer, | ||
error: nodebalancerError, | ||
isLoading: nodebalancerLoading, | ||
} = useNodeBalancerQuery(nodeBalancerId); | ||
const { data: attachedFirewallData } = useNodeBalancersFirewallsQuery( | ||
Number(nodeBalancerId) | ||
); | ||
const { data: configs } = useAllNodeBalancerConfigsQuery( | ||
Number(nodeBalancerId) | ||
); | ||
|
||
const firewallLabel = attachedFirewallData?.data[0]?.label; | ||
const firewallId = attachedFirewallData?.data[0]?.id; | ||
|
||
const down = configs?.reduce((acc: number, config) => { | ||
return acc + config.nodes_status.down; | ||
}, 0); // add the downtime for each config together | ||
|
||
const up = configs?.reduce((acc: number, config) => { | ||
return acc + config.nodes_status.up; | ||
}, 0); // add the uptime for each config together | ||
|
||
if (nodebalancerLoading) { | ||
return ( | ||
<TableRow hover={hover}> | ||
<TableCell colSpan={6} style={{ textAlign: 'center' }}> | ||
<CircleProgress size="sm" /> | ||
</TableCell> | ||
</TableRow> | ||
); | ||
} | ||
|
||
if (nodebalancerError || !nodebalancer) { | ||
return ( | ||
<TableRow data-testid="subnet-nodebalancer-row-error" hover={hover}> | ||
<TableCell colSpan={6} style={{ justifyItems: 'center' }}> | ||
<Box alignItems="center" display="flex"> | ||
<ErrorOutline | ||
data-qa-error-icon | ||
sx={(theme) => ({ color: theme.color.red, marginRight: 1 })} | ||
/> | ||
<Typography> | ||
There was an error loading{' '} | ||
<Link to={`/nodebalancers/${nodeBalancerId}/summary`}> | ||
Nodebalancer {nodeBalancerId} | ||
</Link> | ||
</Typography> | ||
</Box> | ||
</TableCell> | ||
</TableRow> | ||
); | ||
} | ||
|
||
return ( | ||
<TableRow> | ||
<TableCell> | ||
<Link | ||
className="secondaryLink" | ||
to={`/nodebalancers/${nodebalancer?.id}/summary`} | ||
> | ||
{nodebalancer?.label} | ||
</Link> | ||
</TableCell> | ||
<TableCell statusCell> | ||
<StatusIcon aria-label="Nodebalancer status active" status="active" /> | ||
{`${up} up, ${down} down`} | ||
</TableCell> | ||
<TableCell>{ipv4}</TableCell> | ||
<TableCell colSpan={2}> | ||
<Link | ||
accessibleAriaLabel={`Firewall ${firewallLabel}`} | ||
className="secondaryLink" | ||
to={`/firewalls/${firewallId}`} | ||
> | ||
{firewallLabel} | ||
</Link> | ||
</TableCell> | ||
</TableRow> | ||
); | ||
}; | ||
|
||
export const SubnetNodebalancerTableRowHead = ( | ||
<TableRow> | ||
<TableCell>NodeBalancer</TableCell> | ||
<TableCell>Backend Status</TableCell> | ||
<Hidden smDown> | ||
<TableCell>VPC IPv4 Range</TableCell> | ||
hasyed-akamai marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</Hidden> | ||
<Hidden smDown> | ||
<TableCell>Firewalls</TableCell> | ||
</Hidden> | ||
<TableCell /> | ||
</TableRow> | ||
); |
Uh oh!
There was an error while loading. Please reload this page.