Skip to content

Commit 91b6925

Browse files
committed
feat: add program dashboard directory (#1)
1 parent f903392 commit 91b6925

6 files changed

Lines changed: 81 additions & 46 deletions

File tree

src/App.jsx

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { logError } from '@edx/frontend-platform/logging';
66
import { initializeHotjar } from '@edx/frontend-enterprise-hotjar';
77

88
import { ErrorPage, AppContext } from '@edx/frontend-platform/react';
9-
import { FooterSlot } from '@edx/frontend-component-footer';
109
import { Alert } from '@openedx/paragon';
1110

1211
import { RequestKeys } from 'data/constants/requests';
@@ -22,9 +21,6 @@ import track from 'tracking';
2221

2322
import fakeData from 'data/services/lms/fakeData/courses';
2423

25-
import AppWrapper from 'containers/AppWrapper';
26-
import LearnerDashboardHeader from 'containers/LearnerDashboardHeader';
27-
2824
import { getConfig } from '@edx/frontend-platform';
2925
import messages from './messages';
3026
import './App.scss';
@@ -77,22 +73,16 @@ export const App = () => {
7773
<title>{formatMessage(messages.pageTitle)}</title>
7874
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
7975
</Helmet>
80-
<div>
81-
<AppWrapper>
82-
<LearnerDashboardHeader />
83-
<main id="main">
84-
{hasNetworkFailure
85-
? (
86-
<Alert variant="danger">
87-
<ErrorPage message={formatMessage(messages.errorMessage, { supportEmail })} />
88-
</Alert>
89-
) : (
90-
<Dashboard />
91-
)}
92-
</main>
93-
</AppWrapper>
94-
<FooterSlot />
95-
</div>
76+
<main id="main">
77+
{hasNetworkFailure
78+
? (
79+
<Alert variant="danger">
80+
<ErrorPage message={formatMessage(messages.errorMessage, { supportEmail })} />
81+
</Alert>
82+
) : (
83+
<Dashboard />
84+
)}
85+
</main>
9686
</>
9787
);
9888
};

src/App.test.jsx

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@ import { reduxHooks } from 'hooks';
88
import { App } from './App';
99
import messages from './messages';
1010

