diff --git a/frontend/public/src/components/CourseLoader.js b/frontend/public/src/components/CourseLoader.js
new file mode 100644
index 0000000000..d4fc0320f2
--- /dev/null
+++ b/frontend/public/src/components/CourseLoader.js
@@ -0,0 +1,19 @@
+import React from "react"
+import ContentLoader from "react-content-loader"
+
+const CourseLoader = props => (
+
+
+
+
+
+)
+
+export default CourseLoader
diff --git a/frontend/public/src/containers/pages/CatalogPage.js b/frontend/public/src/containers/pages/CatalogPage.js
index e74b1b80f3..aea0546203 100644
--- a/frontend/public/src/containers/pages/CatalogPage.js
+++ b/frontend/public/src/containers/pages/CatalogPage.js
@@ -28,6 +28,7 @@ import { compose } from "redux"
import { connect } from "react-redux"
import { connectRequest, requestAsync } from "redux-query"
import { pathOr } from "ramda"
+import CourseLoader from "../../components/CourseLoader"
type Props = {
coursesIsLoading: ?boolean,
@@ -297,7 +298,7 @@ export class CatalogPage extends React.Component {
}
/**
- * This is a comparision method used to sort an array of Course Runs
+ * This is a comparison method used to sort an array of Course Runs
* from earliest start date to latest start date.
* @param {BaseCourseRun} courseRunA The first Course Run to compare.
* @param {BaseCourseRun} courseRunB The second Course Run to compare.
@@ -487,17 +488,22 @@ export class CatalogPage extends React.Component {
* Renders the entire catalog of course or program cards based on the catalog tab selected.
*/
renderCatalog() {
+ const { filteredCourses, filteredPrograms, tabSelected } = this.state
+
if (
- this.state.tabSelected === COURSES_TAB &&
- this.state.filteredCourses.length > 0
+ filteredCourses.length === 0 &&
+ (this.props.coursesIsLoading || this.props.programsIsLoading)
) {
+ return courseLoaderGrid
+ }
+ if (tabSelected === COURSES_TAB && filteredCourses.length > 0) {
return this.renderCatalogRows(
- this.state.filteredCourses,
+ filteredCourses,
this.renderCourseCatalogCard.bind(this)
)
- } else if (this.state.tabSelected === PROGRAMS_TAB) {
+ } else if (tabSelected === PROGRAMS_TAB) {
return this.renderCatalogRows(
- this.state.filteredPrograms,
+ filteredPrograms,
this.renderProgramCatalogCard.bind(this)
)
}
@@ -645,16 +651,7 @@ export class CatalogPage extends React.Component {
-
+ {this.state.isLoadingMoreItems ? courseLoaderGrid : null}
{/* span is used to detect when the learner has scrolled to the bottom of the catalog page. */}
@@ -665,6 +662,13 @@ export class CatalogPage extends React.Component {
)
}
}
+const courseLoaderGrid = (
+
+
+
+
+
+)
const getNextCoursePage = page =>
requestAsync({
diff --git a/package.json b/package.json
index 570e813c9c..ab3d150d5f 100644
--- a/package.json
+++ b/package.json
@@ -8,5 +8,8 @@
"build": "yarn workspaces foreach run build"
},
"version": "0.0.0",
- "packageManager": "yarn@3.2.0"
+ "packageManager": "yarn@3.2.0",
+ "dependencies": {
+ "react-content-loader": "^6.2.1"
+ }
}
diff --git a/yarn.lock b/yarn.lock
index e77553834f..b53cf84f52 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -13644,6 +13644,8 @@ __metadata:
"mitx-online-root@workspace:.":
version: 0.0.0-use.local
resolution: "mitx-online-root@workspace:."
+ dependencies:
+ react-content-loader: ^6.2.1
languageName: unknown
linkType: soft
@@ -16829,6 +16831,15 @@ __metadata:
languageName: node
linkType: hard
+"react-content-loader@npm:^6.2.1":
+ version: 6.2.1
+ resolution: "react-content-loader@npm:6.2.1"
+ peerDependencies:
+ react: ">=16.0.0"
+ checksum: f777d408256a4218677e47f4cf3988d9fd8e556450e9b85ee1eb3952a5d5802573cea0df5eaf4dbc936c9522f355657de6f8ab0ecdf035d7dccdef15b45c9dae
+ languageName: node
+ linkType: hard
+
"react-day-picker@npm:7.4.10":
version: 7.4.10
resolution: "react-day-picker@npm:7.4.10"