Skip to content

Commit 57b770b

Browse files
feat: roles and permissions button redirect added (#2975)
* feat: roles and permissions button redirect added
1 parent f36b869 commit 57b770b

6 files changed

Lines changed: 75 additions & 3 deletions

File tree

src/header/hooks.test.tsx

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ describe('header utils', () => {
108108
});
109109
const actualItems =
110110
renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
111-
expect(actualItems).toHaveLength(6);
111+
expect(actualItems).toHaveLength(7);
112112
});
113113
it('when certificate page disabled should not include certificates option', () => {
114114
setConfig({
@@ -117,7 +117,7 @@ describe('header utils', () => {
117117
});
118118
const actualItems =
119119
renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
120-
expect(actualItems).toHaveLength(5);
120+
expect(actualItems).toHaveLength(6);
121121
});
122122
it('when user has access to advanced settings should include advanced settings option', () => {
123123
const actualItemsTitle = renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result
@@ -174,6 +174,20 @@ describe('header utils', () => {
174174
expect(actualItemsTitle).not.toContain('Advanced Settings');
175175
});
176176
});
177+
178+
it('should include roles and permissions option', () => {
179+
setConfig({
180+
...getConfig(),
181+
ADMIN_CONSOLE_URL: 'http://admin-console.example.com',
182+
});
183+
const actualItems =
184+
renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
185+
const rolesPermissionsItem = actualItems.find(item => item.title === 'Roles and Permissions');
186+
expect(rolesPermissionsItem).toEqual({
187+
href: 'http://admin-console.example.com/authz?scope=course-123',
188+
title: 'Roles and Permissions',
189+
});
190+
});
177191
});
178192

179193
describe('getToolsMenuItems', () => {
@@ -227,7 +241,21 @@ describe('header utils', () => {
227241
});
228242

229243
describe('useLibrarySettingsMenuItems', () => {
244+
let originalConfig: any;
245+
246+
beforeEach(() => {
247+
originalConfig = { ...getConfig() };
248+
});
249+
250+
afterEach(() => {
251+
setConfig(originalConfig);
252+
});
253+
230254
it('should contain team access url', () => {
255+
const configWithoutAdminConsole = { ...getConfig() };
256+
delete configWithoutAdminConsole.ADMIN_CONSOLE_URL;
257+
setConfig(configWithoutAdminConsole);
258+
231259
const items =
232260
renderHook(() => useLibrarySettingsMenuItems('library-123', false), { wrapper: createWrapper() }).result
233261
.current;

src/header/hooks.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ export const useSettingMenuItems = (courseId: string) => {
9292
href: `/course/${courseId}/settings/grading`,
9393
title: intl.formatMessage(messages['header.links.grading']),
9494
},
95+
{
96+
href: `${getConfig().ADMIN_CONSOLE_URL}/authz?scope=${courseId}`,
97+
title: intl.formatMessage(messages['header.links.roles.permissions']),
98+
},
9599
{
96100
href: `/course/${courseId}/course_team`,
97101
title: intl.formatMessage(messages['header.links.courseTeam']),

src/header/messages.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ const messages = defineMessages({
6161
defaultMessage: 'Grading',
6262
description: 'Link to Studio Grading page',
6363
},
64+
'header.links.roles.permissions': {
65+
id: 'header.links.roles.permissions',
66+
defaultMessage: 'Roles and Permissions',
67+
description: 'Link to Studio Roles and Permissions page',
68+
},
6469
'header.links.courseTeam': {
6570
id: 'header.links.courseTeam',
6671
defaultMessage: 'Course Team',

src/studio-home/StudioHome.test.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as reactRedux from 'react-redux';
2+
import { getConfig, setConfig } from '@edx/frontend-platform';
23

34
import {
45
fireEvent,
@@ -91,6 +92,18 @@ describe('<StudioHome />', () => {
9192
within(header).getByRole('button', { name: 'New course' }); // will error if not found
9293
});
9394

95+
it('should render roles and permissions button', async () => {
96+
setConfig({
97+
...getConfig(),
98+
ADMIN_CONSOLE_URL: 'https://admin-console.example.com',
99+
});
100+
101+
render(<StudioHome />, { path: '/home' });
102+
const header = getHeaderElement();
103+
const rolesButton = within(header).getByRole('link', { name: 'Roles and permissions' });
104+
expect(rolesButton).toHaveAttribute('href', 'https://admin-console.example.com/authz');
105+
});
106+
94107
it('should show verify email layout if user inactive', async () => {
95108
mockUseSelector.mockReturnValue({
96109
...studioHomeMock,

src/studio-home/StudioHome.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import {
77
MailtoLink,
88
Row,
99
} from '@openedx/paragon';
10-
import { Add as AddIcon, Error } from '@openedx/paragon/icons';
10+
import { Add as AddIcon, Error, ManageAccounts } from '@openedx/paragon/icons';
1111
import { useIntl } from '@edx/frontend-platform/i18n';
12+
import { getConfig } from '@edx/frontend-platform';
1213
import { StudioFooterSlot } from '@edx/frontend-component-footer';
1314
import { useLocation, useNavigate } from 'react-router-dom';
1415

@@ -47,6 +48,8 @@ const StudioHome = () => {
4748
librariesV2Enabled,
4849
} = useStudioHome();
4950

51+
const adminConsoleUrl = `${getConfig().ADMIN_CONSOLE_URL}/authz`;
52+
5053
const v1LibraryTab = librariesV1Enabled && location?.pathname.split('/').pop() === 'libraries-v1';
5154
const showV2LibraryURL = librariesV2Enabled && !v1LibraryTab;
5255

@@ -71,6 +74,20 @@ const StudioHome = () => {
7174
);
7275
}
7376

77+
headerButtons.push(
78+
<div className="border-right mr-3 pr-4 py-2">
79+
<Button
80+
as="a"
81+
href={adminConsoleUrl}
82+
variant="primary"
83+
iconBefore={ManageAccounts}
84+
size="sm"
85+
>
86+
{intl.formatMessage(messages.addRolesPermissionsBtnText)}
87+
</Button>
88+
</div>,
89+
);
90+
7491
if (hasAbilityToCreateNewCourse) {
7592
headerButtons.push(
7693
<Button

src/studio-home/messages.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ const messages = defineMessages({
1313
id: 'course-authoring.studio-home.add-new-library.btn.text',
1414
defaultMessage: 'New library',
1515
},
16+
addRolesPermissionsBtnText: {
17+
id: 'course-authoring.studio-home.add-roles-permissions.btn.text',
18+
defaultMessage: 'Roles and permissions',
19+
description: 'Text for the button that links to the Admin Console Roles and Permissions page.',
20+
},
1621
homePageLoadFailedMessage: {
1722
id: 'course-authoring.studio-home.page-load.failed.message',
1823
defaultMessage: 'Failed to load Studio home. Please try again later.',

0 commit comments

Comments
 (0)