11-
jest.mock('@edx/frontend-component-footer', () => ({
12-
FooterSlot: jest.fn(() => <div>FooterSlot</div>),
13-
}));
1411
jest.mock('containers/Dashboard', () => jest.fn(() => <div>Dashboard</div>));
15-
jest.mock('containers/LearnerDashboardHeader', () => jest.fn(() => <div>LearnerDashboardHeader</div>));
16-
jest.mock('containers/AppWrapper', () => jest.fn(({ children }) => <div className="AppWrapper">{children}</div>));
1712
jest.mock('data/redux', () => ({
1813
selectors: 'redux.selectors',
1914
actions: 'redux.actions',
@@ -49,19 +44,6 @@ describe('App router component', () => {
4944
it('displays title in helmet component', async () => {
5045
await waitFor(() => expect(document.title).toEqual(messages.pageTitle.defaultMessage));
5146
});
52-
it('displays learner dashboard header', () => {
53-
const learnerDashboardHeader = screen.getByText('LearnerDashboardHeader');
54-
expect(learnerDashboardHeader).toBeInTheDocument();
55-
});
56-
it('wraps the header and main components in an AppWrapper widget container', () => {
57-
const appWrapper = screen.getByText('LearnerDashboardHeader').parentElement;
58-
expect(appWrapper).toHaveClass('AppWrapper');
59-
expect(appWrapper.children[1].id).toEqual('main');
60-
});
61-
it('displays footer slot', () => {
62-
const footerSlot = screen.getByText('FooterSlot');
63-
expect(footerSlot).toBeInTheDocument();
64-
});
6547
};
6648
describe('no network failure', () => {
6749
beforeEach(() => {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
2+
import { getConfig } from '@edx/frontend-platform';
3+
4+
export async function getProgramsListData() {
5+
const url = `${getConfig().LMS_BASE_URL}/api/dashboard/v0/programs/`;
6+
const response = await getAuthenticatedHttpClient().get(url);
7+
return response;
8+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { useEffect, useState } from 'react';
2+
import { Helmet } from 'react-helmet';
3+
import { logError } from '@edx/frontend-platform/logging';
4+
import { getProgramsListData } from './api';
5+
6+
interface ProgramsData {
7+
uuid: String,
8+
title: String,
9+
type: String,
10+
banner_image: object,
11+
authorizing_organizations: object[],
12+
progress: object,
13+
}
14+
15+
const ProgramDashboard = () => {
16+
const [programsData, setProgramsData] = useState<ProgramsData[]>([]);
17+
18+
useEffect(() => {
19+
getProgramsListData()
20+
.then(responseData => setProgramsData(responseData.data))
21+
.catch(err => logError(err));
22+
}, []);
23+
24+
return (
25+
<>
26+
<Helmet>
27+
<title>Program Dashboard</title>
28+
</Helmet>
29+
<div>
30+
{programsData.map(item => (
31+
<div>
32+
{item.title}
33+
</div>
34+
))}
35+
</div>
36+
</>
37+
);
38+
};
39+
40+
export default ProgramDashboard;

src/index.jsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,35 @@ import {
1919
APP_INIT_ERROR,
2020
initialize,
2121
subscribe,
22+
getConfig,
2223
mergeConfig,
2324
} from '@edx/frontend-platform';
25+
import { FooterSlot } from '@edx/frontend-component-footer';
26+
27+
import LearnerDashboardHeader from 'containers/LearnerDashboardHeader';
28+
import ProgramDashboard from './containers/ProgramDashboard';
2429

2530
import { configuration } from './config';
2631

2732
import messages from './i18n';
2833

2934
import App from './App';
30-
import NoticesWrapper from './components/NoticesWrapper';
3135

3236
subscribe(APP_READY, () => {
3337
const root = createRoot(document.getElementById('root'));
3438

3539
root.render(
3640
<StrictMode>
3741
<AppProvider store={store}>
38-
<NoticesWrapper>
39-
<Routes>
40-
<Route path="/" element={<PageWrap><App /></PageWrap>} />
41-
<Route path="*" element={<Navigate to="/" replace />} />
42-
</Routes>
43-
</NoticesWrapper>
42+
<LearnerDashboardHeader />
43+
<Routes>
44+
<Route path="/" element={<PageWrap><App /></PageWrap>} />
45+
{getConfig().ENABLE_PROGRAM_DASHBOARD && (
46+
<Route path="/programs" element={<PageWrap><ProgramDashboard /></PageWrap>} />
47+
)}
48+
<Route path="*" element={<Navigate to="/" replace />} />
49+
</Routes>
50+
<FooterSlot />
4451
</AppProvider>
4552
</StrictMode>,
4653
);

src/index.test.jsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ jest.mock('react-dom/client', () => {
2525
});
2626

2727
jest.mock('@edx/frontend-platform', () => ({
28+
getConfig: jest.fn(() => ({
29+
ENABLE_PROGRAM_DASHBOARD: true,
30+
})),
2831
mergeConfig: jest.fn(),
2932
ensureConfig: jest.fn(),
3033
APP_READY: 'app-is-ready-key',
@@ -35,7 +38,12 @@ jest.mock('@edx/frontend-platform', () => ({
3538

3639
jest.mock('data/store', () => ({ redux: 'store' }));
3740
jest.mock('./App', () => 'App');
38-
jest.mock('components/NoticesWrapper', () => 'NoticesWrapper');
41+
jest.mock('@edx/frontend-component-footer', () => ({
42+
FooterSlot: jest.fn(() => <div>FooterSlot</div>),
43+
}));
44+
45+
jest.mock('containers/LearnerDashboardHeader', () => 'LearnerDashboardHeader');
46+
jest.mock('containers/ProgramDashboard', () => 'ProgramDashboard');
3947

4048
describe('app registry', () => {
4149
let getElement;

0 commit comments

Comments
 (0)