Skip to content

Commit dc1fbdb

Browse files
new: STORIF-320 - Object storage creation flow updated.
1 parent b710851 commit dc1fbdb

27 files changed

+603
-494
lines changed

packages/manager/src/features/Account/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export const CUSTOMER_SUPPORT = 'customer support';
55
export const grantTypeMap = {
66
account: 'Account',
77
bucket: 'Buckets',
8+
key: 'Access Keys',
89
database: 'Databases',
910
domain: 'Domains',
1011
firewall: 'Firewalls',

packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyDrawer.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as React from 'react';
44
import { objectStorageBucketFactory } from 'src/factories/objectStorage';
55
import { renderWithTheme } from 'src/utilities/testHelpers';
66

7-
import { AccessKeyDrawer, getDefaultScopes } from './AccessKeyDrawer';
7+
import { AccessKeyDrawerV1, getDefaultScopes } from './AccessKeyDrawer';
88
import { getUpdatedScopes } from './AccessTable';
99

1010
import type { AccessKeyDrawerProps } from './AccessKeyDrawer';
@@ -19,7 +19,7 @@ describe('AccessKeyDrawer', () => {
1919
onSubmit: vi.fn(),
2020
open: true,
2121
};
22-
renderWithTheme(<AccessKeyDrawer {...props} />);
22+
renderWithTheme(<AccessKeyDrawerV1 {...props} />);
2323
it('renders without crashing', () => {
2424
expect(screen.getByTestId('drawer-title')).toBeInTheDocument();
2525
});

packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyDrawer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export const getDefaultScopes = (
7878
}))
7979
.sort(sortByCluster);
8080

