diff --git a/src/components/catalogNoResultsDeck/CatalogNoResultsDeck.jsx b/src/components/catalogNoResultsDeck/CatalogNoResultsDeck.jsx
index 6a221cf1..50883fb9 100644
--- a/src/components/catalogNoResultsDeck/CatalogNoResultsDeck.jsx
+++ b/src/components/catalogNoResultsDeck/CatalogNoResultsDeck.jsx
@@ -7,7 +7,8 @@ import PropTypes from 'prop-types';
import {
CONTENT_TYPE_COURSE,
CONTENT_TYPE_PROGRAM,
- EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
+ EXEC_ED_TITLE,
+ LEARNING_TYPE_REFINEMENT,
NO_RESULTS_DECK_ITEM_COUNT,
NO_RESULTS_PAGE_SIZE,
NO_RESULTS_PAGE_ITEM_COUNT,
@@ -41,7 +42,7 @@ function CatalogNoResultsDeck({
useEffect(() => {
const defaultCoursesRefinements = {
enterprise_catalog_query_titles: selectedCatalog,
- learning_type: contentType,
+ [LEARNING_TYPE_REFINEMENT]: contentType,
};
EnterpriseCatalogApiService.fetchDefaultCoursesInCatalogWithFacets(
@@ -66,7 +67,7 @@ function CatalogNoResultsDeck({
defaultDeckTitle = intl.formatMessage(
messages['catalogSearchResults.DefaultCourseDeckTitle'],
);
- } else if (contentType === EXECUTIVE_EDUCATION_2U_COURSE_TYPE) {
+ } else if (contentType === EXEC_ED_TITLE) {
alertText = intl.formatMessage(
messages['catalogSearchResults.NoResultsExecEdCourseBannerText'],
);
diff --git a/src/components/catalogNoResultsDeck/CatalogNoResultsDeck.test.jsx b/src/components/catalogNoResultsDeck/CatalogNoResultsDeck.test.jsx
index 1326c8e5..cc1d656d 100644
--- a/src/components/catalogNoResultsDeck/CatalogNoResultsDeck.test.jsx
+++ b/src/components/catalogNoResultsDeck/CatalogNoResultsDeck.test.jsx
@@ -60,7 +60,7 @@ const execEdProps = {
setCardView: jest.fn(),
columns: [],
renderCardComponent: jest.fn(),
- contentType: 'executive-education-2u',
+ contentType: 'Executive Education',
};
describe('catalog no results deck works as expected', () => {
diff --git a/src/components/catalogPage/CatalogPage.jsx b/src/components/catalogPage/CatalogPage.jsx
index 261ce494..6bf63f9b 100644
--- a/src/components/catalogPage/CatalogPage.jsx
+++ b/src/components/catalogPage/CatalogPage.jsx
@@ -17,20 +17,20 @@ import CatalogSelectionDeck from '../catalogSelectionDeck/CatalogSelectionDeck';
import {
AVAILABILITY_REFINEMENT,
AVAILABILITY_REFINEMENT_DEFAULTS,
- EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
+ EXEC_ED_TITLE,
+ LEARNING_TYPE_REFINEMENT,
QUERY_TITLE_REFINEMENT,
HIDE_CARDS_REFINEMENT,
TRACKING_APP_NAME,
} from '../../constants';
-const LEARNING_TYPE_REFINEMENT = 'learning_type';
const learningType = {
- attribute: 'learning_type',
+ attribute: LEARNING_TYPE_REFINEMENT,
title: 'Learning Type',
};
// Add learning_type to the search facet filters if it doesn't exist in the list yet.
if (
- !SEARCH_FACET_FILTERS.some((filter) => filter.attribute === 'learning_type')
+ !SEARCH_FACET_FILTERS.some((filter) => filter.attribute === LEARNING_TYPE_REFINEMENT)
) {
SEARCH_FACET_FILTERS.push(learningType);
}
@@ -63,7 +63,7 @@ function CatalogPage({ intl }) {
=== config.EDX_ENTERPRISE_ALACARTE_TITLE
))
&& loadedSearchParams.get(LEARNING_TYPE_REFINEMENT)
- === EXECUTIVE_EDUCATION_2U_COURSE_TYPE
+ === EXEC_ED_TITLE
) {
const loadedLearningTypes = loadedSearchParams.getAll(
LEARNING_TYPE_REFINEMENT,
@@ -71,7 +71,7 @@ function CatalogPage({ intl }) {
if (loadedLearningTypes.length) {
loadedSearchParams.delete(LEARNING_TYPE_REFINEMENT);
loadedLearningTypes.forEach((type) => {
- if (type !== EXECUTIVE_EDUCATION_2U_COURSE_TYPE) {
+ if (type !== EXEC_ED_TITLE) {
loadedSearchParams.append(LEARNING_TYPE_REFINEMENT, type);
}
});
@@ -84,7 +84,6 @@ function CatalogPage({ intl }) {
// the `a la carte` catalog
if (
config.EDX_ENTERPRISE_ALACARTE_TITLE
- && !loadedSearchParams.get(LEARNING_TYPE_REFINEMENT)
&& !loadedSearchParams.get(QUERY_TITLE_REFINEMENT)
) {
loadedSearchParams.set(
@@ -97,7 +96,6 @@ function CatalogPage({ intl }) {
// Ensure we have availability refinement(s) set by default
if (
!loadedSearchParams.get(AVAILABILITY_REFINEMENT)
- && !loadedSearchParams.get(LEARNING_TYPE_REFINEMENT)
) {
AVAILABILITY_REFINEMENT_DEFAULTS.map((a) => loadedSearchParams.append(AVAILABILITY_REFINEMENT, a));
reloadPage = true;
diff --git a/src/components/catalogPage/CatalogPage.test.jsx b/src/components/catalogPage/CatalogPage.test.jsx
index 8d25ba46..875ed942 100644
--- a/src/components/catalogPage/CatalogPage.test.jsx
+++ b/src/components/catalogPage/CatalogPage.test.jsx
@@ -4,6 +4,7 @@ import React from 'react';
import { mockWindowLocations, renderWithRouter } from '../tests/testUtils';
import CatalogPage from './CatalogPage';
import selectionCardMessage from '../catalogSelectionDeck/CatalogSelectionDeck.messages';
+import { LEARNING_TYPE_REFINEMENT } from '../../constants';
// all we are testing is routes, we don't need InstantSearch to work here
jest.mock('react-instantsearch-dom', () => ({
@@ -72,17 +73,17 @@ describe('CatalogPage', () => {
it('accounts for exec ed disclusion when not a la carte is selected', () => {
const location = {
...window.location,
- search: '?learning_type=executive-education-2u&learning_type=ayylmao&enterprise_catalog_query_titles=foobar',
+ search: `?${LEARNING_TYPE_REFINEMENT}=Executive Education&${LEARNING_TYPE_REFINEMENT}=ayylmao&enterprise_catalog_query_titles=foobar`,
};
Object.defineProperty(window, 'location', {
writable: true,
value: location,
});
- expect(window.location.search).toEqual('?learning_type=executive-education-2u&learning_type=ayylmao&enterprise_catalog_query_titles=foobar');
+ expect(window.location.search).toEqual(`?${LEARNING_TYPE_REFINEMENT}=Executive Education&${LEARNING_TYPE_REFINEMENT}=ayylmao&enterprise_catalog_query_titles=foobar`);
renderWithRouter();
// Assert learning type: exec ed has been removed but not learning type `ayylmao`
expect(window.location.search).toEqual(
- 'enterprise_catalog_query_titles=foobar&learning_type=ayylmao',
+ `enterprise_catalog_query_titles=foobar&${LEARNING_TYPE_REFINEMENT}=ayylmao&availability=Available+Now&availability=Starting+Soon&availability=Upcoming`,
);
});
});
diff --git a/src/components/catalogSearchResults/CatalogSearchResults.jsx b/src/components/catalogSearchResults/CatalogSearchResults.jsx
index 0c6789cb..80a6f2e6 100644
--- a/src/components/catalogSearchResults/CatalogSearchResults.jsx
+++ b/src/components/catalogSearchResults/CatalogSearchResults.jsx
@@ -29,7 +29,6 @@ import {
COURSE_TITLE,
EDX_COURSE_TITLE_DESC,
EXEC_ED_TITLE,
- EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
HIDE_PRICE_REFINEMENT,
LEARNING_TYPE_REFINEMENT,
PROGRAM_TITLE,
@@ -91,7 +90,7 @@ export function BaseCatalogSearchResults({
useEffect(() => {
setIsProgramType(contentType === CONTENT_TYPE_PROGRAM);
setIsCourseType(contentType === CONTENT_TYPE_COURSE);
- setIsExecEdType(contentType === EXECUTIVE_EDUCATION_2U_COURSE_TYPE);
+ setIsExecEdType(contentType === EXEC_ED_TITLE);
}, [contentType]);
const TABLE_HEADERS = useMemo(
@@ -168,7 +167,7 @@ export function BaseCatalogSearchResults({
} else if (isExecEdType) {
dispatch(
setRefinementAction(LEARNING_TYPE_REFINEMENT, [
- EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
+ EXEC_ED_TITLE,
]),
);
} else {
@@ -182,7 +181,7 @@ export function BaseCatalogSearchResults({
if (contentType === CONTENT_TYPE_COURSE) {
return ;
}
- if (contentType === EXECUTIVE_EDUCATION_2U_COURSE_TYPE) {
+ if (contentType === EXEC_ED_TITLE) {
return ;
}
return ;
diff --git a/src/components/catalogSearchResults/CatalogSearchResults.test.jsx b/src/components/catalogSearchResults/CatalogSearchResults.test.jsx
index 2dac0057..1f2c7ddb 100644
--- a/src/components/catalogSearchResults/CatalogSearchResults.test.jsx
+++ b/src/components/catalogSearchResults/CatalogSearchResults.test.jsx
@@ -15,7 +15,7 @@ import messages from './CatalogSearchResults.messages';
import {
CONTENT_TYPE_COURSE,
CONTENT_TYPE_PROGRAM,
- EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
+ EXEC_ED_TITLE,
HIDE_PRICE_REFINEMENT,
} from '../../constants';
import EnterpriseCatalogApiService from '../../data/services/EnterpriseCatalogAPIService';
@@ -150,7 +150,7 @@ const searchResultsExecEd = {
card_image_url: 'http://url.test2.location',
availability: ['Available Now'],
course_keys: [],
- content_type: EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
+ content_type: EXEC_ED_TITLE,
entitlements: [{ price: '100.00' }],
advertised_course_run: {
start: '2020-01-24T05:00:00Z',
@@ -214,7 +214,7 @@ const execEdProps = {
isSearchStalled: false,
searchState: { page: 1 },
error: null,
- contentType: EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
+ contentType: EXEC_ED_TITLE,
// mock i18n requirements
intl: {
formatMessage: (header) => header.defaultMessage,
diff --git a/src/components/catalogs/CatalogSearch.jsx b/src/components/catalogs/CatalogSearch.jsx
index 10109ffa..60d39f12 100644
--- a/src/components/catalogs/CatalogSearch.jsx
+++ b/src/components/catalogs/CatalogSearch.jsx
@@ -20,7 +20,8 @@ import PageWrapper from '../PageWrapper';
import {
CONTENT_TYPE_COURSE,
CONTENT_TYPE_PROGRAM,
- EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
+ EXEC_ED_TITLE,
+ LEARNING_TYPE_REFINEMENT,
NUM_RESULTS_COURSE,
NUM_RESULTS_PROGRAM,
NUM_RESULTS_PER_PAGE,
@@ -32,19 +33,20 @@ import {
mapAlgoliaObjectToCourse,
mapAlgoliaObjectToExecEd,
} from '../../utils/algoliaUtils';
+import { convertLearningTypesToFilters } from '../../utils/catalogUtils';
import messages from '../catalogSearchResults/CatalogSearchResults.messages';
function CatalogSearch(intl) {
const {
refinements: {
- learning_type: learningType,
+ [LEARNING_TYPE_REFINEMENT]: learningType,
enterprise_catalog_query_titles: enterpriseCatalogQueryTitles,
},
} = useContext(SearchContext);
const { algoliaIndexName, searchClient } = useAlgoliaIndex();
- const courseFilter = `learning_type:${CONTENT_TYPE_COURSE}`;
- const execEdFilter = `learning_type:${EXECUTIVE_EDUCATION_2U_COURSE_TYPE}`;
- const programFilter = `learning_type:${CONTENT_TYPE_PROGRAM}`;
+ const courseFilter = `${LEARNING_TYPE_REFINEMENT}:${CONTENT_TYPE_COURSE}`;
+ const execEdFilter = `${LEARNING_TYPE_REFINEMENT}:"${EXEC_ED_TITLE}"`;
+ const programFilter = `${LEARNING_TYPE_REFINEMENT}:${CONTENT_TYPE_PROGRAM}`;
const [noCourseResults, setNoCourseResults] = useState(false);
const [noProgramResults, setNoProgramResults] = useState(false);
const [noExecEdResults, setNoExecEdResults] = useState(false);
@@ -67,7 +69,7 @@ function CatalogSearch(intl) {
setNoResults: setNoCourseResults,
numResults: NUM_RESULTS_COURSE,
},
- [EXECUTIVE_EDUCATION_2U_COURSE_TYPE]: {
+ [EXEC_ED_TITLE]: {
filter: execEdFilter,
noResults: noExecEdResults,
setNoResults: setNoExecEdResults,
@@ -93,7 +95,7 @@ function CatalogSearch(intl) {
useEffect(() => {
contentData[CONTENT_TYPE_COURSE].noResults = noCourseResults;
contentData[CONTENT_TYPE_PROGRAM].noResults = noProgramResults;
- contentData[EXECUTIVE_EDUCATION_2U_COURSE_TYPE].noResults = noExecEdResults;
+ contentData[EXEC_ED_TITLE].noResults = noExecEdResults;
}, [noCourseResults, noProgramResults, noExecEdResults, contentData]);
// set specified content types & suggested search content types
@@ -103,7 +105,7 @@ function CatalogSearch(intl) {
setSpecifiedContentType(learningType);
}
setSuggestedSearchContentTypeFilter(
- learningType.map((item) => `learning_type:${item}`).join(' OR '),
+ convertLearningTypesToFilters(learningType),
);
} else {
setSpecifiedContentType(undefined);
@@ -111,9 +113,9 @@ function CatalogSearch(intl) {
[
CONTENT_TYPE_COURSE,
CONTENT_TYPE_PROGRAM,
- EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
+ `"${EXEC_ED_TITLE}"`,
]
- .map((item) => `learning_type:${item}`)
+ .map((item) => `${LEARNING_TYPE_REFINEMENT}:${item}`)
.join(' OR '),
);
}
@@ -126,12 +128,12 @@ function CatalogSearch(intl) {
}, [config.ALGOLIA_INDEX_NAME, searchClient]);
const suggestedCourseOnClick = (hit) => {
- if (hit.learning_type === CONTENT_TYPE_PROGRAM) {
+ if (hit[LEARNING_TYPE_REFINEMENT] === CONTENT_TYPE_PROGRAM) {
setSelectedSuggestedCourse(mapAlgoliaObjectToProgram(hit));
setSelectedSuggestedCourseType(CONTENT_TYPE_PROGRAM);
- } else if (hit.learning_type === EXECUTIVE_EDUCATION_2U_COURSE_TYPE) {
+ } else if (hit[LEARNING_TYPE_REFINEMENT] === EXEC_ED_TITLE) {
setSelectedSuggestedCourse(mapAlgoliaObjectToExecEd(hit));
- setSelectedSuggestedCourseType(EXECUTIVE_EDUCATION_2U_COURSE_TYPE);
+ setSelectedSuggestedCourseType(EXEC_ED_TITLE);
} else {
setSelectedSuggestedCourse(mapAlgoliaObjectToCourse(hit, intl, messages));
setSelectedSuggestedCourseType(CONTENT_TYPE_COURSE);
@@ -144,7 +146,7 @@ function CatalogSearch(intl) {
useEffect(() => {
const defaultTypes = [
CONTENT_TYPE_COURSE,
- EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
+ EXEC_ED_TITLE,
CONTENT_TYPE_PROGRAM,
];
// Grab content type(s) to use
@@ -159,9 +161,9 @@ function CatalogSearch(intl) {
config.EDX_ENTERPRISE_ALACARTE_TITLE,
))
) {
- if (contentToDisplay.indexOf(EXECUTIVE_EDUCATION_2U_COURSE_TYPE) > 0) {
+ if (contentToDisplay.indexOf(EXEC_ED_TITLE) > 0) {
contentToDisplay.splice(
- contentToDisplay.indexOf(EXECUTIVE_EDUCATION_2U_COURSE_TYPE),
+ contentToDisplay.indexOf(EXEC_ED_TITLE),
1,
);
}
@@ -215,7 +217,7 @@ function CatalogSearch(intl) {
return itemsWithResultsList;
};
- const defaultInstantSearchFilter = `learning_type:${CONTENT_TYPE_COURSE} OR learning_type:${CONTENT_TYPE_PROGRAM} OR learning_type:${EXECUTIVE_EDUCATION_2U_COURSE_TYPE}`;
+ const defaultInstantSearchFilter = `${LEARNING_TYPE_REFINEMENT}:${CONTENT_TYPE_COURSE} OR ${LEARNING_TYPE_REFINEMENT}:${CONTENT_TYPE_PROGRAM} OR ${LEARNING_TYPE_REFINEMENT}:"${EXEC_ED_TITLE}"`;
return (
diff --git a/src/components/courseCard/CourseCard.jsx b/src/components/courseCard/CourseCard.jsx
index 49eb3e8a..33eda7a7 100644
--- a/src/components/courseCard/CourseCard.jsx
+++ b/src/components/courseCard/CourseCard.jsx
@@ -60,14 +60,14 @@ function CourseCard({
{priceText} • {pacingType}
- {enterprise_catalog_query_titles.includes(
+ {enterprise_catalog_query_titles?.includes(
process.env.EDX_ENTERPRISE_ALACARTE_TITLE,
) && (
{intl.formatMessage(messages['courseCard.aLaCarteBadge'])}
)}
- {enterprise_catalog_query_titles.includes(
+ {enterprise_catalog_query_titles?.includes(
process.env.EDX_FOR_BUSINESS_TITLE,
) && (
)}
- {enterprise_catalog_query_titles.includes(
+ {enterprise_catalog_query_titles?.includes(
process.env.EDX_FOR_ONLINE_EDU_TITLE,
) && (
diff --git a/src/components/courseCard/CourseCard.test.jsx b/src/components/courseCard/CourseCard.test.jsx
index aee1b495..235dd536 100644
--- a/src/components/courseCard/CourseCard.test.jsx
+++ b/src/components/courseCard/CourseCard.test.jsx
@@ -4,7 +4,7 @@ import '@testing-library/jest-dom/extend-expect';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import CourseCard from './CourseCard';
-import { CONTENT_TYPE_COURSE, EXECUTIVE_EDUCATION_2U_COURSE_TYPE } from '../../constants';
+import { CONTENT_TYPE_COURSE, EXEC_ED_TITLE } from '../../constants';
jest.mock('@edx/frontend-platform', () => ({
...jest.requireActual('@edx/frontend-platform'),
@@ -40,7 +40,7 @@ const execEdData = {
const execEdProps = {
original: execEdData,
- learningType: EXECUTIVE_EDUCATION_2U_COURSE_TYPE,
+ learningType: EXEC_ED_TITLE,
};
describe('Course card works as expected', () => {
diff --git a/src/constants.js b/src/constants.js
index 32f1a88b..5fe17a21 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -18,34 +18,33 @@ export const AVAILABILITY_REFINEMENT_DEFAULTS = [
'Upcoming',
];
+// Facet filters
export const CONTENT_TYPE_REFINEMENT = 'content_type';
export const COURSE_TYPE_REFINEMENT = 'course_type';
-export const LEARNING_TYPE_REFINEMENT = 'learning_type';
+export const LEARNING_TYPE_REFINEMENT = 'learning_type_v2';
+
+// Page refinement settings
export const HIDE_CARDS_REFINEMENT = 'hide_cards';
export const HIDE_PRICE_REFINEMENT = 'hide_price';
export const NUM_RESULTS_PER_PAGE = 40;
+
+// Learning types
export const CONTENT_TYPE_COURSE = 'course';
export const CONTENT_TYPE_PROGRAM = 'program';
+export const EXEC_ED_TITLE = 'Executive Education';
+
+// Page metric settings
export const NUM_RESULTS_PROGRAM = 4;
export const NUM_RESULTS_COURSE = 8;
+
export const COURSE_TITLE = 'Courses';
export const PROGRAM_TITLE = 'Programs';
-export const EXEC_ED_TITLE = 'Executive Education';
+
export const NO_RESULTS_DECK_ITEM_COUNT = 4;
export const NO_RESULTS_PAGE_ITEM_COUNT = 1;
export const NO_RESULTS_PAGE_SIZE = 4;
-const AUDIT_COURSE_TYPE = 'audit';
-const VERIFIED_AUDIT_COURSE_TYPE = 'verified-audit';
-const PROFESSIONAL_COURSE_TYPE = 'professional';
-const CREDIT_VERIFIED_AUDIT_COURSE_TYPE = 'credit-verified-audit';
-export const EXECUTIVE_EDUCATION_2U_COURSE_TYPE = 'executive-education-2u';
-export const EDX_COURSES_COURSE_TYPES = [
- AUDIT_COURSE_TYPE,
- VERIFIED_AUDIT_COURSE_TYPE,
- PROFESSIONAL_COURSE_TYPE,
- CREDIT_VERIFIED_AUDIT_COURSE_TYPE,
-];
+// Descriptions
export const EDX_COURSE_TITLE_DESC = 'Self paced online learning from world-class academic institutions and corporate partners.';
export const TWOU_EXEC_ED_TITLE_DESC = 'Immersive, instructor led online short courses designed to develop interpersonal, analytical, and critical thinking skills.';
export const PROGRAM_TITLE_DESC = 'Multi-course bundled learning for skills mastery and to earn credentials such as Professional Certificates, MicroBachelors™, MicroMasters®, and Master’s Degrees.';
diff --git a/src/utils/catalogUtils.js b/src/utils/catalogUtils.js
index 3b20d2b2..128a5144 100644
--- a/src/utils/catalogUtils.js
+++ b/src/utils/catalogUtils.js
@@ -1,3 +1,5 @@
+import { EXEC_ED_TITLE } from '../constants';
+
/* eslint-disable import/prefer-default-export */
const nowDate = new Date(Date.now());
@@ -32,4 +34,15 @@ function checkAvailability(start, end) {
return '';
}
-export { checkAvailability, checkSubscriptions };
+function convertLearningTypesToFilters(types) {
+ return types.reduce((learningFacets, type) => {
+ if (type === EXEC_ED_TITLE) {
+ learningFacets.push(`"${type}"`);
+ } else {
+ learningFacets.push(type);
+ }
+ return learningFacets;
+ }, []).join(' OR ');
+}
+
+export { checkAvailability, checkSubscriptions, convertLearningTypesToFilters };
diff --git a/src/utils/catalogUtils.test.js b/src/utils/catalogUtils.test.js
new file mode 100644
index 00000000..91b29975
--- /dev/null
+++ b/src/utils/catalogUtils.test.js
@@ -0,0 +1,9 @@
+import { EXEC_ED_TITLE } from '../constants';
+import { convertLearningTypesToFilters } from './catalogUtils';
+
+describe('catalogUtils', () => {
+ it('converts lists of learning types to algolia filters', () => {
+ const algoliaFilter = convertLearningTypesToFilters(['a', 'b', EXEC_ED_TITLE]);
+ expect(algoliaFilter).toEqual('a OR b OR "Executive Education"');
+ });
+});