Skip to content

Commit

Permalink
Hide "Advanced Settings" settings item [BB-9081] (#1252)
Browse files Browse the repository at this point in the history
* refactor: convert header utils to hooks

* feat: hide advanced settings button if a user doesn't have access
  • Loading branch information
0x29a authored Sep 12, 2024
1 parent 5672831 commit 45c68d6
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 43 deletions.
5 changes: 5 additions & 0 deletions src/CourseAuthoringPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { fetchCourseDetail } from './data/thunks';
import { useModel } from './generic/model-store';
import NotFoundAlert from './generic/NotFoundAlert';
import PermissionDeniedAlert from './generic/PermissionDeniedAlert';
import { fetchStudioHomeData } from './studio-home/data/thunks';
import { getCourseAppsApiStatus } from './pages-and-resources/data/selectors';
import { RequestStatus } from './data/constants';
import Loading from './generic/Loading';
Expand All @@ -22,6 +23,10 @@ const CourseAuthoringPage = ({ courseId, children }) => {
dispatch(fetchCourseDetail(courseId));
}, [courseId]);

useEffect(() => {
dispatch(fetchStudioHomeData());
}, []);

const courseDetail = useModel('courseDetails', courseId);

const courseNumber = courseDetail ? courseDetail.number : null;
Expand Down
13 changes: 9 additions & 4 deletions src/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useToggle } from '@openedx/paragon';
import { generatePath, useHref } from 'react-router-dom';

import { SearchModal } from '../search-modal';
import { getContentMenuItems, getSettingMenuItems, getToolsMenuItems } from './utils';
import { useContentMenuItems, useSettingMenuItems, useToolsMenuItems } from './hooks';
import messages from './messages';

