Hide "Advanced Settings" settings item [BB-9081] (#1252)
* refactor: convert header utils to hooks * feat: hide advanced settings button if a user doesn't have access
This commit is contained in:
@@ -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';
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
@@ -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 });
|
||||
|
||||
@@ -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}`,
|
||||
@@ -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}`,
|
||||
@@ -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({
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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', () => {
|
||||
@@ -16,7 +22,7 @@ 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', () => {
|
||||
@@ -24,18 +30,20 @@ describe('header utils', () => {
|
||||
...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', () => {
|
||||
@@ -43,9 +51,18 @@ describe('header utils', () => {
|
||||
...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', () => {
|
||||
@@ -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',
|
||||
@@ -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',
|
||||
Reference in New Issue
Block a user