Skip to content

Commit be2b36a

Browse files
authored
Merge pull request #890 from terrestris/create-entities-from-provider-endpoints
Introduce buttons to create users, groups and roles from the respective provider
2 parents 0d0cf07 + a47407f commit be2b36a

File tree

26 files changed

+1427
-552
lines changed

26 files changed

+1427
-552
lines changed

package-lock.json

Lines changed: 11 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"@monaco-editor/react": "4.6.0",
4141
"@terrestris/base-util": "3.0.0",
4242
"@terrestris/ol-util": "21.0.0",
43-
"@terrestris/shogun-util": "9.1.1",
43+
"@terrestris/shogun-util": "10.2.0",
4444
"@uiw/react-md-editor": "4.0.4",
4545
"antd": "5.21.5",
4646
"i18next-browser-languagedetector": "8.0.0",
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React from 'react';
2+
3+
import {
4+
cleanup,
5+
fireEvent,
6+
render,
7+
screen,
8+
waitForElementToBeRemoved
9+
} from '@testing-library/react';
10+
11+
import SHOGunAPIClient from '@terrestris/shogun-util/dist/service/SHOGunAPIClient';
12+
13+
import { CreateAllGroupsButton } from './CreateAllGroupsButton';
14+
import GroupService from '@terrestris/shogun-util/dist/service/GroupService';
15+
import Group from '@terrestris/shogun-util/dist/model/Group';
16+
17+
import type { PartialOmit } from '../../test-util';
18+
19+
const mockService: Partial<GroupService<Group>> = {
20+
createAllFromProvider: jest.fn()
21+
};
22+
23+
const mockSHOGunAPIClient: PartialOmit<SHOGunAPIClient, 'group'> = {
24+
group: jest.fn().mockReturnValue(mockService)
25+
};
26+
27+
jest.mock('../../Hooks/useSHOGunAPIClient', () => {
28+
const originalModule = jest.requireActual('../../Hooks/useSHOGunAPIClient');
29+
return {
30+
__esModule: true,
31+
...originalModule,
32+
default: jest.fn(() => mockSHOGunAPIClient)
33+
};
34+
});
35+
36+
describe('<CreateAllGroupsButton />', () => {
37+
38+
afterEach(cleanup);
39+
40+
it('can be rendered', () => {
41+
const {
42+
container
43+
} = render(
44+
<CreateAllGroupsButton />);
45+
46+
expect(container).toBeVisible();
47+
});
48+
49+
it('calls the appropriate service method', async () => {
50+
render(<CreateAllGroupsButton />);
51+
52+
const buttonElement = screen.getByText('CreateAllGroupsButton.title');
53+
54+
fireEvent.click(buttonElement);
55+
56+
expect(mockSHOGunAPIClient.group().createAllFromProvider).toHaveBeenCalled();
57+
58+
await waitForElementToBeRemoved(() => screen.queryByLabelText('loading'));
59+
60+
expect(screen.getByText('CreateAllGroupsButton.success')).toBeVisible();
61+
});
62+
});
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import React, {
2+
useState
3+
} from 'react';
4+
5+
import {
6+
UsergroupAddOutlined
7+
} from '@ant-design/icons';
8+
import {
9+
Button,
10+
message,
11+
Tooltip
12+
} from 'antd';
13+
import { ButtonProps } from 'antd/lib/button';
14+
15+
import { useTranslation } from 'react-i18next';
16+
17+
import useSHOGunAPIClient from '../../Hooks/useSHOGunAPIClient';
18+
19+
import Logger from '../../Logger';
20+
21+
export type CreateAllGroupsButtonProps = Omit<ButtonProps, 'onClick' | 'loading'> & {
22+
onSuccess?: () => void;
23+
onError?: (error: any) => void;
24+
};
25+
26+
export const CreateAllGroupsButton: React.FC<CreateAllGroupsButtonProps> = ({
27+
onSuccess,
28+
onError,
29+
...passThroughProps
30+
}) => {
31+
32+
const [isLoading, setIsLoading] = useState<boolean>(false);
33+
34+
const [messageApi, contextHolder] = message.useMessage();
35+
36+
const client = useSHOGunAPIClient();
37+
38+
const {
39+
t
40+
} = useTranslation();
41+
42+
const onCreateGroupsClick = async () => {
43+
setIsLoading(true);
44+
45+
try {
46+
await client?.group().createAllFromProvider();
47+
48+
messageApi.success(t('CreateAllGroupsButton.success'));
49+
50+
onSuccess?.();
51+
} catch (error) {
52+
messageApi.error(t('CreateAllGroupsButton.error'));
53+
54+
Logger.error('Error while creating the groups: ', error);
55+
56+
onError?.(error);
57+
} finally {
58+
setIsLoading(false);
59+
}
60+
};
61+
62+
return (
63+
<>
64+
{contextHolder}
65+
<Tooltip
66+
title={t('CreateAllGroupsButton.tooltip')}
67+
>
68+
<Button
69+
onClick={onCreateGroupsClick}
70+
loading={isLoading}
71+
icon={<UsergroupAddOutlined />}
72+
{...passThroughProps}
73+
>
74+
{t('CreateAllGroupsButton.title')}
75+
</Button>
76+
</Tooltip>
77+
</>
78+
);
79+
};
80+
81+
export default CreateAllGroupsButton;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React from 'react';
2+
3+
import {
4+
cleanup,
5+
fireEvent,
6+
render,
7+
screen,
8+
waitForElementToBeRemoved
9+
} from '@testing-library/react';
10+
11+
import SHOGunAPIClient from '@terrestris/shogun-util/dist/service/SHOGunAPIClient';
12+
13+
import { CreateAllRolesButton } from './CreateAllRolesButton';
14+
import RoleService from '@terrestris/shogun-util/dist/service/RoleService';
15+
import Role from '@terrestris/shogun-util/dist/model/Role';
16+
17+
import type { PartialOmit } from '../../test-util';
18+
19+
const mockService: Partial<RoleService<Role>> = {
20+
createAllFromProvider: jest.fn()
21+
};
22+
23+
const mockSHOGunAPIClient: PartialOmit<SHOGunAPIClient, 'role'> = {
24+
role: jest.fn().mockReturnValue(mockService)
25+
};
26+
27+
jest.mock('../../Hooks/useSHOGunAPIClient', () => {
28+
const originalModule = jest.requireActual('../../Hooks/useSHOGunAPIClient');
29+
return {
30+
__esModule: true,
31+
...originalModule,
32+
default: jest.fn(() => mockSHOGunAPIClient)
33+
};
34+
});
35+
36+
describe('<CreateAllRolesButton />', () => {
37+
38+
afterEach(cleanup);
39+
40+
it('can be rendered', () => {
41+
const {
42+
container
43+
} = render(
44+
<CreateAllRolesButton />);
45+
46+
expect(container).toBeVisible();
47+
});
48+
49+
it('calls the appropriate service method', async () => {
50+
render(<CreateAllRolesButton />);
51+
52+
const buttonElement = screen.getByText('CreateAllRolesButton.title');
53+
54+
fireEvent.click(buttonElement);
55+
56+
expect(mockSHOGunAPIClient.role().createAllFromProvider).toHaveBeenCalled();
57+
58+
await waitForElementToBeRemoved(() => screen.queryByLabelText('loading'));
59+
60+
expect(screen.getByText('CreateAllRolesButton.success')).toBeVisible();
61+
});
62+
});
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import React, {
2+
useState
3+
} from 'react';
4+
5+
import {
6+
TagOutlined
7+
} from '@ant-design/icons';
8+
import {
9+
Button,
10+
message,
11+
Tooltip
12+
} from 'antd';
13+
import { ButtonProps } from 'antd/lib/button';
14+
15+
import { useTranslation } from 'react-i18next';
16+
17+
import useSHOGunAPIClient from '../../Hooks/useSHOGunAPIClient';
18+
19+
import Logger from '../../Logger';
20+
21+
export type CreateAllRolesButtonProps = Omit<ButtonProps, 'onClick' | 'loading'> & {
22+
onSuccess?: () => void;
23+
onError?: (error: any) => void;
24+
};
25+
26+
export const CreateAllRolesButton: React.FC<CreateAllRolesButtonProps> = ({
27+
onSuccess,
28+
onError,
29+
...passThroughProps
30+
}) => {
31+
32+
const [isLoading, setIsLoading] = useState<boolean>(false);
33+
34+
const [messageApi, contextHolder] = message.useMessage();
35+
36+
const client = useSHOGunAPIClient();
37+
38+
const {
39+
t
40+
} = useTranslation();
41+
42+
const onCreateRolesClick = async () => {
43+
setIsLoading(true);
44+
45+
try {
46+
await client?.role().createAllFromProvider();
47+
48+
messageApi.success(t('CreateAllRolesButton.success'));
49+
50+
onSuccess?.();
51+
} catch (error) {
52+
messageApi.error(t('CreateAllRolesButton.error'));
53+
54+
Logger.error('Error while creating the roles: ', error);
55+
56+
onError?.(error);
57+
} finally {
58+
setIsLoading(false);
59+
}
60+
};
61+
62+
return (
63+
<>
64+
{contextHolder}
65+
<Tooltip
66+
title={t('CreateAllRolesButton.tooltip')}
67+
>
68+
<Button
69+
onClick={onCreateRolesClick}
70+
loading={isLoading}
71+
icon={<TagOutlined />}
72+
{...passThroughProps}
73+
>
74+
{t('CreateAllRolesButton.title')}
75+
</Button>
76+
</Tooltip>
77+
</>
78+
);
79+
};
80+
81+
export default CreateAllRolesButton;

0 commit comments

Comments
 (0)