interface HeaderProps {
Expand All @@ -33,23 +33,28 @@ const Header = ({

const studioBaseUrl = getConfig().STUDIO_BASE_URL;
const meiliSearchEnabled = [true, 'true'].includes(getConfig().MEILISEARCH_ENABLED);

const contentMenuItems = useContentMenuItems(contextId);
const settingMenuItems = useSettingMenuItems(contextId);
const toolsMenuItems = useToolsMenuItems(contextId);
const mainMenuDropdowns = !isLibrary ? [
{
id: `${intl.formatMessage(messages['header.links.content'])}-dropdown-menu`,
buttonTitle: intl.formatMessage(messages['header.links.content']),
items: getContentMenuItems({ studioBaseUrl, courseId: contextId, intl }),
items: contentMenuItems,
},
{
id: `${intl.formatMessage(messages['header.links.settings'])}-dropdown-menu`,
buttonTitle: intl.formatMessage(messages['header.links.settings']),
items: getSettingMenuItems({ studioBaseUrl, courseId: contextId, intl }),
items: settingMenuItems,
},
{
id: `${intl.formatMessage(messages['header.links.tools'])}-dropdown-menu`,
buttonTitle: intl.formatMessage(messages['header.links.tools']),
items: getToolsMenuItems({ studioBaseUrl, courseId: contextId, intl }),
items: toolsMenuItems,
},
] : [];

const outlineLink = !isLibrary
? `${studioBaseUrl}/course/${contextId}`
: generatePath(libraryHref, { libraryId: contextId });
Expand Down
70 changes: 44 additions & 26 deletions src/header/utils.js → src/header/hooks.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useSelector } from 'react-redux';
import { getPagePath } from '../utils';
import { getStudioHomeData } from '../studio-home/data/selectors';
import messages from './messages';

export const getContentMenuItems = ({ studioBaseUrl, courseId, intl }) => {
export const useContentMenuItems = courseId => {
const intl = useIntl();
const studioBaseUrl = getConfig().STUDIO_BASE_URL;

const items = [
{
href: `${studioBaseUrl}/course/${courseId}`,
Expand Down Expand Up @@ -31,7 +37,11 @@ export const getContentMenuItems = ({ studioBaseUrl, courseId, intl }) => {
return items;
};

export const getSettingMenuItems = ({ studioBaseUrl, courseId, intl }) => {
export const useSettingMenuItems = courseId => {
const intl = useIntl();
const studioBaseUrl = getConfig().STUDIO_BASE_URL;
const { canAccessAdvancedSettings } = useSelector(getStudioHomeData);

const items = [
{
href: `${studioBaseUrl}/settings/details/${courseId}`,
Expand All @@ -49,10 +59,12 @@ export const getSettingMenuItems = ({ studioBaseUrl, courseId, intl }) => {
href: `${studioBaseUrl}/group_configurations/${courseId}`,
title: intl.formatMessage(messages['header.links.groupConfigurations']),
},
{
href: `${studioBaseUrl}/settings/advanced/${courseId}`,
title: intl.formatMessage(messages['header.links.advancedSettings']),
},
...(canAccessAdvancedSettings === true
? [{
href: `${studioBaseUrl}/settings/advanced/${courseId}`,
title: intl.formatMessage(messages['header.links.advancedSettings']),
}] : []
),
];
if (getConfig().ENABLE_CERTIFICATE_PAGE === 'true') {
items.push({
Expand All @@ -63,23 +75,29 @@ export const getSettingMenuItems = ({ studioBaseUrl, courseId, intl }) => {
return items;
};

export const getToolsMenuItems = ({ studioBaseUrl, courseId, intl }) => ([
{
href: `${studioBaseUrl}/import/${courseId}`,
title: intl.formatMessage(messages['header.links.import']),
},
{
href: `${studioBaseUrl}/export/${courseId}`,
title: intl.formatMessage(messages['header.links.exportCourse']),
},
...(getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true'
? [{
href: '#export-tags',
title: intl.formatMessage(messages['header.links.exportTags']),
}] : []
),
{
href: `${studioBaseUrl}/checklists/${courseId}`,
title: intl.formatMessage(messages['header.links.checklists']),
},
]);
export const useToolsMenuItems = courseId => {
const intl = useIntl();
const studioBaseUrl = getConfig().STUDIO_BASE_URL;

const items = [
{
href: `${studioBaseUrl}/import/${courseId}`,
title: intl.formatMessage(messages['header.links.import']),
},
{
href: `${studioBaseUrl}/export/${courseId}`,
title: intl.formatMessage(messages['header.links.exportCourse']),
},
...(getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true'
? [{
href: '#export-tags',
title: intl.formatMessage(messages['header.links.exportTags']),
}] : []
),
{
href: `${studioBaseUrl}/checklists/${courseId}`,
title: intl.formatMessage(messages['header.links.checklists']),
},
];
return items;
};
43 changes: 30 additions & 13 deletions src/header/utils.test.js → src/header/hooks.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { useSelector } from 'react-redux';
import { getConfig, setConfig } from '@edx/frontend-platform';
import { getContentMenuItems, getToolsMenuItems, getSettingMenuItems } from './utils';
import { renderHook } from '@testing-library/react-hooks';
import { useContentMenuItems, useToolsMenuItems, useSettingMenuItems } from './hooks';

const props = {
studioBaseUrl: 'UrLSTuiO',
courseId: '123',
intl: {
jest.mock('@edx/frontend-platform/i18n', () => ({
...jest.requireActual('@edx/frontend-platform/i18n'),
useIntl: () => ({
formatMessage: jest.fn(message => message.defaultMessage),
},
};
}),
}));

jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useSelector: jest.fn(),
}));

describe('header utils', () => {
describe('getContentMenuItems', () => {
Expand All @@ -16,36 +22,47 @@ describe('header utils', () => {
...getConfig(),
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN: 'true',
});
const actualItems = getContentMenuItems(props);
const actualItems = renderHook(() => useContentMenuItems('course-123')).result.current;
expect(actualItems).toHaveLength(5);
});
it('should not include Video Uploads option', () => {
setConfig({
...getConfig(),
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN: 'false',
});
const actualItems = getContentMenuItems(props);
const actualItems = renderHook(() => useContentMenuItems('course-123')).result.current;
expect(actualItems).toHaveLength(4);
});
});

describe('getSettingsMenuitems', () => {
useSelector.mockReturnValue({ canAccessAdvancedSettings: true });

it('should include certificates option', () => {
setConfig({
...getConfig(),
ENABLE_CERTIFICATE_PAGE: 'true',
});
const actualItems = getSettingMenuItems(props);
const actualItems = renderHook(() => useSettingMenuItems('course-123')).result.current;
expect(actualItems).toHaveLength(6);
});
it('should not include certificates option', () => {
setConfig({
...getConfig(),
ENABLE_CERTIFICATE_PAGE: 'false',
});
const actualItems = getSettingMenuItems(props);
const actualItems = renderHook(() => useSettingMenuItems('course-123')).result.current;
expect(actualItems).toHaveLength(5);
});
it('should include advanced settings option', () => {
const actualItemsTitle = renderHook(() => useSettingMenuItems('course-123')).result.current.map((item) => item.title);
expect(actualItemsTitle).toContain('Advanced Settings');
});
it('should not include advanced settings option', () => {
useSelector.mockReturnValue({ canAccessAdvancedSettings: false });
const actualItemsTitle = renderHook(() => useSettingMenuItems('course-123')).result.current.map((item) => item.title);
expect(actualItemsTitle).not.toContain('Advanced Settings');
});
});

describe('getToolsMenuItems', () => {
Expand All @@ -54,7 +71,7 @@ describe('header utils', () => {
...getConfig(),
ENABLE_TAGGING_TAXONOMY_PAGES: 'true',
});
const actualItemsTitle = getToolsMenuItems(props).map((item) => item.title);
const actualItemsTitle = renderHook(() => useToolsMenuItems('course-123')).result.current.map((item) => item.title);
expect(actualItemsTitle).toEqual([
'Import',
'Export Course',
Expand All @@ -67,7 +84,7 @@ describe('header utils', () => {
...getConfig(),
ENABLE_TAGGING_TAXONOMY_PAGES: 'false',
});
const actualItemsTitle = getToolsMenuItems(props).map((item) => item.title);
const actualItemsTitle = renderHook(() => useToolsMenuItems('course-123')).result.current.map((item) => item.title);
expect(actualItemsTitle).toEqual([
'Import',
'Export Course',
Expand Down

0 comments on commit 45c68d6

Please sign in to comment.