Skip to content

Commit e6a265d

Browse files
MaxFrank13renovate[bot]brian-smith-tcriljacobo-dominguez-wgumarslanabdulrauf
authored
feat!: sync react query conversion (#11)
* fix(deps): remove filesize dependency (openedx#767) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @openedx/paragon to v23.18.2 (openedx#771) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix: remove unused universal-cookie dep (openedx#794) * fix: update react-share to v5 (openedx#795) * fix(deps): regenerate `package-lock.json` (openedx#788) * fix(deps): update dependency core-js to v3.48.0 (openedx#799) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @edx/frontend-platform to v8.5.5 (openedx#798) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(docs): use correct image for custom course banner (openedx#796) * feat!: React query and react context conversion (openedx#786) Migrate from Redux to React Query and React Context. This modernizes state management while maintaining all existing functionality. All the redux code and files were removed, including all redux and related packages. * feat: showing course unenroll survey is configurable now (openedx#738) * chore(deps): update dependency @tanstack/react-query to v5.90.21 (openedx#803) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency react-share to v5.3.0 (openedx#807) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @tanstack/react-query to v5.95.0 (openedx#808) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency core-js to v3.49.0 (openedx#809) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: sync fork from upstream master (#4) * fix: Run `npm audit fix` to update dependencies. * chore(deps): update dependency @openedx/paragon to v23.14.9 (openedx#735) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @reduxjs/toolkit to v2.9.1 (openedx#736) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): bump actions/setup-node from 5 to 6 (openedx#737) --------- Co-authored-by: Feanil Patel <feanil@axim.org> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: baseAppUrl add ins * fix: package-lock * fix: test * fix: lint --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Brian Smith <112954497+brian-smith-tcril@users.noreply.github.com> Co-authored-by: Jacobo Dominguez <jacobo.dominguez@wgu.edu> Co-authored-by: Muhammad Arslan <m.arslanabdulrauf@gmail.com> Co-authored-by: Feanil Patel <feanil@axim.org> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1 parent 63568ee commit e6a265d

187 files changed

Lines changed: 11236 additions & 7468 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
NODE_ENV='production'
2+
APP_ID='learner-dashboard'
23
NODE_PATH=./src
34
BASE_URL=''
45
LMS_BASE_URL=''
@@ -41,5 +42,6 @@ CAREER_LINK_URL=''
4142
ENABLE_EDX_PERSONAL_DASHBOARD=false
4243
ENABLE_PROGRAMS=false
4344
NON_BROWSABLE_COURSES=false
45+
SHOW_UNENROLL_SURVEY=true
4446
# Fallback in local style files
4547
PARAGON_THEME_URLS={}

.env.development

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
NODE_ENV='development'
2+
APP_ID='learner-dashboard'
23
PORT=1996
34
BASE_URL='localhost:1996'
45
LMS_BASE_URL='http://localhost:18000'
@@ -47,5 +48,6 @@ CAREER_LINK_URL=''
4748
ENABLE_EDX_PERSONAL_DASHBOARD=false
4849
ENABLE_PROGRAMS=false
4950
NON_BROWSABLE_COURSES=false
51+
SHOW_UNENROLL_SURVEY=true
5052
# Fallback in local style files
5153
PARAGON_THEME_URLS={}

.env.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
NODE_ENV='test'
2+
APP_ID='learner-dashboard'
23
PORT=1996
34
BASE_URL='localhost:1996'
45
LMS_BASE_URL='http://localhost:18000'
@@ -46,4 +47,5 @@ CAREER_LINK_URL=''
4647
ENABLE_EDX_PERSONAL_DASHBOARD=true
4748
ENABLE_PROGRAMS=false
4849
NON_BROWSABLE_COURSES=false
50+
SHOW_UNENROLL_SURVEY=true
4951
PARAGON_THEME_URLS={}

example.env.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ frontend-platform's getConfig loads configuration in the following sequence:
1919

2020
module.exports = {
2121
NODE_ENV: 'development',
22+
APP_ID: 'learner-dashboard',
2223
NODE_PATH: './src',
2324
PORT: 1996,
2425
BASE_URL: 'localhost:1996',
@@ -69,4 +70,5 @@ module.exports = {
6970
ACCOUNT_PROFILE_URL: 'http://localhost:1995',
7071
CAREER_LINK_URL: '',
7172
EXPERIMENT_08_23_VAN_PAINTED_DOOR: true,
73+
SHOW_UNENROLL_SURVEY: true
7274
};

package-lock.json

Lines changed: 2073 additions & 1709 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,9 @@
4141
"@fortawesome/react-fontawesome": "^0.2.0",
4242
"@openedx/frontend-plugin-framework": "^1.7.0",
4343
"@openedx/paragon": "^23.4.5",
44-
"@redux-devtools/extension": "3.3.0",
45-
"@reduxjs/toolkit": "^2.0.0",
44+
"@tanstack/react-query": "^5.90.16",
4645
"classnames": "^2.3.1",
47-
"core-js": "3.47.0",
46+
"core-js": "3.49.0",
4847
"font-awesome": "4.7.0",
4948
"history": "5.3.0",
5049
"lodash": "^4.17.21",
@@ -54,14 +53,9 @@
5453
"react-dom": "^18.3.1",
5554
"react-helmet": "^6.1.0",
5655
"react-intl": "6.8.9",
57-
"react-redux": "^7.2.4",
5856
"react-router-dom": "6.30.3",
59-
"react-share": "^4.4.0",
60-
"redux": "4.2.1",
61-
"redux-logger": "3.0.6",
62-
"redux-thunk": "2.4.2",
57+
"react-share": "^5.2.2",
6358
"regenerator-runtime": "^0.14.0",
64-
"reselect": "^4.0.0",
6559
"util": "^0.12.4"
6660
},
6761
"devDependencies": {
@@ -78,7 +72,6 @@
7872
"jest-expect-message": "^1.1.3",
7973
"jest-when": "^3.6.0",
8074
"react-dev-utils": "^12.0.0",
81-
"react-test-renderer": "^18.3.1",
82-
"redux-mock-store": "^1.5.4"
75+
"react-test-renderer": "^18.3.1"
8376
}
8477
}

src/App.jsx

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,60 +5,30 @@ import { useIntl } from '@edx/frontend-platform/i18n';
55
import { logError } from '@edx/frontend-platform/logging';
66
import { initializeHotjar } from '@edx/frontend-enterprise-hotjar';
77

8-
import { ErrorPage, AppContext } from '@edx/frontend-platform/react';
8+
import { ErrorPage } from '@edx/frontend-platform/react';
99
import { FooterSlot } from '@edx/frontend-component-footer';
1010
import { Alert } from '@openedx/paragon';
1111

12-
import { RequestKeys } from 'data/constants/requests';
13-
import store from 'data/store';
14-
import {
15-
selectors,
16-
actions,
17-
} from 'data/redux';
18-
import { reduxHooks } from 'hooks';
1912
import Dashboard from 'containers/Dashboard';
2013

21-
import track from 'tracking';
22-
23-
import fakeData from 'data/services/lms/fakeData/courses';
24-
2514
import AppWrapper from 'containers/AppWrapper';
2615
import LearnerDashboardHeader from 'containers/LearnerDashboardHeader';
2716

2817
import { getConfig } from '@edx/frontend-platform';
18+
import { useInitializeLearnerHome } from 'data/hooks';
19+
import { useMasquerade } from 'data/context';
2920
import messages from './messages';
3021
import './App.scss';
3122

3223
export const App = () => {
33-
const { authenticatedUser } = React.useContext(AppContext);
3424
const { formatMessage } = useIntl();
35-
const isFailed = {
36-
initialize: reduxHooks.useRequestIsFailed(RequestKeys.initialize),
37-
refreshList: reduxHooks.useRequestIsFailed(RequestKeys.refreshList),
38-
};
39-
const hasNetworkFailure = isFailed.initialize || isFailed.refreshList;
40-
const { supportEmail } = reduxHooks.usePlatformSettingsData();
41-
const loadData = reduxHooks.useLoadData();
25+
const { masqueradeUser } = useMasquerade();
26+
const { data, isError } = useInitializeLearnerHome();
27+
const hasNetworkFailure = !masqueradeUser && isError;
28+
const supportEmail = data?.platformSettings?.supportEmail || undefined;
4229

30+
/* istanbul ignore next */
4331
React.useEffect(() => {
44-
if (authenticatedUser?.administrator || getConfig().NODE_ENV === 'development') {
45-
window.loadEmptyData = () => {
46-
loadData({ ...fakeData.globalData, courses: [] });
47-
};
48-
window.loadMockData = () => {
49-
loadData({
50-
...fakeData.globalData,
51-
courses: [
52-
...fakeData.courseRunData,
53-
...fakeData.entitlementData,
54-
],
55-
});
56-
};
57-
window.store = store;
58-
window.selectors = selectors;
59-
window.actions = actions;
60-
window.track = track;
61-
}
6232
if (getConfig().HOTJAR_APP_ID) {
6333
try {
6434
initializeHotjar({
@@ -70,7 +40,7 @@ export const App = () => {
7040
logError(error);
7141
}
7242
}
73-
}, [authenticatedUser, loadData]);
43+
}, []);
7444
return (
7545
<>
7646
<Helmet>

src/App.test.jsx

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,24 @@ import { render, screen, waitFor } from '@testing-library/react';
33
import { IntlProvider } from '@edx/frontend-platform/i18n';
44
import { getConfig } from '@edx/frontend-platform';
55

6-
import { RequestKeys } from 'data/constants/requests';
7-
import { reduxHooks } from 'hooks';
6+
import { useInitializeLearnerHome } from 'data/hooks';
87
import { App } from './App';
98
import messages from './messages';
109

10+
jest.mock('data/hooks', () => ({
11+
useInitializeLearnerHome: jest.fn(),
12+
}));
13+
14+
jest.mock('data/context', () => ({
15+
useMasquerade: jest.fn(() => ({ masqueradeUser: null })),
16+
}));
17+
1118
jest.mock('@edx/frontend-component-footer', () => ({
1219
FooterSlot: jest.fn(() => <div>FooterSlot</div>),
1320
}));
1421
jest.mock('containers/Dashboard', () => jest.fn(() => <div>Dashboard</div>));
1522
jest.mock('containers/LearnerDashboardHeader', () => jest.fn(() => <div>LearnerDashboardHeader</div>));
1623
jest.mock('containers/AppWrapper', () => jest.fn(({ children }) => <div className="AppWrapper">{children}</div>));
17-
jest.mock('data/redux', () => ({
18-
selectors: 'redux.selectors',
19-
actions: 'redux.actions',
20-
thunkActions: 'redux.thunkActions',
21-
}));
22-
jest.mock('hooks', () => ({
23-
reduxHooks: {
24-
useRequestIsFailed: jest.fn(),
25-
usePlatformSettingsData: jest.fn(),
26-
useLoadData: jest.fn(),
27-
},
28-
}));
29-
jest.mock('data/store', () => 'data/store');
3024

3125
jest.mock('@edx/frontend-platform', () => ({
3226
getConfig: jest.fn(() => ({})),
@@ -37,11 +31,15 @@ jest.mock('@edx/frontend-platform/react', () => ({
3731
ErrorPage: () => 'ErrorPage',
3832
}));
3933

40-
const loadData = jest.fn();
41-
reduxHooks.useLoadData.mockReturnValue(loadData);
42-
4334
const supportEmail = 'test@support.com';
44-
reduxHooks.usePlatformSettingsData.mockReturnValue({ supportEmail });
35+
useInitializeLearnerHome.mockReturnValue({
36+
data: {
37+
platformSettings: {
38+
supportEmail,
39+
},
40+
},
41+
isError: false,
42+
});
4543

4644
describe('App router component', () => {
4745
describe('component', () => {
@@ -66,7 +64,6 @@ describe('App router component', () => {
6664
describe('no network failure', () => {
6765
beforeEach(() => {
6866
jest.clearAllMocks();
69-
reduxHooks.useRequestIsFailed.mockReturnValue(false);
7067
getConfig.mockReturnValue({});
7168
render(<IntlProvider locale="en"><App /></IntlProvider>);
7269
});
@@ -79,7 +76,6 @@ describe('App router component', () => {
7976
describe('no network failure with optimizely url', () => {
8077
beforeEach(() => {
8178
jest.clearAllMocks();
82-
reduxHooks.useRequestIsFailed.mockReturnValue(false);
8379
getConfig.mockReturnValue({ OPTIMIZELY_URL: 'fake.url' });
8480
render(<IntlProvider locale="en"><App /></IntlProvider>);
8581
});
@@ -92,7 +88,6 @@ describe('App router component', () => {
9288
describe('no network failure with optimizely project id', () => {
9389
beforeEach(() => {
9490
jest.clearAllMocks();
95-
reduxHooks.useRequestIsFailed.mockReturnValue(false);
9691
getConfig.mockReturnValue({ OPTIMIZELY_PROJECT_ID: 'fakeId' });
9792
render(<IntlProvider locale="en"><App /></IntlProvider>);
9893
});
@@ -105,7 +100,10 @@ describe('App router component', () => {
105100
describe('initialize failure', () => {
106101
beforeEach(() => {
107102
jest.clearAllMocks();
108-
reduxHooks.useRequestIsFailed.mockImplementation((key) => key === RequestKeys.initialize);
103+
useInitializeLearnerHome.mockReturnValue({
104+
data: null,
105+
isError: true,
106+
});
109107
getConfig.mockReturnValue({});
110108
render(<IntlProvider locale="en" messages={messages}><App /></IntlProvider>);
111109
});
@@ -119,7 +117,6 @@ describe('App router component', () => {
119117
});
120118
describe('refresh failure', () => {
121119
beforeEach(() => {
122-
reduxHooks.useRequestIsFailed.mockImplementation((key) => key === RequestKeys.refreshList);
123120
getConfig.mockReturnValue({});
124121
render(<IntlProvider locale="en"><App /></IntlProvider>);
125122
});

src/config/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const configuration = {
22
// BASE_URL: process.env.BASE_URL,
3+
APP_ID: process.env.APP_ID,
34
LMS_BASE_URL: process.env.LMS_BASE_URL,
45
ECOMMERCE_BASE_URL: process.env.ECOMMERCE_BASE_URL,
56
CREDIT_PURCHASE_URL: process.env.CREDIT_PURCHASE_URL,
@@ -20,6 +21,7 @@ const configuration = {
2021
SEARCH_CATALOG_URL: process.env.SEARCH_CATALOG_URL || null,
2122
ENABLE_PROGRAMS: process.env.ENABLE_PROGRAMS === 'true',
2223
NON_BROWSABLE_COURSES: process.env.NON_BROWSABLE_COURSES === 'true',
24+
SHOW_UNENROLL_SURVEY: process.env.SHOW_UNENROLL_SURVEY === 'true',
2325
};
2426

2527
const features = {};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import AppWrapper from './index';
4+
5+
describe('AppWrapper', () => {
6+
it('should render children without modification', () => {
7+
render(
8+
<AppWrapper>
9+
<div>Test Child</div>
10+
</AppWrapper>,
11+
);
12+
13+
expect(screen.getByText('Test Child')).toBeInTheDocument();
14+
});
15+
});

0 commit comments

Comments
 (0)