Skip to content

Commit 7316711

Browse files
PR changes
1 parent 455b36d commit 7316711

File tree

8 files changed

+88
-98
lines changed

8 files changed

+88
-98
lines changed

src/components/ControlPlanes/List/ControlPlaneListWorkspaceGridTile.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import IllustrationMessageType from '@ui5/webcomponents-fiori/dist/types/Illustr
2222
import styles from './WorkspacesList.module.css';
2323
import { ControlPlanesListMenu } from '../ControlPlanesListMenu.tsx';
2424
import { CreateManagedControlPlaneWizardContainer } from '../../Wizards/CreateManagedControlPlane/CreateManagedControlPlaneWizardContainer.tsx';
25-
import { useDeleteWorkspace } from '../../../hooks/useDeleteWorkspace.tsx';
25+
import { useDeleteWorkspace } from '../../../hooks/useDeleteWorkspace.ts';
2626

2727
interface Props {
2828
projectName: string;

src/components/Dialogs/CreateWorkspaceDialogContainer.cy.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@ import { useCreateWorkspace, CreateWorkspaceParams } from '../../hooks/useCreate
33
import { useAuthOnboarding } from '../../spaces/onboarding/auth/AuthContextOnboarding';
44

55
describe('CreateWorkspaceDialogContainer', () => {
6-
let createWorkspacePayload: Omit<CreateWorkspaceParams, 'namespace'> | null = null;
6+
let createWorkspacePayload: CreateWorkspaceParams | null = null;
77

88
const fakeUseCreateWorkspace: typeof useCreateWorkspace = () => ({
9-
createWorkspace: async (data: Omit<CreateWorkspaceParams, 'namespace'>): Promise<boolean> => {
9+
createWorkspace: async (data: CreateWorkspaceParams): Promise<void> => {
1010
createWorkspacePayload = data;
11-
return true;
1211
},
1312
isLoading: false,
14-
errorDialogRef: { current: null },
1513
});
1614

1715
const fakeUseAuthOnboarding = (() => ({
@@ -41,6 +39,7 @@ describe('CreateWorkspaceDialogContainer', () => {
4139
name: 'test-workspace',
4240
displayName: 'Test Workspace Display Name',
4341
chargingTarget: '12345678-1234-1234-1234-123456789abc',
42+
chargingTargetType: 'btp',
4443
members: [
4544
{
4645
@@ -127,11 +126,10 @@ describe('CreateWorkspaceDialogContainer', () => {
127126

128127
it('should not close dialog when creation fails', () => {
129128
const failingUseCreateWorkspace: typeof useCreateWorkspace = () => ({
130-
createWorkspace: async (): Promise<boolean> => {
131-
return false; // Simulate failure
129+
createWorkspace: async (): Promise<void> => {
130+
throw new Error('Creation failed'); // Simulate failure by throwing error
132131
},
133132
isLoading: false,
134-
errorDialogRef: { current: null },
135133
});
136134

137135
const setIsOpen = cy.stub();

src/components/Dialogs/CreateWorkspaceDialogContainer.tsx

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import { useCallback, useEffect, useMemo } from 'react';
1+
import { useCallback, useEffect, useMemo, useRef } from 'react';
22
import { CreateProjectWorkspaceDialog, OnCreatePayload } from './CreateProjectWorkspaceDialog.tsx';
33
import { projectnameToNamespace } from '../../utils';
4-
import { useAuthOnboarding } from '../../spaces/onboarding/auth/AuthContextOnboarding.tsx';
4+
import { useAuthOnboarding as _useAuthOnboarding } from '../../spaces/onboarding/auth/AuthContextOnboarding.tsx';
55
import { Member, MemberRoles } from '../../lib/api/types/shared/members.ts';
66
import { useTranslation } from 'react-i18next';
77
import { zodResolver } from '@hookform/resolvers/zod';
88
import { useForm } from 'react-hook-form';
99
import { createProjectWorkspaceSchema } from '../../lib/api/validations/schemas.ts';
1010
import { ComponentsListItem } from '../../lib/api/types/crate/createManagedControlPlane.ts';
11-
import { useCreateWorkspace } from '../../hooks/useCreateWorkspace.tsx';
11+
import { useCreateWorkspace as _useCreateWorkspace } from '../../hooks/useCreateWorkspace.ts';
12+
import { APIError } from '../../lib/api/error.ts';
13+
import { ErrorDialogHandle } from '../Shared/ErrorMessageBox.tsx';
1214

1315
export type CreateDialogProps = {
1416
name: string;
@@ -23,14 +25,14 @@ export function CreateWorkspaceDialogContainer({
2325
isOpen,
2426
setIsOpen,
2527
project = '',
26-
useCreateWorkspace: useCreateWorkspaceHook = useCreateWorkspace,
27-
useAuthOnboarding: useAuthOnboardingHook = useAuthOnboarding,
28+
useCreateWorkspace: useCreateWorkspaceHook = _useCreateWorkspace,
29+
useAuthOnboarding: useAuthOnboardingHook = _useAuthOnboarding,
2830
}: {
2931
isOpen: boolean;
3032
setIsOpen: (isOpen: boolean) => void;
3133
project?: string;
32-
useCreateWorkspace?: typeof useCreateWorkspace;
33-
useAuthOnboarding?: typeof useAuthOnboarding;
34+
useCreateWorkspace?: typeof _useCreateWorkspace;
35+
useAuthOnboarding?: typeof _useAuthOnboarding;
3436
}) {
3537
const { t } = useTranslation();
3638
const validationSchemaProjectWorkspace = useMemo(() => createProjectWorkspaceSchema(t), [t]);
@@ -56,7 +58,8 @@ export function CreateWorkspaceDialogContainer({
5658
const username = user?.email;
5759
const namespace = projectnameToNamespace(project);
5860

59-
const { createWorkspace, errorDialogRef } = useCreateWorkspaceHook(project, namespace);
61+
const { createWorkspace } = useCreateWorkspaceHook(project, namespace);
62+
const errorDialogRef = useRef<ErrorDialogHandle>(null);
6063

6164
const clearForm = useCallback(() => {
6265
resetField('name');
@@ -78,20 +81,28 @@ export function CreateWorkspaceDialogContainer({
7881
name,
7982
displayName,
8083
chargingTarget,
84+
chargingTargetType,
8185
members,
8286
}: OnCreatePayload): Promise<boolean> => {
83-
const success = await createWorkspace({
84-
name,
85-
displayName,
86-
chargingTarget,
87-
members,
88-
});
89-
90-
if (success) {
87+
try {
88+
await createWorkspace({
89+
name,
90+
displayName,
91+
chargingTarget,
92+
chargingTargetType,
93+
members,
94+
});
9195
setIsOpen(false);
96+
return true;
97+
} catch (e) {
98+
console.error(e);
99+
if (e instanceof APIError) {
100+
if (errorDialogRef.current) {
101+
errorDialogRef.current.showErrorDialog(`${e.message}: ${JSON.stringify(e.info)}`);
102+
}
103+
}
104+
return false;
92105
}
93-
94-
return success;
95106
};
96107

97108
return (

src/hooks/useCreateWorkspace.spec.tsx renamed to src/hooks/useCreateWorkspace.spec.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,11 @@ describe('useCreateWorkspace', () => {
5454
const renderHookResult = renderHook(() => useCreateWorkspace('test-project', 'test-project--ns'));
5555
const { createWorkspace } = renderHookResult.result.current;
5656

57-
let result: boolean = false;
5857
await act(async () => {
59-
result = await createWorkspace(mockWorkspaceData);
58+
await createWorkspace(mockWorkspaceData);
6059
});
6160

6261
// ASSERT
63-
expect(result).toBe(true);
6462
expect(fetchMock).toHaveBeenCalledTimes(1);
6563

6664
const call = fetchMock.mock.calls[0];
@@ -88,7 +86,7 @@ describe('useCreateWorkspace', () => {
8886
expect(parsedBody.spec.members[0].name).toBe('[email protected]');
8987
});
9088

91-
it('should return false on API error', async () => {
89+
it('should throw error on API failure', async () => {
9290
// ARRANGE
9391
fetchMock.mockRejectedValue(new Error('API Error'));
9492

@@ -103,12 +101,9 @@ describe('useCreateWorkspace', () => {
103101
const renderHookResult = renderHook(() => useCreateWorkspace('test-project', 'test-project--ns'));
104102
const { createWorkspace } = renderHookResult.result.current;
105103

106-
let result: boolean = true;
104+
// ASSERT
107105
await act(async () => {
108-
result = await createWorkspace(mockWorkspaceData);
106+
await expect(createWorkspace(mockWorkspaceData)).rejects.toThrow('API Error');
109107
});
110-
111-
// ASSERT
112-
expect(result).toBe(false);
113108
});
114109
});

src/hooks/useCreateWorkspace.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { useCallback } from 'react';
2+
import { useApiResourceMutation, useRevalidateApiResource } from '../lib/api/useApiResource';
3+
import { CreateWorkspace, CreateWorkspaceResource, CreateWorkspaceType } from '../lib/api/types/crate/createWorkspace';
4+
import { ListWorkspaces } from '../lib/api/types/crate/listWorkspaces';
5+
import { useToast } from '../context/ToastContext';
6+
import { Member } from '../lib/api/types/shared/members';
7+
import { useTranslation } from 'react-i18next';
8+
9+
export interface CreateWorkspaceParams {
10+
name: string;
11+
displayName?: string;
12+
chargingTarget?: string;
13+
chargingTargetType?: string;
14+
members: Member[];
15+
}
16+
17+
export function useCreateWorkspace(projectName: string, namespace: string) {
18+
const { t } = useTranslation();
19+
const toast = useToast();
20+
21+
const { trigger } = useApiResourceMutation<CreateWorkspaceType>(CreateWorkspaceResource(namespace));
22+
const revalidate = useRevalidateApiResource(ListWorkspaces(projectName));
23+
24+
const createWorkspace = useCallback(
25+
async ({
26+
name,
27+
displayName,
28+
chargingTarget,
29+
chargingTargetType,
30+
members,
31+
}: CreateWorkspaceParams): Promise<void> => {
32+
await trigger(
33+
CreateWorkspace(name, namespace, {
34+
displayName,
35+
chargingTarget,
36+
chargingTargetType,
37+
members,
38+
}),
39+
);
40+
await revalidate();
41+
toast.show(t('CreateWorkspaceDialog.toastMessage'));
42+
},
43+
[trigger, revalidate, toast, t, namespace],
44+
);
45+
46+
return {
47+
createWorkspace,
48+
};
49+
}

src/hooks/useCreateWorkspace.tsx

Lines changed: 0 additions & 63 deletions
This file was deleted.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)