Skip to content
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

feat: [UIE-8074] - DBaaS GA Summary tab #11091

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

DBaaS GA summary tab enhancements ([#11091](https://github.com/linode/manager/pull/11091))
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import { Database } from '@linode/api-v4';
import { waitFor } from '@testing-library/react';
import * as React from 'react';
import { databaseFactory } from 'src/factories';
import { renderWithTheme } from 'src/utilities/testHelpers';
import { vi } from 'vitest';
import * as utils from '../../utilities';
import { DatabaseSummary } from './DatabaseSummary';

const CLUSTER_CONFIGURATION = 'Cluster Configuration';
const THREE_NODE = 'Primary +2 replicas';
const TWO_NODE = 'Primary +1 replicas';
const VERSION = 'Version';

const CONNECTION_DETAILS = 'Connection Details';
const PRIVATE_NETWORK_HOST = 'Private Network Host';
const PRIVATE_NETWORK_HOST_LABEL = 'private network host';
const READONLY_HOST_LABEL = 'read-only host';
const GA_READONLY_HOST_LABEL = 'Read-only Host';

const ACCESS_CONTROLS = 'Access Controls';

const DEFAULT_PLATFORM = 'rdbms-default';
const DEFAULT_PRIMARY = 'db-mysql-default-primary.net';
const DEFAULT_STANDBY = 'db-mysql-default-standby.net';

const LEGACY_PLATFORM = 'rdbms-legacy';
const LEGACY_PRIMARY = 'db-mysql-legacy-primary.net';
const LEGACY_SECONDARY = 'db-mysql-legacy-secondary.net';

const spy = vi.spyOn(utils, 'useIsDatabasesEnabled');
spy.mockReturnValue({
isDatabasesEnabled: true,
isDatabasesV1Enabled: true,
isDatabasesV2Enabled: true,
isDatabasesV2Beta: false,
isV2ExistingBetaUser: false,
isV2NewBetaUser: false,
isDatabasesGAEnabled: true,
isV2GAUser: true,
});

describe('Database Summary', () => {
it('should render V2GA view default db', async () => {
const database = databaseFactory.build({
platform: DEFAULT_PLATFORM,
cluster_size: 2,
hosts: {
primary: DEFAULT_PRIMARY,
standby: DEFAULT_STANDBY,
},
}) as Database;

const { queryAllByText } = renderWithTheme(
<DatabaseSummary database={database} />
);

await waitFor(() => {
expect(queryAllByText(CLUSTER_CONFIGURATION)).toHaveLength(1);
expect(queryAllByText(TWO_NODE)).toHaveLength(1);
expect(queryAllByText(VERSION)).toHaveLength(0);

expect(queryAllByText(CONNECTION_DETAILS)).toHaveLength(1);
expect(queryAllByText(PRIVATE_NETWORK_HOST)).toHaveLength(0);
expect(queryAllByText(GA_READONLY_HOST_LABEL)).toHaveLength(1);
expect(queryAllByText(DEFAULT_STANDBY)).toHaveLength(1);

expect(queryAllByText(ACCESS_CONTROLS)).toHaveLength(0);
});
});

it('should render V2GA view legacy db', async () => {
const database = databaseFactory.build({
platform: LEGACY_PLATFORM,
cluster_size: 3,
hosts: {
primary: LEGACY_PRIMARY,
secondary: LEGACY_SECONDARY,
},
}) as Database;

const { queryAllByText } = renderWithTheme(
<DatabaseSummary database={database} />
);

await waitFor(() => {
expect(queryAllByText(CLUSTER_CONFIGURATION)).toHaveLength(1);
expect(queryAllByText(THREE_NODE)).toHaveLength(1);
expect(queryAllByText(VERSION)).toHaveLength(0);

expect(queryAllByText(CONNECTION_DETAILS)).toHaveLength(1);
expect(queryAllByText(PRIVATE_NETWORK_HOST)).toHaveLength(1);
expect(queryAllByText(GA_READONLY_HOST_LABEL)).toHaveLength(0);
expect(queryAllByText(LEGACY_SECONDARY)).toHaveLength(1);

expect(queryAllByText(ACCESS_CONTROLS)).toHaveLength(0);
});
});

it('should render Beta view default db', async () => {
spy.mockReturnValue({
isDatabasesEnabled: true,
isDatabasesV1Enabled: true,
isDatabasesV2Enabled: true,
isDatabasesV2Beta: true,
isV2ExistingBetaUser: true,
isV2NewBetaUser: false,
isDatabasesGAEnabled: false,
isV2GAUser: false,
});
const database = databaseFactory.build({
platform: DEFAULT_PLATFORM,
cluster_size: 2,
hosts: {
primary: DEFAULT_PRIMARY,
standby: DEFAULT_STANDBY,
secondary: undefined,
},
}) as Database;

const { queryAllByText } = renderWithTheme(
<DatabaseSummary database={database} />
);

await waitFor(() => {
expect(queryAllByText(CLUSTER_CONFIGURATION)).toHaveLength(1);
expect(queryAllByText(TWO_NODE)).toHaveLength(1);
expect(queryAllByText(VERSION)).toHaveLength(1);

expect(queryAllByText(CONNECTION_DETAILS)).toHaveLength(1);
expect(queryAllByText(PRIVATE_NETWORK_HOST_LABEL)).toHaveLength(0);
expect(queryAllByText(READONLY_HOST_LABEL)).toHaveLength(1);
expect(queryAllByText(/db-mysql-default-standby.net/)).toHaveLength(1);

expect(queryAllByText(ACCESS_CONTROLS)).toHaveLength(1);
});
});

it('should render Beta view legacy db', async () => {
spy.mockReturnValue({
isDatabasesEnabled: true,
isDatabasesV1Enabled: true,
isDatabasesV2Enabled: true,
isDatabasesV2Beta: true,
isV2ExistingBetaUser: true,
isV2NewBetaUser: false,
isDatabasesGAEnabled: false,
isV2GAUser: false,
});
const database = databaseFactory.build({
platform: LEGACY_PLATFORM,
cluster_size: 3,
hosts: {
primary: LEGACY_PRIMARY,
secondary: LEGACY_SECONDARY,
standby: undefined,
},
}) as Database;

const { queryAllByText } = renderWithTheme(
<DatabaseSummary database={database} />
);

await waitFor(() => {
expect(queryAllByText(CLUSTER_CONFIGURATION)).toHaveLength(1);
expect(queryAllByText(THREE_NODE)).toHaveLength(1);
expect(queryAllByText(VERSION)).toHaveLength(1);

expect(queryAllByText(CONNECTION_DETAILS)).toHaveLength(1);
expect(queryAllByText(PRIVATE_NETWORK_HOST_LABEL)).toHaveLength(1);
expect(queryAllByText(READONLY_HOST_LABEL)).toHaveLength(0);
expect(queryAllByText(/db-mysql-legacy-secondary.net/)).toHaveLength(1);

expect(queryAllByText(ACCESS_CONTROLS)).toHaveLength(1);
});
});

it('should render V1 view legacy db', async () => {
spy.mockReturnValue({
isDatabasesEnabled: true,
isDatabasesV1Enabled: true,
isDatabasesV2Enabled: false,
isDatabasesV2Beta: false,
isV2ExistingBetaUser: false,
isV2NewBetaUser: false,
isDatabasesGAEnabled: false,
isV2GAUser: false,
});
const database = databaseFactory.build({
platform: LEGACY_PLATFORM,
cluster_size: 3,
hosts: {
primary: LEGACY_PRIMARY,
secondary: LEGACY_SECONDARY,
standby: undefined,
},
}) as Database;

const { queryAllByText } = renderWithTheme(
<DatabaseSummary database={database} />
);

await waitFor(() => {
expect(queryAllByText(CLUSTER_CONFIGURATION)).toHaveLength(1);
expect(queryAllByText(THREE_NODE)).toHaveLength(1);
expect(queryAllByText(VERSION)).toHaveLength(1);

expect(queryAllByText(CONNECTION_DETAILS)).toHaveLength(1);
expect(queryAllByText(PRIVATE_NETWORK_HOST_LABEL)).toHaveLength(1);
expect(queryAllByText(READONLY_HOST_LABEL)).toHaveLength(0);
expect(queryAllByText(/db-mysql-legacy-secondary.net/)).toHaveLength(1);

expect(queryAllByText(ACCESS_CONTROLS)).toHaveLength(1);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import type { Database } from '@linode/api-v4/lib/databases/types';
import Grid from '@mui/material/Unstable_Grid2';
import * as React from 'react';

import { Divider } from 'src/components/Divider';
import { Link } from 'src/components/Link';
import { Paper } from 'src/components/Paper';
import { Typography } from 'src/components/Typography';

import AccessControls from '../AccessControls';
import ClusterConfiguration from './DatabaseSummaryClusterConfiguration';
import ConnectionDetails from './DatabaseSummaryConnectionDetails';

import type { Database } from '@linode/api-v4/lib/databases/types';
import AccessControls from 'src/features/Databases/DatabaseDetail/AccessControls';
import ClusterConfiguration from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration';
import ConnectionDetails from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails';
import ClusterConfigurationLegacy from 'src/features/Databases/DatabaseDetail/DatabaseSummary/legacy/DatabaseSummaryClusterConfigurationLegacy';
import ConnectionDetailsLegacy from 'src/features/Databases/DatabaseDetail/DatabaseSummary/legacy/DatabaseSummaryConnectionDetailsLegacy';
import { useIsDatabasesEnabled } from 'src/features/Databases/utilities';

interface Props {
database: Database;
Expand All @@ -19,6 +19,7 @@ interface Props {

export const DatabaseSummary: React.FC<Props> = (props) => {
const { database, disabled } = props;
const { isV2GAUser } = useIsDatabasesEnabled();

const description = (
<>
Expand All @@ -40,19 +41,35 @@ export const DatabaseSummary: React.FC<Props> = (props) => {
return (
<Paper>
<Grid container spacing={2}>
<Grid md={4} sm={12}>
<ClusterConfiguration database={database} />
<Grid md={isV2GAUser ? 12 : 4} sm={12}>
{isV2GAUser ? (
<ClusterConfiguration database={database} />
) : (
// Deprecated @since DBaaS V2 GA. Will be removed remove post GA release ~ Dec 2024
<ClusterConfigurationLegacy database={database} />
)}
</Grid>
<Grid md={8} sm={12}>
<ConnectionDetails database={database} />
<Grid md={isV2GAUser ? 12 : 8} sm={12}>
{isV2GAUser ? (
<ConnectionDetails database={database} />
) : (
// Deprecated @since DBaaS V2 GA. Will be removed remove post GA release ~ Dec 2024
<ConnectionDetailsLegacy database={database} />
)}
</Grid>
</Grid>
<Divider spacingBottom={16} spacingTop={28} />
<AccessControls
database={database}
description={description}
disabled={disabled}
/>
{!isV2GAUser && (
// Deprecated @since DBaaS V2 GA. Will be removed remove post GA release ~ Dec 2024
// AccessControls accessible through dropdown menu on landing page table and on settings tab
<>
<Divider spacingBottom={16} spacingTop={28} />
<AccessControls
database={database}
description={description}
disabled={disabled}
/>
</>
)}
</Paper>
);
};
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { styled } from '@mui/material/styles';
import Grid2 from '@mui/material/Unstable_Grid2/Grid2';
import { Box } from 'src/components/Box';
import { Typography } from 'src/components/Typography';

export const StyledGridContainer = styled(Grid2, {
label: 'StyledGridContainer',
})(({ theme }) => ({
'&>*:nth-of-type(even)': {
boxShadow: `inset 0px -1px 0px 0 ${
theme.palette.mode === 'dark'
? theme.color.white
: theme.palette.grey[200]
}`,
},
'&>*:nth-of-type(odd)': {
boxShadow: `inset 0px -1px 0px 0 ${theme.color.white}`,
marginBottom: '1px',
},
boxShadow: `inset 0 -1px 0 0 ${
theme.palette.mode === 'dark' ? theme.color.white : theme.palette.grey[200]
}, inset 0 1px 0 0 ${
theme.palette.mode === 'dark' ? theme.color.white : theme.palette.grey[200]
}, inset -1px 0 0 ${
theme.palette.mode === 'dark' ? theme.color.white : theme.palette.grey[200]
}`,
}));

export const StyledLabelTypography = styled(Typography, {
label: 'StyledLabelTypography',
})(({ theme }) => ({
background:
theme.palette.mode === 'dark'
? theme.bg.tableHeader
: theme.palette.grey[200],
color: theme.palette.mode === 'dark' ? theme.color.grey6 : 'inherit',
fontFamily: theme.font.bold,
height: '100%',
padding: '4px 15px',
}));

export const StyledValueBox = styled(Box, {
label: 'StyledValueBox',
})(({ theme }) => ({
'& > button': {
marginTop: '-5px',
},
'& > div': {
alignSelf: 'flex-start',
verticalAlign: 'sub',
},
'& button.MuiButtonBase-root': {
marginTop: '0',
},
'& button.copy-tooltip': {
marginTop: '-3px',
},
color: theme.palette.mode === 'dark' ? theme.color.grey8 : theme.color.black,
display: 'flex',
padding: '3px 5px',
}));
Comment on lines +42 to +61
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we do something like the following to improve alignment (vertically centered values), make use of flex, and avoid the need for another nested component within the Grid item by replacing the parent of StyledValueBox with:

Suggested change
export const StyledValueBox = styled(Box, {
label: 'StyledValueBox',
})(({ theme }) => ({
'& > button': {
marginTop: '-5px',
},
'& > div': {
alignSelf: 'flex-start',
verticalAlign: 'sub',
},
'& button.MuiButtonBase-root': {
marginTop: '0',
},
'& button.copy-tooltip': {
marginTop: '-3px',
},
color: theme.palette.mode === 'dark' ? theme.color.grey8 : theme.color.black,
display: 'flex',
padding: '3px 5px',
}));
export const StyledGridValue= styled(Grid2, {
label: 'StyledGridValue',
})(({ theme }) => ({
alignItems: 'center',
color: theme.palette.mode === 'dark' ? theme.color.grey8 : theme.color.black,
display: 'flex',
padding: `0 ${theme.spacing()}`,
}));

I was seeing some weirdness with the icons existing outside the grid container at really small screen sizes (which is also currently happening), so might need to make some adjustments to this still.

Screenshot 2024-10-16 at 4 07 16β€―PM

Loading
Loading