Skip to content

Commit

Permalink
Merge pull request #133 from edx/aakbar/PROD-2395
Browse files Browse the repository at this point in the history
refactor: move api calls in entitlement component
  • Loading branch information
Ali-D-Akbar authored Jul 1, 2021
2 parents 76fc6ec + acaa918 commit 0b9b2eb
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 160 deletions.
1 change: 0 additions & 1 deletion src/users/UserPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ export default function UserPage({ location }) {
/>
<Entitlements
user={data.user.username}
data={data.entitlements}
changeHandler={handleEntitlementsChange}
expanded={showEntitlements}
/>
Expand Down
35 changes: 23 additions & 12 deletions src/users/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,31 @@ import * as AppUrls from './urls';
import { isEmail, sortedCompareDates } from '../../utils';

export async function getEntitlements(username, page = 1) {
const baseURL = AppUrls.getEntitlementUrl();
const queryString = `user=${username}&page=${page}`;
const { data } = await getAuthenticatedHttpClient().get(
`${baseURL}?${queryString}`,
);
if (data.next !== null) {
const nextPageData = await getEntitlements(username, data.current_page + 1);
data.results = data.results.concat(nextPageData.results);
try {
const baseURL = AppUrls.getEntitlementUrl();
const queryString = `user=${username}&page=${page}`;
const { data } = await getAuthenticatedHttpClient().get(
`${baseURL}?${queryString}`,
);
if (data.next !== null) {
const nextPageData = await getEntitlements(username, data.current_page + 1);
data.results = data.results.concat(nextPageData.results);
return data;
}
return data;
} catch (error) {
return {
errors: [
{
code: null,
dismissible: true,
text: JSON.parse(error.customAttributes.httpErrorResponseData),
type: 'danger',
topic: 'entitlements',
},
],
};
}
return data;
}

export async function getEnrollments(username) {
Expand Down Expand Up @@ -221,7 +235,6 @@ export async function getOnboardingStatus(enrollments, username) {
export async function getAllUserData(userIdentifier) {
const errors = [];
let user = null;
let entitlements = [];
let enrollments = [];
let verificationStatus = null;
let ssoRecords = null;
Expand All @@ -236,7 +249,6 @@ export async function getAllUserData(userIdentifier) {
}
}
if (user !== null) {
entitlements = await getEntitlements(user.username);
enrollments = await getEnrollments(user.username);
verificationStatus = await getUserVerificationStatus(user.username);
ssoRecords = await getSsoRecords(user.username);
Expand All @@ -247,7 +259,6 @@ export async function getAllUserData(userIdentifier) {
return {
errors,
user,
entitlements,
enrollments,
verificationStatus,
ssoRecords,
Expand Down
7 changes: 5 additions & 2 deletions src/users/data/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,6 @@ describe('API', () => {

it('Successful User Data Retrieval', async () => {
mockAdapter.onGet(`${userAccountApiBaseUrl}/${testUsername}`).reply(200, successDictResponse);
mockAdapter.onGet(`${entitlementsApiBaseUrl}&page=1`).reply(200, { results: [], next: null });
mockAdapter.onGet(enrollmentsApiUrl).reply(200, []);
mockAdapter.onGet(ssoRecordsApiUrl).reply(200, []);
mockAdapter.onGet(verificationDetailsApiUrl).reply(200, {});
Expand All @@ -363,7 +362,6 @@ describe('API', () => {
ssoRecords: [],
verificationStatus: { extraData: {} },
enrollments: [],
entitlements: { results: [], next: null },
onboardingStatus: { ...onboardingDefaultResponse, onboardingStatus: 'No Paid Enrollment' },
});
});
Expand Down Expand Up @@ -474,6 +472,11 @@ describe('API', () => {
user: testUsername,
uuid: 'uuid',
};
it('Unsuccessful fetch', async () => {
mockAdapter.onGet(`${entitlementsApiBaseUrl}&page=1`).reply(() => throwError(400, 'There was an error fetching entitlements.'));
const response = await api.getEntitlements(testUsername);
expect(...response.errors).toEqual({ ...expectedError, text: 'There was an error fetching entitlements.' });
});
it('Single page result', async () => {
const expectedData = {
count: 1,
Expand Down
93 changes: 49 additions & 44 deletions src/users/data/test/entitlements.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,54 @@
const entitlementsData = {
data: {
results: [
{
user: 'edX',
uuid: 'entitlement-uuid',
courseUuid: 'course-uuid',
enrollmentCourseRun: 'course-v1:testX+test123+2030',
created: Date().toLocaleString(),
modified: Date().toLocaleString(),
expiredAt: Date().toLocaleString(),
mode: 'verified',
orderNumber: '123edX456',
supportDetails: [{
supportUser: 'admin',
action: 'CREATE',
actionCreated: Date().toLocaleString(),
comments: 'creating entitlement',
unenrolledRun: null,
},
{
supportUser: 'admin',
action: 'EXPIRE',
actionCreated: Date().toLocaleString(),
comments: 'expiring entitlement',
unenrolledRun: null,
},
],
export const entitlementsData = {
results: [
{
user: 'edX',
uuid: 'entitlement-uuid',
courseUuid: 'course-uuid',
enrollmentCourseRun: 'course-v1:testX+test123+2030',
created: Date().toLocaleString(),
modified: Date().toLocaleString(),
expiredAt: Date().toLocaleString(),
mode: 'verified',
orderNumber: '123edX456',
supportDetails: [{
supportUser: 'admin',
action: 'CREATE',
actionCreated: Date().toLocaleString(),
comments: 'creating entitlement',
unenrolledRun: null,
},
{
user: 'edX',
uuid: 'entitlement-1-uuid',
courseUuid: 'course-1-uuid',
enrollmentCourseRun: 'course-v1:testX+test123+2040',
created: Date().toLocaleString(),
modified: Date().toLocaleString(),
expiredAt: Date().toLocaleString(),
mode: 'professional',
orderNumber: '123edX456789',
supportDetails: [],
supportUser: 'admin',
action: 'EXPIRE',
actionCreated: Date().toLocaleString(),
comments: 'expiring entitlement',
unenrolledRun: null,
},
],
},
user: 'edX',
expanded: true,
changeHandler: jest.fn(() => {}),
],
},
{
user: 'edX',
uuid: 'entitlement-1-uuid',
courseUuid: 'course-1-uuid',
enrollmentCourseRun: null,
created: Date().toLocaleString(),
modified: Date().toLocaleString(),
expiredAt: null,
mode: 'professional',
orderNumber: '123edX456789',
supportDetails: [],
},
],
};

export default entitlementsData;
export const entitlementsErrors = {
errors: [
{
code: null,
dismissible: true,
text: 'Test Error',
type: 'danger',
topic: 'entitlements',
},
],
};
59 changes: 38 additions & 21 deletions src/users/entitlements/Entitlements.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {
useMemo, useState, useCallback, useRef, useLayoutEffect, useContext,
useMemo, useState, useCallback, useRef, useLayoutEffect, useContext, useEffect,
} from 'react';
import PropTypes from 'prop-types';

Expand All @@ -9,14 +9,16 @@ import {
import { camelCaseObject, getConfig } from '@edx/frontend-platform';
import EntitlementForm from './EntitlementForm';
import { CREATE, REISSUE, EXPIRE } from './EntitlementActions';
import PageLoading from '../../components/common/PageLoading';
import Table from '../../Table';
import CourseSummary from '../courseSummary/CourseSummary';
import { getCourseData } from '../data/api';
import { getCourseData, getEntitlements } from '../data/api';
import UserMessagesContext from '../../userMessages/UserMessagesContext';
import { formatDate, sort } from '../../utils';
import AlertList from '../../userMessages/AlertList';

export default function Entitlements({
data, changeHandler, user, expanded,
changeHandler, user, expanded,
}) {
const { add, clear } = useContext(UserMessagesContext);
const [sortColumn, setSortColumn] = useState('created');
Expand All @@ -26,12 +28,25 @@ export default function Entitlements({
const [courseSummaryUUID, setCourseSummaryUUID] = useState(null);
const [courseSummaryData, setCourseSummaryData] = useState(null);
const [courseSummaryErrors, setCourseSummaryErrors] = useState(false);
const [entitlementData, setEntitlementData] = useState(null);
const [entitlementDetailModalIsOpen, setEntitlementDetailModalIsOpen] = useState(false);
const [entitlementSupportDetailsTitle, setEntitlementSupportDetailsTitle] = useState('');
const [entitlementSupportDetails, setEntitlementSupportDetails] = useState([]);
const formRef = useRef(null);
const summaryRef = useRef(null);

useEffect(() => {
getEntitlements(user).then((result) => {
const camelCaseResult = camelCaseObject(result);
if (camelCaseResult.errors) {
camelCaseResult.errors.forEach(error => add(error));
setEntitlementData({ results: [] });
} else {
setEntitlementData(camelCaseResult);
}
});
}, [user]);

useLayoutEffect(() => {
if (formType != null) {
formRef.current.focus();
Expand Down Expand Up @@ -79,10 +94,10 @@ export default function Entitlements({
});

const tableData = useMemo(() => {
if (data === null) {
if (entitlementData === null) {
return [];
}
return data.results.map(entitlement => ({
return entitlementData.results.map(entitlement => ({
courseUuid: {
displayValue: (
<Button
Expand Down Expand Up @@ -155,7 +170,7 @@ export default function Entitlements({
id="reissue"
type="button"
variant="outline-primary mt-2 mr-2"
disabled={!entitlement.enrollmentCourseRun}
disabled={Boolean(!entitlement.enrollmentCourseRun)}
onClick={() => {
clearCourseSummary();
setUserEntitlement(entitlement);
Expand All @@ -167,7 +182,7 @@ export default function Entitlements({
<Button
type="button"
variant="outline-danger mt-2"
disabled={entitlement.expiredAt}
disabled={Boolean(entitlement.expiredAt)}
onClick={() => {
clearCourseSummary();
setUserEntitlement(entitlement);
Expand All @@ -181,7 +196,7 @@ export default function Entitlements({
value: 'Resissue',
},
}));
}, [data]);
}, [entitlementData]);

const setSort = useCallback((column) => {
if (sortColumn === column) {
Expand Down Expand Up @@ -256,6 +271,7 @@ export default function Entitlements({
</Button>
)}
</div>
<AlertList topic="entitlements" className="mb-3" />
<TransitionReplace>
{formType !== null ? (
<EntitlementForm
Expand Down Expand Up @@ -297,31 +313,32 @@ export default function Entitlements({
)}
/>
<Collapsible title={`Entitlements (${tableData.length})`} defaultOpen={expanded}>
<Table
className="w-100"
data={tableDataSortable.sort(
(firstElement, secondElement) => sort(firstElement, secondElement, sortColumn, sortDirection),
{!entitlementData
? <PageLoading srMessage="Loading" />
: (
<Table
className="w-100"
data={tableDataSortable.sort(
(firstElement, secondElement) => sort(firstElement, secondElement, sortColumn, sortDirection),
)}
columns={columns}
tableSortable
defaultSortedColumn="created"
defaultSortDirection="desc"
/>
)}
columns={columns}
tableSortable
defaultSortedColumn="created"
defaultSortDirection="desc"
/>

</Collapsible>
</section>
);
}

Entitlements.propTypes = {
data: PropTypes.shape({
results: PropTypes.arrayOf(PropTypes.object),
}),
changeHandler: PropTypes.func.isRequired,
user: PropTypes.string.isRequired,
expanded: PropTypes.bool,
};

Entitlements.defaultProps = {
data: null,
expanded: false,
};
Loading

0 comments on commit 0b9b2eb

Please sign in to comment.