- { /* eslint-disable-next-line react/no-danger, no-underscore-dangle */ }
-
);
};
@@ -47,12 +68,21 @@ SearchSuggestionItem.propTypes = {
title: PropTypes.string,
program_type: PropTypes.string,
_highlightResult: PropTypes.shape({ title: PropTypes.shape({ value: PropTypes.string }) }),
+ card_image_url: PropTypes.string,
+ partners: PropTypes.arrayOf(
+ PropTypes.shape({
+ name: PropTypes.string,
+ }),
+ ),
+ learning_type: PropTypes.string,
}).isRequired,
disableSuggestionRedirect: PropTypes.bool.isRequired,
+ isPreQuery: PropTypes.bool,
};
SearchSuggestionItem.defaultProps = {
suggestionItemHandler: undefined,
+ isPreQuery: false,
};
export default SearchSuggestionItem;
diff --git a/packages/catalog-search/src/SearchSuggestions.jsx b/packages/catalog-search/src/SearchSuggestions.jsx
index af8f743d..6f126ca2 100644
--- a/packages/catalog-search/src/SearchSuggestions.jsx
+++ b/packages/catalog-search/src/SearchSuggestions.jsx
@@ -4,10 +4,12 @@ import PropTypes from 'prop-types';
import {
MAX_NUM_SUGGESTIONS, LEARNING_TYPE_COURSE, LEARNING_TYPE_PROGRAM,
LEARNING_TYPE_EXECUTIVE_EDUCATION, COURSE_TYPE_EXECUTIVE_EDUCATION,
+ MAX_NUM_PRE_QUERY_SUGGESTIONS,
} from './data/constants';
import SearchSuggestionItem from './SearchSuggestionItem';
const SearchSuggestions = ({
+ preQueryHits,
autoCompleteHits,
enterpriseSlug,
handleSubmit,
@@ -24,9 +26,16 @@ const SearchSuggestions = ({
};
const getLinkToProgram = (program) => `/${enterpriseSlug}/program/${program.aggregation_key.split(':').pop()}`;
+ const preQuerySuggestions = [];
const courses = [];
const programs = [];
const execEdCourses = [];
+
+ if (preQueryHits) {
+ preQueryHits.forEach((hit) => {
+ preQuerySuggestions.push(hit);
+ });
+ }
autoCompleteHits.forEach((hit) => {
const { learning_type: learningType } = hit;
if (learningType === LEARNING_TYPE_COURSE) { courses.push(hit); }
@@ -35,6 +44,36 @@ const SearchSuggestions = ({
});
return (
+ {preQuerySuggestions.length > 0 && (
+
+
+ Top-rated courses
+
+ {
+ preQuerySuggestions.slice(0, MAX_NUM_PRE_QUERY_SUGGESTIONS)
+ .map((hit) => {
+ const getUrl = (course) => {
+ const { learning_type: learningType } = course;
+ if (learningType === LEARNING_TYPE_COURSE || learningType === LEARNING_TYPE_EXECUTIVE_EDUCATION) {
+ return getLinkToCourse(course);
+ }
+ return getLinkToProgram(course);
+ };
+
+ return (
+
0}
+ disableSuggestionRedirect={disableSuggestionRedirect}
+ suggestionItemHandler={handleSuggestionClickSubmit}
+ />
+ );
+ })
+ }
+
+ )}
{courses.length > 0 && (
@@ -47,6 +86,7 @@ const SearchSuggestions = ({
key={hit.title}
url={getLinkToCourse(hit)}
hit={hit}
+ isPreQuery={preQuerySuggestions.length > 0}
disableSuggestionRedirect={disableSuggestionRedirect}
suggestionItemHandler={handleSuggestionClickSubmit}
/>
@@ -92,9 +132,11 @@ const SearchSuggestions = ({
}
)}
-
+ {!preQuerySuggestions.length && (
+
+ )}
);
};
@@ -107,6 +149,7 @@ SearchSuggestions.propTypes = {
handleSubmit: PropTypes.func,
handleSuggestionClickSubmit: PropTypes.func,
disableSuggestionRedirect: PropTypes.bool,
+ preQueryHits: PropTypes.arrayOf(PropTypes.shape()),
};
SearchSuggestions.defaultProps = {
@@ -114,6 +157,7 @@ SearchSuggestions.defaultProps = {
enterpriseSlug: '',
handleSuggestionClickSubmit: undefined,
disableSuggestionRedirect: false,
+ preQueryHits: undefined,
};
export default SearchSuggestions;
diff --git a/packages/catalog-search/src/data/constants.js b/packages/catalog-search/src/data/constants.js
index e000b0fc..bf11b32b 100644
--- a/packages/catalog-search/src/data/constants.js
+++ b/packages/catalog-search/src/data/constants.js
@@ -87,6 +87,7 @@ export const NUM_CURRENT_REFINEMENTS_TO_DISPLAY = 3;
export const NUM_RESULTS_PER_PAGE = 24;
export const MAX_NUM_SUGGESTIONS = 3;
+export const MAX_NUM_PRE_QUERY_SUGGESTIONS = 5;
export const NO_OPTIONS_FOUND = 'No options found.';
diff --git a/packages/catalog-search/src/styles/_SearchSuggestions.scss b/packages/catalog-search/src/styles/_SearchSuggestions.scss
index 7d589775..b75aadfc 100644
--- a/packages/catalog-search/src/styles/_SearchSuggestions.scss
+++ b/packages/catalog-search/src/styles/_SearchSuggestions.scss
@@ -1,4 +1,4 @@
-.suggestions{
+.suggestions {
position: absolute;
background: white;
margin-top: auto;
@@ -13,53 +13,84 @@
margin: 5px 10px 5px 10px;
padding: 8px;
color: #000;
+ font-size: 75%;
white-space: pre-wrap;
- &:hover{
- color:white;
- background-color:#000000 ;
- text-decoration: none;
- }
- &:hover span {
- color:white;
+ &:hover {
+ color: white;
+ background-color: #000000;
+ text-decoration: none;
}
- em {
- font-weight: bold;
- font-style: normal;
- &:hover{
+
+ &:hover span {
color: white;
}
- &:not(:first-child) {
- margin-left: 4px; // add space between _highlightResult.title.value hits
+
+ em {
+ font-weight: bold;
+ font-style: normal;
+
+ &:hover {
+ color: white;
+ }
+
+ &:not(:first-child) {
+ margin-left: 4px; // add space between _highlightResult.title.value hits
+ }
}
-}
- div{
+
+ div {
display: flex;
}
- .authoring-org-badge{
+
+ .authoring-org-badge {
line-height: 1.5;
}
- .program-type{
+ .program-type {
font-size: .9rem;
margin-bottom: 0px;
}
}
+.prequery-item {
+ margin: 5px 10px 5px 10px;
+ color: #000;
+ white-space: pre-wrap;
+
+ &:hover {
+ color: white;
+ background-color: #000000;
+ text-decoration: none;
+ }
+
+ &:hover span {
+ color: white;
+ }
+}
+
+.prequery-image {
+ width: 40px;
+ height: 40px;
+ object-fit: cover;
+ border-radius: 0 !important;
+}
+
.suggestion-heading {
- color: #707070!important
+ color: #707070 !important
}
.view-all-btn {
- color:#000;
+ color: #000;
border-radius: 0px;
- &:hover{
- color:#000;
+
+ &:hover {
+ color: #000;
}
}
.suggestions-section {
color: #707070;
font-size: .9rem;
-}
+}
\ No newline at end of file
diff --git a/packages/catalog-search/src/tests/SearchHeader.test.jsx b/packages/catalog-search/src/tests/SearchHeader.test.jsx
index 41c6e5c9..2c84132f 100644
--- a/packages/catalog-search/src/tests/SearchHeader.test.jsx
+++ b/packages/catalog-search/src/tests/SearchHeader.test.jsx
@@ -19,7 +19,12 @@ jest.mock('../SearchFilters', () => ({
__esModule: true,
default: () =>
Filter
,
}));
-const enterpriseConfig = { slug: 'test-enterprise' };
+const enterpriseConfig = {
+ slug: 'test-enterprise',
+ enterpriseFeatures: {
+ featurePrequerySearchSuggestions: true,
+ },
+};
describe('SearchHeader', () => {
test('displays a SearchBox', () => {
renderWithSearchContext(
);
diff --git a/packages/catalog-search/src/tests/SearchSuggestions.test.jsx b/packages/catalog-search/src/tests/SearchSuggestions.test.jsx
index 1d322c1c..2c94bc48 100644
--- a/packages/catalog-search/src/tests/SearchSuggestions.test.jsx
+++ b/packages/catalog-search/src/tests/SearchSuggestions.test.jsx
@@ -13,6 +13,9 @@ const fakeSuggestionsData = {
key: 'edX+courseX',
title: 'test-course',
_highlightResult: { title: { value: 'test-
course' } },
+ partners: [{
+ name: 'edx-partner',
+ }],
},
{
learning_type: 'program',
@@ -22,6 +25,9 @@ const fakeSuggestionsData = {
aggregation_key: '123:456',
authoring_organizations: [{ key: 'harvard' }],
program_type: 'xSeries',
+ partners: [{
+ name: 'harvard-partner',
+ }],
},
],
};
@@ -74,7 +80,18 @@ describe('
', () => {
expect(screen.getByText('xSeries')).not.toBeNull();
expect(screen.getByText('View all results')).not.toBeNull();
});
-
+ test('renders only prequery suggestions if isPreQueryEnabled is true', () => {
+ renderWithRouter(
);
+ expect(screen.getByText('Top-rated courses')).not.toBeNull();
+ expect(screen.queryByText('Courses')).toBeNull();
+ expect(screen.queryByText('Programs')).toBeNull();
+ });
test('renders no errors when no authoring orgs found for programs data', () => {
renderWithRouter(