{
if (isSearchStalled) {
return (
-
-
- {/* eslint-disable */}
- {[...new Array(8)].map((element, index) =>
- )}
- {/* eslint-enable */}
-
-
+
);
}
if (!searchResults) {
@@ -50,7 +40,6 @@ export const BaseReviewContentSelections = ({
}
const { hits } = camelCaseObject(searchResults);
- // eslint-disable-next-line react-hooks/rules-of-hooks
const transformedCardData = hits.map((highlightedContent) => {
const {
aggregationKey, title, cardImageUrl, contentType, partners, originalImageUrl, firstEnrollablePaidSeatPrice,
@@ -67,14 +56,7 @@ export const BaseReviewContentSelections = ({
return original;
});
return (
-
+
{transformedCardData.map((original) => (
))}
@@ -130,11 +112,14 @@ export const SelectedContent = ({ enterpriseId }) => {
filterString += ')';
}
return filterString;
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [currentSelectedRowIds]);
+ }, [currentSelectedRowIds, enterpriseId]);
if (currentSelectedRowIds.length === 0) {
- return ();
+ return (
+
+ {DEFAULT_ERROR_MESSAGE.EMPTY_SELECTEDROWIDS}
+
+ );
}
return (
diff --git a/src/components/ContentHighlights/HighlightStepper/tests/HighlightStepperConfirmContent.test.jsx b/src/components/ContentHighlights/HighlightStepper/tests/HighlightStepperConfirmContent.test.jsx
index 4c90440299..122b0e718f 100644
--- a/src/components/ContentHighlights/HighlightStepper/tests/HighlightStepperConfirmContent.test.jsx
+++ b/src/components/ContentHighlights/HighlightStepper/tests/HighlightStepperConfirmContent.test.jsx
@@ -8,6 +8,7 @@ import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import HighlightStepperConfirmContent, { BaseReviewContentSelections, SelectedContent } from '../HighlightStepperConfirmContent';
import {
+ DEFAULT_ERROR_MESSAGE,
testCourseAggregation,
} from '../../data/constants';
import { ContentHighlightsContext } from '../../ContentHighlightsContext';
@@ -67,7 +68,7 @@ describe('BaseReviewContentSelections', () => {
,
);
- expect(screen.getByTestId('skeleton-container')).toBeInTheDocument();
+ expect(screen.getAllByTestId('card-item-skeleton')).toBeTruthy();
});
it('should render selected card content', () => {
renderWithRouter(
@@ -87,5 +88,6 @@ describe('SelectedContent', () => {
,
);
expect(screen.getByTestId('selected-content-no-results')).toBeInTheDocument();
+ expect(screen.getByText(DEFAULT_ERROR_MESSAGE.EMPTY_SELECTEDROWIDS)).toBeInTheDocument();
});
});
diff --git a/src/components/ContentHighlights/SkeletonContentCard.jsx b/src/components/ContentHighlights/SkeletonContentCard.jsx
index 913555428c..e35a595d75 100644
--- a/src/components/ContentHighlights/SkeletonContentCard.jsx
+++ b/src/components/ContentHighlights/SkeletonContentCard.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import { Card } from '@edx/paragon';
const SkeletonContentCard = () => (
-
+
diff --git a/src/components/ContentHighlights/SkeletonContentCardContainer.jsx b/src/components/ContentHighlights/SkeletonContentCardContainer.jsx
new file mode 100644
index 0000000000..6ed5505c04
--- /dev/null
+++ b/src/components/ContentHighlights/SkeletonContentCardContainer.jsx
@@ -0,0 +1,29 @@
+import PropTypes from 'prop-types';
+import { CardGrid } from '@edx/paragon';
+import SkeletonContentCard from './SkeletonContentCard';
+import { HIGHLIGHTS_CARD_GRID_COLUMN_SIZES } from './data/constants';
+
+const SkeletonContentCardContainer = ({ length, columnSizes }) => (
+
+ {[
+ ...new Array(length),
+ // eslint-disable-next-line react/no-array-index-key
+ ].map((_, index) => )};
+
+);
+
+SkeletonContentCardContainer.propTypes = {
+ length: PropTypes.number.isRequired,
+ columnSizes: PropTypes.shape({
+ xs: PropTypes.number,
+ md: PropTypes.number,
+ lg: PropTypes.number,
+ xl: PropTypes.number,
+ }),
+};
+
+SkeletonContentCardContainer.defaultProps = {
+ columnSizes: HIGHLIGHTS_CARD_GRID_COLUMN_SIZES,
+};
+
+export default SkeletonContentCardContainer;
diff --git a/src/components/ContentHighlights/data/constants.js b/src/components/ContentHighlights/data/constants.js
index d118cd5de8..1d621105b6 100644
--- a/src/components/ContentHighlights/data/constants.js
+++ b/src/components/ContentHighlights/data/constants.js
@@ -1,18 +1,22 @@
/* eslint-disable import/no-extraneous-dependencies */
import { faker } from '@faker-js/faker';
-import { configuration } from '../../../config';
/* eslint-enable import/no-extraneous-dependencies */
-// Generate URLs for about pages from the enterprise learner portal
-export const generateAboutPageUrl = (enterpriseSlug, contentType, contentKey) => {
- const { ENTERPRISE_LEARNER_PORTAL_URL } = configuration;
- const aboutPageBase = `${ENTERPRISE_LEARNER_PORTAL_URL}/${enterpriseSlug}`;
- if (contentType === 'learnerpathway') {
- return `${aboutPageBase}/search/${contentKey}`;
- }
- return `${aboutPageBase}/${contentType}/${contentKey}`;
+// Default Card Grid columnSizes
+export const HIGHLIGHTS_CARD_GRID_COLUMN_SIZES = {
+ xs: 12,
+ md: 6,
+ lg: 4,
+ xl: 3,
};
-
+// Empty Content and Error Messages
+export const DEFAULT_ERROR_MESSAGE = {
+ EMPTY_HIGHLIGHT_SET: 'There is no highlighted content for this highlight collection.',
+ // eslint-disable-next-line quotes
+ EMPTY_SELECTEDROWIDS: `You don't have any highlighted content selected. Go back to the previous step to select content.`,
+};
+// Max highlight sets per enteprise curation
+export const MAX_HIGHLIGHT_SETS_PER_ENTERPRISE_CURATION = 8;
// Max number of content items per highlight set
export const MAX_CONTENT_ITEMS_PER_HIGHLIGHT_SET = 12;
// Max length of highlight title in stepper
@@ -40,15 +44,6 @@ export const FOOTER_TEXT_BY_CONTENT_TYPE = {
learnerpathway: 'Pathway',
};
-// High Card logic for footer text
-export const getContentHighlightCardFooter = (price, contentType) => {
- const formattedContentType = FOOTER_TEXT_BY_CONTENT_TYPE[contentType?.toLowerCase()];
- if (!price) {
- return formattedContentType;
- }
- return `$${price} · ${formattedContentType}`;
-};
-
// Test Data for Content Highlights TODO: Remove when API is available || Remove when feature completed
// Test entepriseId for Content Highlights to display card selections and confirmation
export const testEnterpriseId = 'e783bb19-277f-479e-9c41-8b0ed31b4060';
diff --git a/src/components/ContentHighlights/data/hooks.js b/src/components/ContentHighlights/data/hooks.js
index 67970d3aa2..4131aa9b50 100644
--- a/src/components/ContentHighlights/data/hooks.js
+++ b/src/components/ContentHighlights/data/hooks.js
@@ -101,13 +101,13 @@ export function useContentHighlightsContext() {
}, [setState]);
const deleteSelectedRowId = useCallback((rowId) => {
- const x = getState.stepperModal.currentSelectedRowIds;
- delete x[rowId];
+ const currentRowIds = getState.stepperModal.currentSelectedRowIds;
+ delete currentRowIds[rowId];
setState(s => ({
...s,
stepperModal: {
...s.stepperModal,
- currentSelectedRowIds: x,
+ currentSelectedRowIds: currentRowIds,
},
}));
}, [setState, getState]);
diff --git a/src/components/ContentHighlights/data/utils.js b/src/components/ContentHighlights/data/utils.js
new file mode 100644
index 0000000000..5313002c0d
--- /dev/null
+++ b/src/components/ContentHighlights/data/utils.js
@@ -0,0 +1,20 @@
+import { configuration } from '../../../config';
+import { FOOTER_TEXT_BY_CONTENT_TYPE } from './constants';
+
+// High Card logic for footer text
+export const getContentHighlightCardFooter = ({ price, contentType }) => {
+ const formattedContentType = FOOTER_TEXT_BY_CONTENT_TYPE[contentType?.toLowerCase()];
+ if (!price) {
+ return formattedContentType;
+ }
+ return `$${price} · ${formattedContentType}`;
+};
+// Generate URLs for about pages from the enterprise learner portal
+export function generateAboutPageUrl({ enterpriseSlug, contentType, contentKey }) {
+ const { ENTERPRISE_LEARNER_PORTAL_URL } = configuration;
+ const aboutPageBase = `${ENTERPRISE_LEARNER_PORTAL_URL}/${enterpriseSlug}`;
+ if (contentType === 'learnerpathway') {
+ return `${aboutPageBase}/search/${contentKey}`;
+ }
+ return `${aboutPageBase}/${contentType}/${contentKey}`;
+}
diff --git a/src/components/ContentHighlights/tests/ContentHighlightsCardItemsContainer.test.jsx b/src/components/ContentHighlights/tests/ContentHighlightsCardItemsContainer.test.jsx
index f10b3a8e4e..ae98a1f7b8 100644
--- a/src/components/ContentHighlights/tests/ContentHighlightsCardItemsContainer.test.jsx
+++ b/src/components/ContentHighlights/tests/ContentHighlightsCardItemsContainer.test.jsx
@@ -8,7 +8,7 @@ import { camelCaseObject } from '@edx/frontend-platform';
import { renderWithRouter } from '@edx/frontend-enterprise-utils';
import ContentHighlightsCardItemsContainer from '../ContentHighlightsCardItemsContainer';
-import { TEST_COURSE_HIGHLIGHTS_DATA } from '../data/constants';
+import { DEFAULT_ERROR_MESSAGE, TEST_COURSE_HIGHLIGHTS_DATA } from '../data/constants';
const mockStore = configureMockStore([thunk]);
@@ -66,12 +66,13 @@ describe('', () => {
highlightedContent={[]}
/>);
expect(screen.getByTestId('empty-highlighted-content')).toBeInTheDocument();
+ expect(screen.getByText(DEFAULT_ERROR_MESSAGE.EMPTY_HIGHLIGHT_SET)).toBeInTheDocument();
});
it('Displays Skeleton on load', () => {
renderWithRouter();
- expect(screen.getByTestId('card-item-skeleton')).toBeInTheDocument();
+ expect(screen.getAllByTestId('card-item-skeleton')).toBeTruthy();
});
});