From 92efb1aaf97de892e9f2c8e7bcd86af9dc949b4f Mon Sep 17 00:00:00 2001
From: Chris Beer <cabeer@stanford.edu>
Date: Tue, 19 Feb 2019 09:32:18 -0800
Subject: [PATCH] Delay loading unnecessary manifests until they are required
 for rendering e.g. in the add window

---
 __tests__/src/actions/manifest.test.js        |  2 +-
 .../src/components/ManifestListItem.test.js   |  6 ++++
 __tests__/src/reducers/manifests.test.js      |  1 -
 src/components/ManifestListItem.js            | 35 ++++++++++++++++++-
 src/containers/ManifestListItem.js            |  4 ++-
 src/lib/MiradorViewer.js                      |  2 +-
 src/state/actions/manifest.js                 |  3 +-
 src/state/reducers/manifests.js               |  1 -
 8 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/__tests__/src/actions/manifest.test.js b/__tests__/src/actions/manifest.test.js
index 2fba736d9..4cf1fdccf 100644
--- a/__tests__/src/actions/manifest.test.js
+++ b/__tests__/src/actions/manifest.test.js
@@ -45,7 +45,7 @@ describe('manifest actions', () => {
       it('dispatches the REQUEST_MANIFEST action', () => {
         store.dispatch(actions.fetchManifest('https://purl.stanford.edu/sn904cj3429/iiif/manifest'));
         expect(store.getActions()).toEqual([
-          { manifestId: 'https://purl.stanford.edu/sn904cj3429/iiif/manifest', type: 'REQUEST_MANIFEST' },
+          { manifestId: 'https://purl.stanford.edu/sn904cj3429/iiif/manifest', type: 'REQUEST_MANIFEST', properties: { isFetching: true } },
         ]);
       });
       it('dispatches the REQUEST_MANIFEST and then RECEIVE_MANIFEST', () => {
diff --git a/__tests__/src/components/ManifestListItem.test.js b/__tests__/src/components/ManifestListItem.test.js
index 2b698224f..b6084286d 100644
--- a/__tests__/src/components/ManifestListItem.test.js
+++ b/__tests__/src/components/ManifestListItem.test.js
@@ -30,6 +30,12 @@ describe('ManifestListItem', () => {
     expect(wrapper.find('.mirador-manifest-list-item').length).toBe(1);
     expect(wrapper.find('ReactPlaceholder').length).toBe(1);
   });
+  it('renders an error message if fetching the manifest failed', () => {
+    const wrapper = createWrapper({ error: 'This is an error message' });
+
+    expect(wrapper.find('WithStyles(Paper)').length).toBe(1);
+    expect(wrapper.find('WithStyles(Paper)').children().text()).toEqual('This is an error message');
+  });
   it('updates and adds window when button clicked', () => {
     const addWindow = jest.fn();
     const wrapper = createWrapper({ addWindow });
diff --git a/__tests__/src/reducers/manifests.test.js b/__tests__/src/reducers/manifests.test.js
index 3eb3c25c2..21cbe9bc1 100644
--- a/__tests__/src/reducers/manifests.test.js
+++ b/__tests__/src/reducers/manifests.test.js
@@ -9,7 +9,6 @@ describe('manifests reducer', () => {
     })).toEqual({
       abc123: {
         id: 'abc123',
-        isFetching: true,
       },
     });
   });
diff --git a/src/components/ManifestListItem.js b/src/components/ManifestListItem.js
index ffdbce53f..ade9413cd 100644
--- a/src/components/ManifestListItem.js
+++ b/src/components/ManifestListItem.js
@@ -25,10 +25,30 @@ const handleOpenButtonClick = (event, manifest, addWindow) => {
 
 /** */
 class ManifestListItem extends React.Component {
+  /** */
+  componentDidMount() {
+    const {
+      fetchManifest, manifestId, ready, isFetching, error,
+    } = this.props;
+
+    if (!ready && !error && !isFetching) fetchManifest(manifestId);
+  }
+
   /** */
   render() {
     const {
-      manifestId, ready, title, thumbnail, logo, addWindow, handleClose, size, classes, provider, t,
+      manifestId,
+      ready,
+      title,
+      thumbnail,
+      logo,
+      addWindow,
+      handleClose,
+      size,
+      classes,
+      provider,
+      t,
+      error,
     } = this.props;
 
     const placeholder = (
@@ -48,6 +68,14 @@ class ManifestListItem extends React.Component {
       </Grid>
     );
 
+    if (error) {
+      return (
+        <Paper elevation={1} className={classes.root} data-manifestid={manifestId}>
+          {error}
+        </Paper>
+      );
+    }
+
     return (
       <Paper elevation={1} className={classes.root} data-manifestid={manifestId}>
         <ReactPlaceholder
@@ -113,6 +141,9 @@ ManifestListItem.propTypes = {
   classes: PropTypes.object, // eslint-disable-line react/forbid-prop-types
   provider: PropTypes.string,
   t: PropTypes.func,
+  fetchManifest: PropTypes.func.isRequired,
+  error: PropTypes.string,
+  isFetching: PropTypes.bool,
 };
 
 ManifestListItem.defaultProps = {
@@ -125,6 +156,8 @@ ManifestListItem.defaultProps = {
   size: 0,
   provider: null,
   t: key => key,
+  error: null,
+  isFetching: false,
 };
 
 /** */
diff --git a/src/containers/ManifestListItem.js b/src/containers/ManifestListItem.js
index 562f1e3c6..bd49edaf0 100644
--- a/src/containers/ManifestListItem.js
+++ b/src/containers/ManifestListItem.js
@@ -13,6 +13,8 @@ const mapStateToProps = (state, { manifestId }) => {
 
   return {
     ready: !!manifest.manifestation,
+    error: manifest.error,
+    isFetching: manifest.isFetching,
     title: getManifestTitle(manifest),
     logo: getManifestLogo(manifest),
     thumbnail: getManifestThumbnail(manifest),
@@ -26,7 +28,7 @@ const mapStateToProps = (state, { manifestId }) => {
  * @memberof ManifestListItem
  * @private
  */
-const mapDispatchToProps = { addWindow: actions.addWindow };
+const mapDispatchToProps = { addWindow: actions.addWindow, fetchManifest: actions.fetchManifest };
 
 const enhance = compose(
   connect(mapStateToProps, mapDispatchToProps),
diff --git a/src/lib/MiradorViewer.js b/src/lib/MiradorViewer.js
index 0f8826574..30e9b27f9 100644
--- a/src/lib/MiradorViewer.js
+++ b/src/lib/MiradorViewer.js
@@ -66,7 +66,7 @@ class MiradorViewer {
 
     Object.keys(mergedConfig.manifests || {}).forEach((manifestId) => {
       this.store.dispatch(
-        actions.fetchManifest(manifestId, mergedConfig.manifests[manifestId]),
+        actions.requestManifest(manifestId, mergedConfig.manifests[manifestId]),
       );
     });
   }
diff --git a/src/state/actions/manifest.js b/src/state/actions/manifest.js
index 5caf2058f..beda211f0 100644
--- a/src/state/actions/manifest.js
+++ b/src/state/actions/manifest.js
@@ -53,7 +53,8 @@ export function receiveManifestFailure(manifestId, error) {
  */
 export function fetchManifest(manifestId, properties) {
   return ((dispatch) => {
-    dispatch(requestManifest(manifestId, properties));
+    dispatch(requestManifest(manifestId, { ...properties, isFetching: true }));
+
     return fetch(manifestId)
       .then(response => response.json())
       .then(json => dispatch(receiveManifest(manifestId, json)))
diff --git a/src/state/reducers/manifests.js b/src/state/reducers/manifests.js
index 87881bc32..5b1c0ba73 100644
--- a/src/state/reducers/manifests.js
+++ b/src/state/reducers/manifests.js
@@ -13,7 +13,6 @@ export const manifestsReducer = (state = {}, action) => {
           ...state[action.manifestId],
           ...action.properties,
           id: action.manifestId,
-          isFetching: true,
         },
       };
     case ActionTypes.RECEIVE_MANIFEST:
-- 
GitLab