Skip to content

Commit

Permalink
squash: address comments 2
Browse files Browse the repository at this point in the history
  • Loading branch information
pwnage101 committed Aug 20, 2024
1 parent 3a10a7b commit 87d0126
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 29 deletions.
31 changes: 22 additions & 9 deletions src/components/app/data/hooks/useCourseMetadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
determineAllocatedCourseRunAssignmentsForCourse,
getAvailableCourseRuns,
transformCourseMetadataByAllocatedCourseRunAssignments,
isRunUnrestrictedForCatalog,
isRunUnrestrictedForCustomer,
} from '../utils';
import useLateEnrollmentBufferDays from './useLateEnrollmentBufferDays';
Expand All @@ -16,7 +17,7 @@ import useEnterpriseCustomerContainsContent from './useEnterpriseCustomerContain
* Retrieves the course metadata for the given enterprise customer and course key.
* @returns {Types.UseQueryResult}} The query results for the course metadata.
*/
export default function useCourseMetadata(queryOptions = {}) {
export default function useCourseMetadata(queryOptions = {}, catalogUuid = undefined) {
const { select, ...queryOptionsRest } = queryOptions;
const { courseKey } = useParams();
const [searchParams] = useSearchParams();
Expand Down Expand Up @@ -55,14 +56,26 @@ export default function useCourseMetadata(queryOptions = {}) {
// First stage filters out any runs that are unavailable for universal reasons, such as enrollment windows and
// published states.
const basicAvailableCourseRuns = getAvailableCourseRuns({ course: data, lateEnrollmentBufferDays });
// Second stage filters out any *restricted* runs that are certainly not available to the current customer. The
// result may still include runs that are restricted for the subsidy types actually applicable for the learner, so
// consumers of useCourseMetadata() should perform additional subsidy-specific filtering.
const availableAndUnrestrictedCourseRuns = basicAvailableCourseRuns.filter(r => isRunUnrestrictedForCustomer({
restrictedRunsAllowed,
courseKey,
courseRunMetadata: r,
}));
// Second stage filters out any *restricted* runs.
let restrictedRunFilter;
if (catalogUuid) {
// We have all the info we need to filter out restricted runs that are not redeemable via a specific catalog.
restrictedRunFilter = courseRunMetadata => isRunUnrestrictedForCatalog({

Check warning on line 63 in src/components/app/data/hooks/useCourseMetadata.js

View check run for this annotation

Codecov / codecov/patch

src/components/app/data/hooks/useCourseMetadata.js#L63

Added line #L63 was not covered by tests
restrictedRunsAllowed,
courseKey,
courseRunMetadata,
catalogUuid,
});
} else {
// Fallback to only filtering out runs that are not available to the current customer under ANY catalog. The
// result may still include runs that are restricted for the subsidy types actually applicable for the learner.
restrictedRunFilter = courseRunMetadata => isRunUnrestrictedForCustomer({
restrictedRunsAllowed,
courseKey,
courseRunMetadata,
});
}
const availableAndUnrestrictedCourseRuns = basicAvailableCourseRuns.filter(restrictedRunFilter);
let transformedData = {
...data,
availableCourseRuns: availableAndUnrestrictedCourseRuns,
Expand Down
3 changes: 2 additions & 1 deletion src/components/app/data/services/course.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { logError } from '@edx/frontend-platform/logging';

import { getErrorResponseStatusCode } from '../../../../utils/common';
import { findHighestLevelEntitlementSku, getActiveCourseRun } from '../utils';
import { ENTERPRISE_RESTRICTION_TYPE } from '../../../../constants';

/**
* TODO
Expand All @@ -17,7 +18,7 @@ export async function fetchCourseMetadata(courseKey, courseRunKey) {
const contentMetadataUrl = `${getConfig().DISCOVERY_API_BASE_URL}/api/v1/courses/${courseKey}/`;
const queryParams = new URLSearchParams();
// Always include restricted/custom-b2b-enterprise runs in case one has been requested.
queryParams.append('include_restricted', 'custom-b2b-enterprise');
queryParams.append('include_restricted', ENTERPRISE_RESTRICTION_TYPE);
const url = `${contentMetadataUrl}?${queryParams.toString()}`;
try {
const response = await getAuthenticatedHttpClient().get(url);
Expand Down
5 changes: 3 additions & 2 deletions src/components/app/data/services/course.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { fetchCanRedeem, fetchCourseMetadata, fetchCourseRunMetadata } from './c
import { findHighestLevelEntitlementSku, getActiveCourseRun } from '../utils';
import { getErrorResponseStatusCode } from '../../../../utils/common';
import { COURSE_MODES_MAP } from '../constants';
import { ENTERPRISE_RESTRICTION_TYPE } from '../../../../constants';

const axiosMock = new MockAdapter(axios);
getAuthenticatedHttpClient.mockReturnValue(axios);
Expand Down Expand Up @@ -35,7 +36,7 @@ jest.mock('@edx/frontend-platform/auth', () => ({
}));

describe('fetchCourseMetadata', () => {
const params = 'include_restricted=custom-b2b-enterprise';
const params = `include_restricted=${ENTERPRISE_RESTRICTION_TYPE}`;
const CONTENT_METADATA_URL = `${APP_CONFIG.DISCOVERY_API_BASE_URL}/api/v1/courses/${mockCourseKey}/?${params}`;
const courseMetadata = {
key: mockCourseKey,
Expand Down Expand Up @@ -77,7 +78,7 @@ describe('fetchCourseMetadata', () => {
});

describe('fetchCourseRunMetadata', () => {
const params = 'include_restricted=custom-b2b-enterprise';
const params = `include_restricted=${ENTERPRISE_RESTRICTION_TYPE}`;
const COURSE_RUN_METADATA = `${APP_CONFIG.DISCOVERY_API_BASE_URL}/api/v1/course_runs/${mockCourseRunKey}/?${params}`;
const courseRunMetadata = {
key: mockCourseRunKey,
Expand Down
4 changes: 2 additions & 2 deletions src/components/app/data/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { logError } from '@edx/frontend-platform/logging';
import { ASSIGNMENT_TYPES, POLICY_TYPES } from '../../enterprise-user-subsidy/enterprise-offers/data/constants';
import { LICENSE_STATUS } from '../../enterprise-user-subsidy/data/constants';
import { getBrandColorsFromCSSVariables, isDefinedAndNotNull, isTodayWithinDateThreshold } from '../../../utils/common';
import { COURSE_STATUSES, SUBSIDY_TYPE } from '../../../constants';
import { COURSE_STATUSES, SUBSIDY_TYPE, ENTERPRISE_RESTRICTION_TYPE } from '../../../constants';
import { LATE_ENROLLMENTS_BUFFER_DAYS } from '../../../config/constants';
import {
COUPON_CODE_SUBSIDY_TYPE,
Expand Down Expand Up @@ -848,7 +848,7 @@ export function getAllowedCatalogsForRestrictedRun({
courseKey,
courseRunMetadata,
}) {
if (courseRunMetadata?.restrictionType === 'custom-b2b-enterprise') {
if (courseRunMetadata?.restrictionType === ENTERPRISE_RESTRICTION_TYPE) {
return {
allowedCatalogs: restrictedRunsAllowed?.[courseKey]?.[courseRunMetadata.key]?.catalogUuids,
isRestricted: true,
Expand Down
18 changes: 3 additions & 15 deletions src/components/course/course-header/CourseRunCards.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
useEnterpriseCourseEnrollments,
useEnterpriseCustomerContainsContent,
useUserEntitlements,
isRunUnrestrictedForCatalog,
} from '../../app/data';

/**
Expand All @@ -24,28 +23,17 @@ const CourseRunCards = () => {
missingUserSubsidyReason,
catalogUuid,
} = useUserSubsidyApplicableToCourse();
const {
data: {
catalogList,
restrictedRunsAllowed,
},
} = useEnterpriseCustomerContainsContent([courseKey]);
const { data: courseMetadata } = useCourseMetadata();
const { data: courseMetadata } = useCourseMetadata({}, catalogUuid);
const { data: { catalogList } } = useEnterpriseCustomerContainsContent([courseKey]);
const { data: { enterpriseCourseEnrollments } } = useEnterpriseCourseEnrollments();
const { data: userEntitlements } = useUserEntitlements();
const availableCourseRuns = courseMetadata.availableCourseRuns.filter(r => isRunUnrestrictedForCatalog({
restrictedRunsAllowed,
courseKey: courseMetadata.key,
courseRunMetadata: r,
catalogUuid,
}));

return (
<CardGrid
columnSizes={{ xs: 12, md: 6, lg: 5 }}
hasEqualColumnHeights={false}
>
{availableCourseRuns.map((courseRun) => {
{courseMetadata.availableCourseRuns.map((courseRun) => {
const hasRedeemablePolicy = userSubsidyApplicableToCourse?.subsidyType === LEARNER_CREDIT_SUBSIDY_TYPE;

// Render the newer `CourseRunCard` component when the user's subsidy, if any, is
Expand Down
5 changes: 5 additions & 0 deletions src/constants/course.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,8 @@ export const COURSE_PACING = {
INSTRUCTOR: 'instructor',
SELF: 'self',
};

// [ENT-9360] Restricted runs feature. Pass this slug to discovery API endpoints (param key is "include_restricted") to
// retrieve restricted runs. Find the same restriction type encoded in course run metadata under the `restriction_type`
// metadata key.
export const ENTERPRISE_RESTRICTION_TYPE = 'custom-b2b-enterprise';

0 comments on commit 87d0126

Please sign in to comment.