Skip to content

Commit

Permalink
Hide "Advanced Settings" settings item [BB-9081] (openedx#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

(cherry picked from commit 45c68d6)
  • Loading branch information
0x29a committed Sep 13, 2024
1 parent 33b5897 commit 147effd
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 143 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 Down Expand Up @@ -45,6 +46,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.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { StudioHeader } from '@edx/frontend-component-header';
import { useToggle } from '@openedx/paragon';

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

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

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

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

const outlineLink = `${studioBaseUrl}/course/${courseId}`;

return (
Expand Down
101 changes: 101 additions & 0 deletions src/header/hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
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 useContentMenuItems = courseId => {
const intl = useIntl();
const studioBaseUrl = getConfig().STUDIO_BASE_URL;

const items = [
{
href: `${studioBaseUrl}/course/${courseId}`,
title: intl.formatMessage(messages['header.links.outline']),
},
{
href: `${studioBaseUrl}/course_info/${courseId}`,
title: intl.formatMessage(messages['header.links.updates']),
},
{
href: getPagePath(courseId, 'true', 'tabs'),
title: intl.formatMessage(messages['header.links.pages']),
},
{
href: `${studioBaseUrl}/assets/${courseId}`,
title: intl.formatMessage(messages['header.links.filesAndUploads']),
},
];
if (getConfig().ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN === 'true') {
items.push({
href: `${studioBaseUrl}/videos/${courseId}`,
title: intl.formatMessage(messages['header.links.videoUploads']),
});
}

return items;
};

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

const items = [
{
href: `${studioBaseUrl}/settings/details/${courseId}`,
title: intl.formatMessage(messages['header.links.scheduleAndDetails']),
},
{
href: `${studioBaseUrl}/settings/grading/${courseId}`,
title: intl.formatMessage(messages['header.links.grading']),
},
{
href: `${studioBaseUrl}/course_team/${courseId}`,
title: intl.formatMessage(messages['header.links.courseTeam']),
},
{
href: `${studioBaseUrl}/group_configurations/${courseId}`,
title: intl.formatMessage(messages['header.links.groupConfigurations']),
},
...(canAccessAdvancedSettings === true
? [{
href: `${studioBaseUrl}/settings/advanced/${courseId}`,
title: intl.formatMessage(messages['header.links.advancedSettings']),
}] : []
),
{
href: `${studioBaseUrl}/certificates/${courseId}`,
title: intl.formatMessage(messages['header.links.certificates']),
},
];
return items;
};

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;
};
79 changes: 79 additions & 0 deletions src/header/hooks.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useSelector } from 'react-redux';
import { getConfig, setConfig } from '@edx/frontend-platform';
import { renderHook } from '@testing-library/react-hooks';
import { useContentMenuItems, useToolsMenuItems, useSettingMenuItems } from './hooks';

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', () => {
it('should include Video Uploads option', () => {
setConfig({
...getConfig(),
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN: 'true',
});
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 = renderHook(() => useContentMenuItems('course-123')).result.current;
expect(actualItems).toHaveLength(4);
});
});

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

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', () => {
it('should include export tags option', () => {
setConfig({
...getConfig(),
ENABLE_TAGGING_TAXONOMY_PAGES: 'true',
});
const actualItemsTitle = renderHook(() => useToolsMenuItems('course-123')).result.current.map((item) => item.title);
expect(actualItemsTitle).toEqual([
'Import',
'Export Course',
'Export Tags',
'Checklists',
]);
});
it('should not include export tags option', () => {
setConfig({
...getConfig(),
ENABLE_TAGGING_TAXONOMY_PAGES: 'false',
});
const actualItemsTitle = renderHook(() => useToolsMenuItems('course-123')).result.current.map((item) => item.title);
expect(actualItemsTitle).toEqual([
'Import',
'Export Course',
'Checklists',
]);
});
});
});
80 changes: 0 additions & 80 deletions src/header/utils.js

This file was deleted.

59 changes: 0 additions & 59 deletions src/header/utils.test.js

This file was deleted.

0 comments on commit 147effd

Please sign in to comment.