Skip to content

Commit

Permalink
Review comments: pass db to ActionMenu
Browse files Browse the repository at this point in the history
  • Loading branch information
corya-akamai committed Oct 7, 2024
1 parent 6f653bc commit d15f7b8
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 91 deletions.
4 changes: 2 additions & 2 deletions packages/api-v4/.changeset/pr-11039-added-1727885059968.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
"@linode/api-v4": Added
'@linode/api-v4': Added
---

allow_list to the DatabaseInstance ([#11039](https://github.com/linode/manager/pull/11039))
DBaaS 2.0: Add allow_list to the DatabaseInstance ([#11039](https://github.com/linode/manager/pull/11039))
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
"@linode/manager": Upcoming Features
'@linode/manager': Upcoming Features
---

Landing Page for DBaaS V2 GA ([#11039](https://github.com/linode/manager/pull/11039))
Added Action Menu Column to the Databases Table and update Database Logo ([#11039](https://github.com/linode/manager/pull/11039))
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ import { TableCell } from 'src/components/TableCell';
import { TableRow } from 'src/components/TableRow';
import { Typography } from 'src/components/Typography';
import { useDatabaseMutation } from 'src/queries/databases/databases';
import { stringToExtendedIP } from 'src/utilities/ipUtils';

import AddAccessControlDrawer from './AddAccessControlDrawer';

import type { APIError, Database } from '@linode/api-v4';
import type { Theme } from '@mui/material/styles';
import type { ExtendedIP } from 'src/utilities/ipUtils';

const useStyles = makeStyles()((theme: Theme) => ({
addAccessControlBtn: {
Expand Down Expand Up @@ -86,11 +84,7 @@ interface Props {
}

export const AccessControls = (props: Props) => {
const {
database: { allow_list: allowList, engine, id },
description,
disabled,
} = props;
const { database, description, disabled } = props;

const { classes } = useStyles();

Expand All @@ -107,22 +101,10 @@ export const AccessControls = (props: Props) => {
setAddAccessControlDrawerOpen,
] = React.useState<boolean>(false);

const [extendedIPs, setExtendedIPs] = React.useState<ExtendedIP[]>([]);

const {
isPending: databaseUpdating,
mutateAsync: updateDatabase,
} = useDatabaseMutation(engine, id);

React.useEffect(() => {
if (allowList.length > 0) {
const allowListExtended = allowList.map(stringToExtendedIP);

setExtendedIPs(allowListExtended);
} else {
setExtendedIPs([]);
}
}, [allowList]);
} = useDatabaseMutation(database.engine, database.id);

const handleClickRemove = (accessControl: string) => {
setError(undefined);
Expand All @@ -136,7 +118,7 @@ export const AccessControls = (props: Props) => {

const handleRemoveIPAddress = () => {
updateDatabase({
allow_list: allowList.filter(
allow_list: database.allow_list.filter(
(ipAddress) => ipAddress !== accessControlToBeRemoved
),
})
Expand Down Expand Up @@ -206,7 +188,7 @@ export const AccessControls = (props: Props) => {
Manage Access Controls
</Button>
</div>
{ipTable(allowList)}
{ipTable(database.allow_list)}
<ConfirmationDialog
actions={actionsPanel}
onClose={handleDialogClose}
Expand All @@ -222,10 +204,9 @@ export const AccessControls = (props: Props) => {
</Typography>
</ConfirmationDialog>
<AddAccessControlDrawer
allowList={extendedIPs}
database={database}
onClose={() => setAddAccessControlDrawerOpen(false)}
open={addAccessControlDrawerOpen}
updateDatabase={updateDatabase}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers';

import AccessControls from './AccessControls';
import AddAccessControlDrawer from './AddAccessControlDrawer';
import { DatabaseInstance } from '@linode/api-v4';

beforeAll(() => mockMatchMedia());

Expand All @@ -27,13 +28,13 @@ describe('Add Access Controls drawer', () => {

it('Should open with a full list of current inbound sources that are allow listed', async () => {
const IPv4ListWithMasks = IPv4List.map((ip) => `${ip}/32`);
const db = ({
id: 123,
engine: 'Postgres',
allowList: IPv4ListWithMasks,
} as unknown) as DatabaseInstance;
const { getAllByTestId } = renderWithTheme(
<AddAccessControlDrawer
allowList={IPv4ListWithMasks.map(stringToExtendedIP)}
onClose={() => null}
open={true}
updateDatabase={() => null}
/>
<AddAccessControlDrawer database={db} onClose={() => null} open={true} />
);

expect(getAllByTestId('domain-transfer-input')).toHaveLength(
Expand All @@ -46,13 +47,13 @@ describe('Add Access Controls drawer', () => {
});

it('Should have a disabled Add Inbound Sources button until an inbound source field is touched', () => {
const db = ({
id: 123,
engine: 'Postgres',
allowList: IPv4List.map(stringToExtendedIP),
} as unknown) as DatabaseInstance;
const { getByText } = renderWithTheme(
<AddAccessControlDrawer
allowList={IPv4List.map(stringToExtendedIP)}
onClose={() => null}
open={true}
updateDatabase={() => null}
/>
<AddAccessControlDrawer database={db} onClose={() => null} open={true} />
);

const addAccessControlsButton = getByText('Update Access Controls').closest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@ import { useFormik } from 'formik';
import * as React from 'react';
import { makeStyles } from 'tss-react/mui';

import { Database, DatabaseInstance } from '@linode/api-v4';
import { ActionsPanel } from 'src/components/ActionsPanel/ActionsPanel';
import { Drawer } from 'src/components/Drawer';
import { MultipleIPInput } from 'src/components/MultipleIPInput/MultipleIPInput';
import { Notice } from 'src/components/Notice/Notice';
import { Typography } from 'src/components/Typography';
import { enforceIPMasks } from 'src/features/Firewalls/FirewallDetail/Rules/FirewallRuleDrawer.utils';
import { useDatabaseMutation } from 'src/queries/databases/databases';
import { handleAPIErrors } from 'src/utilities/formikErrorUtils';
import {
ExtendedIP,
extendedIPToString,
ipFieldPlaceholder,
stringToExtendedIP,
validateIPs,
} from 'src/utilities/ipUtils';

Expand All @@ -28,10 +31,9 @@ const useStyles = makeStyles()((theme: Theme) => ({
}));

interface Props {
allowList: ExtendedIP[];
database: Database | DatabaseInstance;
onClose: () => void;
open: boolean;
updateDatabase: any;
}

interface Values {
Expand All @@ -41,7 +43,7 @@ interface Values {
type CombinedProps = Props;

const AddAccessControlDrawer = (props: CombinedProps) => {
const { allowList, onClose, open, updateDatabase } = props;
const { database, onClose, open } = props;

const { classes } = useStyles();

Expand All @@ -58,6 +60,11 @@ const AddAccessControlDrawer = (props: CombinedProps) => {
setValues({ _allowList: _ipsWithMasks });
};

const { mutateAsync: updateDatabase } = useDatabaseMutation(
database.engine,
database.id
);

const handleUpdateAccessControlsClick = (
{ _allowList }: Values,
{
Expand Down Expand Up @@ -132,7 +139,7 @@ const AddAccessControlDrawer = (props: CombinedProps) => {
} = useFormik({
enableReinitialize: true,
initialValues: {
_allowList: allowList,
_allowList: database!.allow_list.map(stringToExtendedIP),

Check failure on line 142 in packages/manager/src/features/Databases/DatabaseDetail/AddAccessControlDrawer.tsx

View workflow job for this annotation

GitHub Actions / test-manager

src/features/Databases/DatabaseDetail/AddAccessControlDrawer.test.tsx > Add Access Controls drawer > Should open with a full list of current inbound sources that are allow listed

TypeError: Cannot read properties of undefined (reading 'map') ❯ AddAccessControlDrawer src/features/Databases/DatabaseDetail/AddAccessControlDrawer.tsx:142:40 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:15486:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20103:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21626:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27465:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26599:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26505:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26473:7 ❯ recoverFromConcurrentError ../../node_modules/react-dom/cjs/react-dom.development.js:25889:20 ❯ performSyncWorkOnRoot ../../node_modules/react-dom/cjs/react-dom.development.js:26135:20

Check failure on line 142 in packages/manager/src/features/Databases/DatabaseDetail/AddAccessControlDrawer.tsx

View workflow job for this annotation

GitHub Actions / test-manager

src/features/Databases/DatabaseDetail/AddAccessControlDrawer.test.tsx > Add Access Controls drawer > Should have a disabled Add Inbound Sources button until an inbound source field is touched

TypeError: Cannot read properties of undefined (reading 'map') ❯ AddAccessControlDrawer src/features/Databases/DatabaseDetail/AddAccessControlDrawer.tsx:142:40 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:15486:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20103:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21626:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27465:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26599:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26505:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26473:7 ❯ recoverFromConcurrentError ../../node_modules/react-dom/cjs/react-dom.development.js:25889:20 ❯ performSyncWorkOnRoot ../../node_modules/react-dom/cjs/react-dom.development.js:26135:20
},
onSubmit: handleUpdateAccessControlsClick,
validate: (values: Values) => onValidate(values),
Expand Down Expand Up @@ -182,7 +189,7 @@ const AddAccessControlDrawer = (props: CombinedProps) => {
className={classes.ipSelect}
forDatabaseAccessControls
inputProps={{ autoFocus: true }}
ips={values._allowList}
ips={values._allowList!}
onBlur={handleIPBlur}
onChange={handleIPChange}
placeholder={ipFieldPlaceholder}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ interface Props {
databaseEngine: Engine;
databaseId: number;
databaseLabel: string;
handlers?: ActionHandlers;
handlers: ActionHandlers;
}

export interface ActionHandlers {
handleDelete: () => void;
handleManageAccessControls: () => void;
Expand All @@ -22,6 +23,8 @@ export const DatabaseActionMenu = (props: Props) => {
const { databaseEngine, databaseId, databaseLabel, handlers } = props;

const databaseStatus = 'running';
const isDatabaseNotRunning = databaseStatus !== 'running';

const history = useHistory();

const actions: Action[] = [
Expand All @@ -31,17 +34,17 @@ export const DatabaseActionMenu = (props: Props) => {
// title: databaseStatus === 'running' ? 'Suspend' : 'Power On',
// },
{
disabled: databaseStatus !== 'running',
onClick: handlers ? handlers.handleManageAccessControls : () => {},
disabled: isDatabaseNotRunning,
onClick: handlers.handleManageAccessControls,
title: 'Manage Access Controls',
},
{
disabled: databaseStatus !== 'running',
onClick: handlers ? handlers.handleResetPassword : () => {},
disabled: isDatabaseNotRunning,
onClick: handlers.handleResetPassword,
title: 'Reset Root Password',
},
{
disabled: databaseStatus !== 'running',
disabled: isDatabaseNotRunning,
onClick: () => {
history.push({
pathname: `/databases/${databaseEngine}/${databaseId}/resize`,
Expand All @@ -50,8 +53,8 @@ export const DatabaseActionMenu = (props: Props) => {
title: 'Resize',
},
{
disabled: databaseStatus !== 'running',
onClick: handlers ? handlers.handleDelete : () => {},
disabled: isDatabaseNotRunning,
onClick: handlers.handleDelete,
title: 'Delete',
},
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const managedDBCapability = 'Managed Databases';

const newDBTabTitle = 'New Database Clusters';
const legacyDBTabTitle = 'Legacy Database Clusters';

describe('Database Table Row', () => {
it('should render a database row', () => {
const database = databaseInstanceFactory.build();
Expand Down Expand Up @@ -291,25 +292,17 @@ describe('Database Landing', () => {
it('should have the "Create Database Cluster" button enabled for users with full access', async () => {
queryMocks.useProfile.mockReturnValue({ data: { restricted: false } });

const { getByTestId } = renderWithTheme(<DatabaseLanding />, {
flags: { dbaasV2: { beta: true, enabled: true } },
});
const { container, getByTestId } = renderWithTheme(<DatabaseLanding />);

expect(getByTestId(loadingTestId)).toBeInTheDocument();

await waitForElementToBeRemoved(getByTestId(loadingTestId));

const tables = screen.getAllByRole('table');
expect(tables).toHaveLength(1);

const table = tables[0];

const headers = within(table).getAllByRole('columnheader');
expect(headers.some((header) => header.textContent === 'Plan')).toBe(true);
const createClusterButton = container.querySelector('button');

expect(screen.queryByText('Legacy Database Clusters')).toBeNull();
expect(screen.queryByText('New Database Clusters')).toBeNull();
expect(screen.queryByText('Powered by')).toBeTruthy();
expect(createClusterButton).toBeInTheDocument();
expect(createClusterButton).toHaveTextContent('Create Database Cluster');
expect(createClusterButton).toBeEnabled();
});

it('should render a single new database table with action menu ', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ const DatabaseLanding = () => {
const showTabs = isV2ExistingBetaUser && legacyDatabases?.data.length !== 0;

const hasNoNewDatabases =
newDatabases?.data.length === 0 || newDatabases === undefined;
!newDatabases?.data?.length || newDatabases === undefined;
const hasNoLegacyDatabases =
legacyDatabases?.data.length === 0 || legacyDatabases === undefined;
!legacyDatabases?.data?.length || legacyDatabases === undefined;

const showEmptyForGAUser = isV2GAUser && hasNoNewDatabases;
const showEmpty =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,10 @@ import DatabaseLogo from 'src/features/Databases/DatabaseLanding/DatabaseLogo';
import DatabaseRow from 'src/features/Databases/DatabaseLanding/DatabaseRow';
import { useIsDatabasesEnabled } from 'src/features/Databases/utilities';
import { usePagination } from 'src/hooks/usePagination';
import { useDatabaseMutation } from 'src/queries/databases/databases';
import { useInProgressEvents } from 'src/queries/events/events';
import { stringToExtendedIP } from 'src/utilities/ipUtils';

import type { DatabaseInstance } from '@linode/api-v4/lib/databases';
import type { Engine } from '@linode/api-v4/lib/databases';
import type { Order } from 'src/hooks/useOrder';
import type { ExtendedIP } from 'src/utilities/ipUtils';

const preferenceKey = 'databases';

Expand Down Expand Up @@ -61,22 +57,14 @@ const DatabaseLandingTable = ({
setIsManageAccessControlsDialogOpen,
] = React.useState(false);

const [allowList, setAllowList] = React.useState<ExtendedIP[]>([]);

const { mutateAsync: updateDatabase } = useDatabaseMutation(
selectedDatabase?.engine as Engine,
selectedDatabase?.id as number
);
const handleManageAccessControls = (database: DatabaseInstance) => {
setSelectedDatabase(database);
setAllowList(database.allow_list.map(stringToExtendedIP));
setIsManageAccessControlsDialogOpen(true);
};

const onCloseAccesControls = () => {
setIsManageAccessControlsDialogOpen(false);
setSelectedDatabase(null);
setAllowList([]);
};

const handleDelete = (database: DatabaseInstance) => {
Expand Down Expand Up @@ -196,7 +184,8 @@ const DatabaseLandingTable = ({
page={pagination.page}
pageSize={pagination.pageSize}
/>
{isNewDatabase ? (
<h1>what</h1>
{isNewDatabase && (
<>
<DatabaseLogo />
{selectedDatabase && (
Expand All @@ -214,17 +203,14 @@ const DatabaseLandingTable = ({
onClose={() => setIsResetPasswordsDialogOpen(false)}
open={isResetPasswordsDialogOpen}
/>
<AddAccessControlDrawer
database={selectedDatabase}
onClose={onCloseAccesControls}
open={isManageAccessControlsDialogOpen}
/>
</>
)}
<AddAccessControlDrawer
allowList={allowList}
onClose={onCloseAccesControls}
open={isManageAccessControlsDialogOpen}
updateDatabase={updateDatabase}
/>
</>
) : (
''
)}
</>
);
Expand Down
Loading

0 comments on commit d15f7b8

Please sign in to comment.