Compare commits

...

4 Commits

Author SHA1 Message Date
Peter Kulko
49d64ff5c6 fix: fixed module button href (#508) 2024-12-12 10:30:30 +02:00
Peter Kulko
fe658c1796 fix: added LMS_BASE_URL for brand logo (#498) 2024-11-20 13:19:08 +02:00
Max Sokolski
82dbc27aba fix: removed Program link from the header (#497) 2024-11-18 16:59:27 +02:00
Peter Kulko
25d3f831a2 fix: removed program tab in the header 2024-11-14 23:35:40 +02:00
12 changed files with 180 additions and 24 deletions

View File

@@ -1,5 +1,3 @@
import React from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { reduxHooks } from 'hooks';
@@ -12,7 +10,7 @@ export const BrandLogo = () => {
const dashboard = reduxHooks.useEnterpriseDashboardData();
return (
<a href={dashboard?.url || '/'} className="mx-auto">
<a href={dashboard?.url || getConfig().LMS_BASE_URL} className="mx-auto">
<img
className="logo py-3"
src={getConfig().LOGO_URL}

View File

@@ -1,6 +1,7 @@
import { shallow } from '@edx/react-unit-test-utils';
import { getConfig } from '@edx/frontend-platform';
import { reduxHooks } from 'hooks';
import BrandLogo from './BrandLogo';
jest.mock('hooks', () => ({
@@ -23,6 +24,6 @@ describe('BrandLogo', () => {
reduxHooks.useEnterpriseDashboardData.mockReturnValueOnce(null);
const wrapper = shallow(<BrandLogo />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType('a')[0].props.href).toEqual('/');
expect(wrapper.instance.findByType('a')[0].props.href).toEqual(getConfig().LMS_BASE_URL);
});
});

View File

@@ -7,7 +7,7 @@ import { AppContext } from '@edx/frontend-platform/react';
import { Button, Badge } from '@openedx/paragon';
import urls from 'data/services/lms/urls';
import { reduxHooks } from 'hooks';
import { reduxHooks, apiHooks } from 'hooks';
import { findCoursesNavDropdownClicked } from '../hooks';
import messages from '../messages';
@@ -16,6 +16,8 @@ export const CollapseMenuBody = ({ isOpen }) => {
const { formatMessage } = useIntl();
const { authenticatedUser } = React.useContext(AppContext);
const { enabled: programsEnabled } = apiHooks.useProgramsConfig();
const dashboard = reduxHooks.useEnterpriseDashboardData();
const { courseSearchUrl } = reduxHooks.usePlatformSettingsData();
@@ -29,12 +31,14 @@ export const CollapseMenuBody = ({ isOpen }) => {
return (
<div className="d-flex flex-column shadow-sm nav-small-menu">
<Button as="a" href="/" variant="inverse-primary">
<Button as="a" href={`${getConfig().LMS_BASE_URL}/dashboard/`} variant="inverse-primary">
{formatMessage(messages.course)}
</Button>
<Button as="a" href={urls.programsUrl()} variant="inverse-primary">
{formatMessage(messages.program)}
</Button>
{programsEnabled && (
<Button as="a" href={urls.programsUrl()} variant="inverse-primary">
{formatMessage(messages.program)}
</Button>
)}
<Button
as="a"
href={urls.baseAppUrl(courseSearchUrl)}

View File

@@ -1,6 +1,7 @@
import { shallow } from '@edx/react-unit-test-utils';
import { AppContext } from '@edx/frontend-platform/react';
import { apiHooks } from 'hooks';
import CollapseMenuBody from './CollapseMenuBody';
jest.mock('@edx/frontend-platform/react', () => ({
@@ -20,6 +21,11 @@ jest.mock('hooks', () => ({
courseSearchUrl: '/courseSearchUrl',
}),
},
apiHooks: {
useProgramsConfig: () => ({
enabled: true,
}),
},
}));
jest.mock('../hooks', () => ({
@@ -45,4 +51,10 @@ describe('CollapseMenuBody', () => {
expect(wrapper.snapshot).toMatchSnapshot();
AppContext.authenticatedUser = authenticatedUser;
});
test('render with disabled programs', () => {
apiHooks.useProgramsConfig = () => ({ enabled: false });
const wrapper = shallow(<CollapseMenuBody isOpen />);
expect(wrapper.snapshot).toMatchSnapshot();
});
});

View File

@@ -6,7 +6,7 @@ exports[`CollapseMenuBody render 1`] = `
>
<Button
as="a"
href="/"
href="http://localhost:18000/dashboard/"
variant="inverse-primary"
>
Courses
@@ -74,7 +74,7 @@ exports[`CollapseMenuBody render unauthenticated 1`] = `
>
<Button
as="a"
href="/"
href="http://localhost:18000/dashboard/"
variant="inverse-primary"
>
Courses
@@ -103,3 +103,62 @@ exports[`CollapseMenuBody render unauthenticated 1`] = `
</Button>
</div>
`;
exports[`CollapseMenuBody render with disabled programs 1`] = `
<div
className="d-flex flex-column shadow-sm nav-small-menu"
>
<Button
as="a"
href="http://localhost:18000/dashboard/"
variant="inverse-primary"
>
Courses
</Button>
<Button
as="a"
href="http://localhost:18000/courseSearchUrl"
onClick={[MockFunction findCoursesNavDropdownClicked("http://localhost:18000/courseSearchUrl")]}
variant="inverse-primary"
>
Discover New
</Button>
<Button
as="a"
href="http://localhost:18000/support"
variant="inverse-primary"
>
Help
</Button>
<Fragment>
<Button
as="a"
href="url"
variant="inverse-primary"
>
Dashboard
</Button>
<Button
as="a"
href="http://localhost:18000/u/username"
variant="inverse-primary"
>
Profile
</Button>
<Button
as="a"
href="http://localhost:18000/account/settings"
variant="inverse-primary"
>
Account
</Button>
<Button
as="a"
href="http://localhost:18000/logout"
variant="inverse-primary"
>
Sign Out
</Button>
</Fragment>
</div>
`;

View File

@@ -11,7 +11,7 @@ exports[`ExpandedHeader render 1`] = `
<Button
as="a"
className="p-4 course-link"
href="/"
href="http://localhost:18000/dashboard/"
variant="inverse-primary"
>
Courses
@@ -50,3 +50,44 @@ exports[`ExpandedHeader render 1`] = `
`;
exports[`ExpandedHeader render empty if collapsed 1`] = `null`;
exports[`ExpandedHeader render with disabled programs 1`] = `
<header
className="d-flex shadow-sm align-items-center learner-variant-header pl-4"
>
<div
className="flex-grow-1 d-flex align-items-center"
>
<BrandLogo />
<Button
as="a"
className="p-4 course-link"
href="http://localhost:18000/dashboard/"
variant="inverse-primary"
>
Courses
</Button>
<Button
as="a"
className="p-4"
href="http://localhost:18000/courseSearchUrl"
onClick={[MockFunction findCoursesNavClicked("http://localhost:18000/courseSearchUrl")]}
variant="inverse-primary"
>
Discover New
</Button>
<span
className="flex-grow-1"
/>
<Button
as="a"
className="p-4"
href="http://localhost:18000/support"
variant="inverse-primary"
>
Help
</Button>
</div>
<AuthenticatedUserDropdown />
</header>
`;

View File

@@ -5,7 +5,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import { Button } from '@openedx/paragon';
import urls from 'data/services/lms/urls';
import { reduxHooks } from 'hooks';
import { reduxHooks, apiHooks } from 'hooks';
import AuthenticatedUserDropdown from './AuthenticatedUserDropdown';
import { useIsCollapsed, findCoursesNavClicked } from '../hooks';
@@ -17,6 +17,8 @@ export const ExpandedHeader = () => {
const { courseSearchUrl } = reduxHooks.usePlatformSettingsData();
const isCollapsed = useIsCollapsed();
const { enabled: programsEnabled } = apiHooks.useProgramsConfig();
const exploreCoursesClick = findCoursesNavClicked(
urls.baseAppUrl(courseSearchUrl),
);
@@ -32,20 +34,22 @@ export const ExpandedHeader = () => {
<Button
as="a"
href="/"
href={`${getConfig().LMS_BASE_URL}/dashboard/`}
variant="inverse-primary"
className="p-4 course-link"
>
{formatMessage(messages.course)}
</Button>
<Button
as="a"
href={urls.programsUrl()}
variant="inverse-primary"
className="p-4"
>
{formatMessage(messages.program)}
</Button>
{programsEnabled && (
<Button
as="a"
href={urls.programsUrl()}
variant="inverse-primary"
className="p-4"
>
{formatMessage(messages.program)}
</Button>
)}
<Button
as="a"
href={urls.baseAppUrl(courseSearchUrl)}

View File

@@ -1,5 +1,6 @@
import { shallow } from '@edx/react-unit-test-utils';
import { apiHooks } from 'hooks';
import ExpandedHeader from '.';
import { useIsCollapsed } from '../hooks';
@@ -15,6 +16,11 @@ jest.mock('hooks', () => ({
courseSearchUrl: '/courseSearchUrl',
}),
},
apiHooks: {
useProgramsConfig: () => ({
enabled: true,
}),
},
}));
jest.mock('../hooks', () => ({
@@ -38,4 +44,10 @@ describe('ExpandedHeader', () => {
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.isEmptyRender()).toBe(true);
});
test('render with disabled programs', () => {
apiHooks.useProgramsConfig = () => ({ enabled: false });
const wrapper = shallow(<ExpandedHeader />);
expect(wrapper.snapshot).toMatchSnapshot();
});
});

View File

@@ -16,7 +16,7 @@ exports[`BrandLogo dashboard defined 1`] = `
exports[`BrandLogo dashboard undefined 1`] = `
<a
className="mx-auto"
href="/"
href="http://localhost:18000"
>
<img
alt="edX, Inc. Dashboard"

View File

@@ -20,6 +20,8 @@ export const initializeList = ({ user } = {}) => get(
stringifyUrl(urls.getInitApiUrl(), { [apiKeys.user]: user }),
);
export const getProgramsConfig = () => get(urls.programsConfigUrl());
export const updateEntitlementEnrollment = ({ uuid, courseId }) => post(
urls.entitlementEnrollment(uuid),
{ [apiKeys.courseRunId]: courseId },
@@ -75,6 +77,7 @@ export default {
initializeList,
unenrollFromCourse,
updateEmailSettings,
getProgramsConfig,
updateEntitlementEnrollment,
deleteEntitlementEnrollment,
logEvent,

View File

@@ -22,6 +22,7 @@ export const baseAppUrl = (url) => updateUrl(getBaseUrl(), url);
export const learningMfeUrl = (url) => updateUrl(getConfig().LEARNING_BASE_URL, url);
// static view url
const programsConfigUrl = () => baseAppUrl('/config/programs');
const programsUrl = () => baseAppUrl('/dashboard/programs');
export const creditPurchaseUrl = (courseId) => `${getEcommerceUrl()}/credit/checkout/${courseId}/`;
@@ -38,5 +39,6 @@ export default StrictDict({
getInitApiUrl,
learningMfeUrl,
programsUrl,
programsConfigUrl,
updateEmailSettings,
});

View File

@@ -1,6 +1,7 @@
import React from 'react';
import { AppContext } from '@edx/frontend-platform/react';
import { logError } from '@edx/frontend-platform/logging';
import { RequestKeys } from 'data/constants/requests';
import { post } from 'data/services/lms/utils';
@@ -31,6 +32,25 @@ export const useInitializeApp = () => {
});
};
export const useProgramsConfig = () => {
const [config, setConfig] = React.useState({});
const fetchProgramsConfig = React.useCallback(async () => {
try {
const { data } = await api.getProgramsConfig();
setConfig(data);
} catch (error) {
logError(`Error accessing programs configuration: ${error.message}`);
}
}, []);
React.useEffect(() => {
fetchProgramsConfig();
}, [fetchProgramsConfig]);
return config;
};
export const useNewEntitlementEnrollment = (cardId) => {
const { uuid } = reduxHooks.useCardEntitlementData(cardId);
const onSuccess = module.useInitializeApp();