81-
export const AccessKeyDrawer = (props: AccessKeyDrawerProps) => {
81+
export const AccessKeyDrawerV1 = (props: AccessKeyDrawerProps) => {
8282
const { isRestrictedUser, mode, objectStorageKey, onClose, onSubmit, open } =
8383
props;
8484

packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyLanding.test.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,9 @@ import { renderWithTheme } from 'src/utilities/testHelpers';
44

55
import { AccessKeyLanding } from './AccessKeyLanding';
66

7-
const props = {
8-
accessDrawerOpen: false,
9-
closeAccessDrawer: vi.fn(),
10-
isRestrictedUser: false,
11-
mode: 'creating' as any,
12-
openAccessDrawer: vi.fn(),
13-
};
14-
157
describe('AccessKeyLanding', () => {
168
it('should render a table of access keys', async () => {
17-
const { getByTestId } = renderWithTheme(<AccessKeyLanding {...props} />);
9+
const { getByTestId } = renderWithTheme(<AccessKeyLanding />);
1810
expect(getByTestId('data-qa-access-key-table')).toBeInTheDocument();
1911
});
2012
});
Lines changed: 21 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,22 @@
1-
import {
2-
createObjectStorageKeys,
3-
revokeObjectStorageKey,
4-
updateObjectStorageKey,
5-
} from '@linode/api-v4/lib/object-storage';
6-
import { useAccountSettings } from '@linode/queries';
1+
import { revokeObjectStorageKey } from '@linode/api-v4/lib/object-storage';
72
import { useErrors, useOpenClose } from '@linode/utilities';
83
import { useNavigate } from '@tanstack/react-router';
94
import * as React from 'react';
105

116
import { DocumentTitleSegment } from 'src/components/DocumentTitle';
127
import { PaginationFooter } from 'src/components/PaginationFooter/PaginationFooter';
13-
import { SecretTokenDialog } from 'src/features/Profile/SecretTokenDialog/SecretTokenDialog';
148
import { usePaginationV2 } from 'src/hooks/usePaginationV2';
159
import { useObjectStorageAccessKeys } from 'src/queries/object-storage/queries';
16-
import {
17-
sendCreateAccessKeyEvent,
18-
sendEditAccessKeyEvent,
19-
sendRevokeAccessKeyEvent,
20-
} from 'src/utilities/analytics/customEventAnalytics';
21-
import { getAPIErrorOrDefault, getErrorMap } from 'src/utilities/errorUtils';
10+
import { sendRevokeAccessKeyEvent } from 'src/utilities/analytics/customEventAnalytics';
11+
import { getAPIErrorOrDefault } from 'src/utilities/errorUtils';
2212

23-
import { useIsObjMultiClusterEnabled } from '../hooks/useIsObjectStorageGen2Enabled';
24-
import { AccessKeyDrawer } from './AccessKeyDrawer';
2513
import { AccessKeyTable } from './AccessKeyTable/AccessKeyTable';
26-
import { OMC_AccessKeyDrawer } from './OMC_AccessKeyDrawer';
2714
import { RevokeAccessKeyDialog } from './RevokeAccessKeyDialog';
28-
import { ViewPermissionsDrawer } from './ViewPermissionsDrawer';
2915

3016
import type { MODE, OpenAccessDrawer } from './types';
31-
import type {
32-
CreateObjectStorageKeyPayload,
33-
ObjectStorageKey,
34-
UpdateObjectStorageKeyPayload,
35-
} from '@linode/api-v4/lib/object-storage';
36-
import type { FormikBag, FormikHelpers } from 'formik';
37-
38-
interface Props {
39-
accessDrawerOpen: boolean;
40-
closeAccessDrawer: () => void;
41-
isRestrictedUser: boolean;
42-
mode: MODE;
43-
openAccessDrawer: (mode: MODE) => void;
44-
}
45-
46-
export type FormikProps = FormikBag<Props, CreateObjectStorageKeyPayload>;
47-
48-
export const AccessKeyLanding = (props: Props) => {
49-
const {
50-
accessDrawerOpen,
51-
closeAccessDrawer,
52-
isRestrictedUser,
53-
mode,
54-
openAccessDrawer,
55-
} = props;
17+
import type { ObjectStorageKey } from '@linode/api-v4/lib/object-storage';
5618

19+
export const AccessKeyLanding = () => {
5720
const navigate = useNavigate();
5821
const pagination = usePaginationV2({
5922
currentRoute: '/object-storage/access-keys',
@@ -66,30 +29,15 @@ export const AccessKeyLanding = (props: Props) => {
6629
page_size: pagination.pageSize,
6730
});
6831

69-
const { data: accountSettings, refetch: requestAccountSettings } =
70-
useAccountSettings();
71-
72-
// Key to display in Confirmation Modal upon creation
73-
const [keyToDisplay, setKeyToDisplay] =
74-
React.useState<null | ObjectStorageKey>(null);
75-
76-
// Key to rename (by clicking on a key's kebab menu )
77-
const [keyToEdit, setKeyToEdit] = React.useState<null | ObjectStorageKey>(
78-
null
79-
);
80-
8132
// Key to revoke (by clicking on a key's kebab menu )
8233
const [keyToRevoke, setKeyToRevoke] = React.useState<null | ObjectStorageKey>(
8334
null
8435
);
8536
const [isRevoking, setIsRevoking] = React.useState<boolean>(false);
8637
const [revokeErrors, setRevokeErrors] = useErrors();
8738

88-
const displayKeysDialog = useOpenClose();
8939
const revokeKeysDialog = useOpenClose();
9040

91-
const { isObjMultiClusterEnabled } = useIsObjMultiClusterEnabled();
92-
9341
// Redirect to base access keys route if current page has no data
9442
// TODO: Remove this implementation and replace `usePagination` with `usePaginate` hook. See [M3-10442]
9543
React.useEffect(() => {
@@ -109,123 +57,6 @@ export const AccessKeyLanding = (props: Props) => {
10957
}
11058
}, [data, isLoading, pagination.page, navigate]);
11159

112-
const handleCreateKey = (
113-
values: CreateObjectStorageKeyPayload,
114-
{
115-
setErrors,
116-
setStatus,
117-
setSubmitting,
118-
}: FormikHelpers<CreateObjectStorageKeyPayload>
119-
) => {
120-
// Clear out status (used for general errors)
121-
setStatus(null);
122-
setSubmitting(true);
123-
124-
createObjectStorageKeys(values)
125-
.then((data) => {
126-
setSubmitting(false);
127-
128-
setKeyToDisplay(data);
129-
130-
// "Refresh" keys to include the newly created key
131-
refetch();
132-
133-
props.closeAccessDrawer();
134-
displayKeysDialog.open();
135-
136-
// If our Redux Store says that the user doesn't have OBJ enabled,
137-
// it probably means they have just enabled it with the creation
138-
// of this key. In that case, update the Redux Store so that
139-
// subsequently created keys don't need to go through the
140-
// confirmation flow.
141-
if (accountSettings?.object_storage === 'disabled') {
142-
requestAccountSettings();
143-
}
144-
145-
// @analytics
146-
sendCreateAccessKeyEvent();
147-
})
148-
.catch((errorResponse) => {
149-
// We also need to refresh account settings on failure, since, depending
150-
// on the error, Object Storage service might have actually been enabled.
151-
if (accountSettings?.object_storage === 'disabled') {
152-
requestAccountSettings();
153-
}
154-
155-
setSubmitting(false);
156-
157-
const errors = getAPIErrorOrDefault(
158-
errorResponse,
159-
'There was an issue creating your Access Key.'
160-
);
161-
const mappedErrors = getErrorMap(['label'], errors);
162-
163-
// `status` holds general errors
164-
if (mappedErrors.none) {
165-
setStatus(mappedErrors.none);
166-
}
167-
168-
setErrors(mappedErrors);
169-
});
170-
};
171-
172-
const handleEditKey = (
173-
values: UpdateObjectStorageKeyPayload,
174-
{
175-
setErrors,
176-
setStatus,
177-
setSubmitting,
178-
}: FormikHelpers<UpdateObjectStorageKeyPayload>
179-
) => {
180-
// This shouldn't happen, but just in case.
181-
if (!keyToEdit) {
182-
return;
183-
}
184-
185-
// Clear out status (used for general errors)
186-
setStatus(null);
187-
188-
// If the new label is the same as the old one, no need to make an API
189-
// request. Just close the drawer and return early.
190-
if (values.label === keyToEdit.label) {
191-
return closeAccessDrawer();
192-
}
193-
194-
setSubmitting(true);
195-
196-
updateObjectStorageKey(
197-
keyToEdit.id,
198-
isObjMultiClusterEnabled ? values : { label: values.label }
199-
)
200-
.then((_) => {
201-
setSubmitting(false);
202-
203-
// "Refresh" keys to display the newly updated key
204-
refetch();
205-
206-
closeAccessDrawer();
207-
208-
// @analytics
209-
sendEditAccessKeyEvent();
210-
})
211-
.catch((errorResponse) => {
212-
setSubmitting(false);
213-
214-
const errors = getAPIErrorOrDefault(
215-
errorResponse,
216-
'There was an issue updating your Access Key.'
217-
);
218-
const mappedErrors = getErrorMap(['label'], errors);
219-
220-
// `status` holds general errors
221-
if (mappedErrors.none) {
222-
setStatus(mappedErrors.none);
223-
}
224-
225-
setErrors(mappedErrors);
226-
});
227-
};
228-
22960
const handleRevokeKeys = () => {
23061
// This shouldn't happen, but just in case.
23162
if (!keyToRevoke) {
@@ -260,12 +91,19 @@ export const AccessKeyLanding = (props: Props) => {
26091

26192
const openDrawer: OpenAccessDrawer = (
26293
mode: MODE,
263-
objectStorageKey: null | ObjectStorageKey = null
94+
objectStorageKey: ObjectStorageKey
26495
) => {
265-
setKeyToEdit(objectStorageKey);
266-
if (mode !== 'creating') {
267-
openAccessDrawer(mode);
96+
let drawerUrl = `/object-storage/access-keys/${objectStorageKey.id}`;
97+
98+
if (mode === 'editing') {
99+
drawerUrl += `/update`;
100+
}
101+
102+
if (mode === 'viewing') {
103+
drawerUrl += `/details`;
268104
}
105+
106+
navigate({ to: drawerUrl });
269107
};
270108

271109
const openRevokeDialog = (objectStorageKey: ObjectStorageKey) => {
@@ -279,19 +117,18 @@ export const AccessKeyLanding = (props: Props) => {
279117
};
280118

281119
return (
282-
<div>
283-
<DocumentTitleSegment
284-
segment={`${accessDrawerOpen ? `Create an Access Key` : `Access Keys`}`}
285-
/>
120+
<>
121+
<DocumentTitleSegment segment="Access Keys" />
122+
286123
<AccessKeyTable
287124
data={data?.data}
288125
data-qa-access-key-table
289126
error={error}
290127
isLoading={isLoading}
291-
isRestrictedUser={isRestrictedUser}
292128
openDrawer={openDrawer}
293129
openRevokeDialog={openRevokeDialog}
294130
/>
131+
295132
<PaginationFooter
296133
count={data?.results || 0}
297134
eventCategory="object storage keys table"
@@ -301,37 +138,6 @@ export const AccessKeyLanding = (props: Props) => {
301138
pageSize={pagination.pageSize}
302139
/>
303140

304-
{isObjMultiClusterEnabled ? (
305-
<OMC_AccessKeyDrawer
306-
isRestrictedUser={props.isRestrictedUser}
307-
mode={mode}
308-
objectStorageKey={keyToEdit ? keyToEdit : undefined}
309-
onClose={closeAccessDrawer}
310-
onSubmit={mode === 'creating' ? handleCreateKey : handleEditKey}
311-
open={accessDrawerOpen}
312-
/>
313-
) : (
314-
<AccessKeyDrawer
315-
isRestrictedUser={props.isRestrictedUser}
316-
mode={mode}
317-
objectStorageKey={keyToEdit ? keyToEdit : undefined}
318-
onClose={closeAccessDrawer}
319-
onSubmit={mode === 'creating' ? handleCreateKey : handleEditKey}
320-
open={accessDrawerOpen}
321-
/>
322-
)}
323-
324-
<ViewPermissionsDrawer
325-
objectStorageKey={keyToEdit}
326-
onClose={closeAccessDrawer}
327-
open={mode === 'viewing' && accessDrawerOpen}
328-
/>
329-
<SecretTokenDialog
330-
objectStorageKey={keyToDisplay}
331-
onClose={displayKeysDialog.close}
332-
open={displayKeysDialog.isOpen}
333-
title="Access Keys"
334-
/>
335141
<RevokeAccessKeyDialog
336142
errors={revokeErrors}
337143
handleClose={closeRevokeDialog}
@@ -341,6 +147,6 @@ export const AccessKeyLanding = (props: Props) => {
341147
label={keyToRevoke?.label || ''}
342148
numAccessKeys={data?.results || 0}
343149
/>
344-
</div>
150+
</>
345151
);
346152
};

packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/AccessKeyTable.test.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ describe('ObjectStorageKeyTable', () => {
1111
data: [],
1212
error: undefined,
1313
isLoading: false,
14-
isRestrictedUser: false,
1514
openDrawer: vi.fn(),
1615
openRevokeDialog: vi.fn(),
1716
};

0 commit comments

Comments
 (0)