From 9e69299f079b247951ed26fe412b8dfa802f7e0e Mon Sep 17 00:00:00 2001
From: Jack Reed <phillipjreed@gmail.com>
Date: Wed, 7 Oct 2020 17:01:59 -0600
Subject: [PATCH] Setup collections to open and close the collection selection
 modal

---
 .../integration/mirador/collections.html      | 22 +++---
 .../src/components/PrimaryWindow.test.js      |  7 ++
 src/components/CollectionDialog.js            | 11 ++-
 src/components/PrimaryWindow.js               | 18 ++++-
 src/components/SelectCollection.js            | 67 +++++++++++++++++++
 src/containers/CollectionDialog.js            |  8 ++-
 src/containers/PrimaryWindow.js               | 11 +++
 src/containers/SelectCollection.js            | 36 ++++++++++
 src/locales/en/translation.json               |  1 +
 src/state/actions/workspace.js                |  1 -
 10 files changed, 167 insertions(+), 15 deletions(-)
 create mode 100644 src/components/SelectCollection.js
 create mode 100644 src/containers/SelectCollection.js

diff --git a/__tests__/integration/mirador/collections.html b/__tests__/integration/mirador/collections.html
index 71056abeb..c41b9135a 100644
--- a/__tests__/integration/mirador/collections.html
+++ b/__tests__/integration/mirador/collections.html
@@ -13,16 +13,18 @@
     <script type="text/javascript">
      var miradorInstance = Mirador.viewer({
        id: 'mirador',
-       windows: [{
-         manifestId: 'https://www.e-codices.unifr.ch/metadata/iiif/collection.json'
-       }],
-       // windows: [{
-       //   collectionPath: [
-       //      "https://www.e-codices.unifr.ch/metadata/iiif/collection.json",
-       //      "https://www.e-codices.unifr.ch/metadata/iiif/collection/stabs.json"
-       //    ],
-       //    manifestId: "https://www.e-codices.unifr.ch/metadata/iiif/stabs-StAlban-DD1-1580/manifest.json"
-       // }],
+       windows: [
+         {
+           collectionPath: [
+              "https://www.e-codices.unifr.ch/metadata/iiif/collection.json",
+              "https://www.e-codices.unifr.ch/metadata/iiif/collection/stabs.json"
+            ],
+            manifestId: "https://www.e-codices.unifr.ch/metadata/iiif/stabs-StAlban-DD1-1580/manifest.json"
+         },
+         {
+           manifestId: 'https://www.e-codices.unifr.ch/metadata/iiif/collection.json'
+         }
+       ],
        catalog: [
          { manifestId: "https://www.e-codices.unifr.ch/metadata/iiif/collection.json" },
        ]
diff --git a/__tests__/src/components/PrimaryWindow.test.js b/__tests__/src/components/PrimaryWindow.test.js
index da8de5fbb..5cdcccfe6 100644
--- a/__tests__/src/components/PrimaryWindow.test.js
+++ b/__tests__/src/components/PrimaryWindow.test.js
@@ -4,6 +4,7 @@ import { PrimaryWindow } from '../../../src/components/PrimaryWindow';
 import WindowSideBar from '../../../src/containers/WindowSideBar';
 import WindowViewer from '../../../src/containers/WindowViewer';
 import GalleryView from '../../../src/containers/GalleryView';
+import CollectionDialog from '../../../src/containers/CollectionDialog';
 
 /** create wrapper */
 function createWrapper(props) {
@@ -37,4 +38,10 @@ describe('PrimaryWindow', () => {
     const wrapper = createWrapper({ isFetching: false, view: 'gallery', windowId: 'window-2' });
     expect(wrapper.find(GalleryView)).toHaveLength(1);
   });
+  it('should render <CollectionDialog> and <SelectCollection> if manifest is collection and isCollectionDialogVisible', () => {
+    const wrapper = createWrapper({ isCollection: true, isCollectionDialogVisible: true });
+    const lazyComponent = wrapper.find('lazy');
+    expect(lazyComponent.type().displayName).toBe('SelectCollection');
+    expect(wrapper.find(CollectionDialog)).toHaveLength(1);
+  });
 });
diff --git a/src/components/CollectionDialog.js b/src/components/CollectionDialog.js
index 59730884c..9930997f3 100644
--- a/src/components/CollectionDialog.js
+++ b/src/components/CollectionDialog.js
@@ -102,12 +102,15 @@ export class CollectionDialog extends Component {
 
   /** */
   placeholder() {
-    const { classes, hideCollectionDialog } = this.props;
+    const { classes, containerId, hideCollectionDialog, windowId } = this.props;
 
     return (
       <Dialog
+        className={classes.dialog}
         onClose={hideCollectionDialog}
         open
+        container={document.querySelector(`#${containerId} #${windowId}`)}
+        BackdropProps={{ classes: classes.dialog }}
       >
         <DialogTitle id="select-collection" disableTypography>
           <Skeleton className={classes.placeholder} variant="text" />
@@ -125,12 +128,14 @@ export class CollectionDialog extends Component {
     const {
       classes,
       collection,
+      containerId,
       error,
       hideCollectionDialog,
       isMultipart,
       manifest,
       ready,
       t,
+      windowId,
     } = this.props;
 
     const { filter } = this.state;
@@ -152,7 +157,10 @@ export class CollectionDialog extends Component {
 
     return (
       <Dialog
+        className={classes.dialog}
         onClose={hideCollectionDialog}
+        container={document.querySelector(`#${containerId} #${windowId}`)}
+        BackdropProps={{ classes: { root: classes.dialog }}}
         open
       >
         <DialogTitle id="select-collection" disableTypography>
@@ -260,6 +268,7 @@ CollectionDialog.propTypes = {
 CollectionDialog.defaultProps = {
   collection: null,
   collectionPath: [],
+  containerId: null,
   error: null,
   isMultipart: false,
   ready: false,
diff --git a/src/components/PrimaryWindow.js b/src/components/PrimaryWindow.js
index e96811e9b..d440b9759 100644
--- a/src/components/PrimaryWindow.js
+++ b/src/components/PrimaryWindow.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React, { Component, lazy } from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import WindowSideBar from '../containers/WindowSideBar';
@@ -7,6 +7,9 @@ import GalleryView from '../containers/GalleryView';
 import CompanionArea from '../containers/CompanionArea';
 import ns from '../config/css-ns';
 
+const SelectCollection = lazy(() => import('../containers/SelectCollection'));
+SelectCollection.displayName = 'SelectCollection';
+
 /**
  * WindowMiddleContent - component that renders the "middle" area of the
  * Mirador Window
@@ -18,7 +21,16 @@ export class PrimaryWindow extends Component {
    * @return {(String|null)}
    */
   renderViewer() {
-    const { isFetching, view, windowId } = this.props;
+    const {
+      isCollection, isFetching, view, windowId,
+    } = this.props;
+    if (isCollection) {
+      return (
+        <SelectCollection
+          windowId={windowId}
+        />
+      );
+    }
     if (isFetching === false) {
       if (view === 'gallery') {
         return (
@@ -53,12 +65,14 @@ export class PrimaryWindow extends Component {
 
 PrimaryWindow.propTypes = {
   classes: PropTypes.objectOf(PropTypes.string).isRequired,
+  isCollection: PropTypes.bool,
   isFetching: PropTypes.bool,
   view: PropTypes.string,
   windowId: PropTypes.string.isRequired,
 };
 
 PrimaryWindow.defaultProps = {
+  isCollection: false,
   isFetching: false,
   view: undefined,
 };
diff --git a/src/components/SelectCollection.js b/src/components/SelectCollection.js
new file mode 100644
index 000000000..decfdf6de
--- /dev/null
+++ b/src/components/SelectCollection.js
@@ -0,0 +1,67 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import Button from '@material-ui/core/Button';
+import Grid from '@material-ui/core/Grid';
+import Typography from '@material-ui/core/Typography';
+import ListSharpIcon from '@material-ui/icons/ListSharp';
+
+/**
+ *
+ */
+export class SelectCollection extends Component {
+  /** */
+  constructor(props) {
+    super(props);
+
+    this.openCollectionDialog = this.openCollectionDialog.bind(this);
+  }
+
+  /** */
+  openCollectionDialog() {
+    const {
+      collectionPath, manifestId, showCollectionDialog, windowId,
+    } = this.props;
+    showCollectionDialog(manifestId, collectionPath.slice(0, -1), windowId);
+  }
+
+  /** */
+  render() {
+    const {
+      t,
+    } = this.props;
+    return (
+      <Grid container justify="center" alignItems="center">
+        <Grid container direction="column" alignItems="center">
+          <Typography variant="h4" paragraph>
+            <em>
+              {t('noItemSelected')}
+            </em>
+          </Typography>
+          <Button
+            color="primary"
+            variant="contained"
+            onClick={this.openCollectionDialog}
+            startIcon={<ListSharpIcon />}
+          >
+            {t('showCollection')}
+          </Button>
+        </Grid>
+      </Grid>
+    );
+  }
+}
+
+SelectCollection.propTypes = {
+  collectionPath: PropTypes.arrayOf(PropTypes.string),
+  manifestId: PropTypes.string,
+  showCollectionDialog: PropTypes.func.isRequired,
+  t: PropTypes.func,
+  windowId: PropTypes.string,
+};
+
+SelectCollection.defaultProps = {
+  collectionPath: [],
+  manifestId: null,
+  t: () => {},
+  windowId: null,
+};
diff --git a/src/containers/CollectionDialog.js b/src/containers/CollectionDialog.js
index 8c1f687ed..325640145 100644
--- a/src/containers/CollectionDialog.js
+++ b/src/containers/CollectionDialog.js
@@ -4,7 +4,9 @@ import { withStyles } from '@material-ui/core';
 import { withTranslation } from 'react-i18next';
 import { withPlugins } from '../extend/withPlugins';
 import * as actions from '../state/actions';
-import { getManifest, getManifestoInstance, getSequenceBehaviors } from '../state/selectors';
+import {
+  getContainerId, getManifest, getManifestoInstance, getSequenceBehaviors,
+} from '../state/selectors';
 import { CollectionDialog } from '../components/CollectionDialog';
 
 /**
@@ -35,6 +37,7 @@ const mapStateToProps = (state) => {
   return {
     collection: collection && getManifestoInstance(state, { manifestId: collection.id }),
     collectionPath,
+    containerId: getContainerId(state),
     error: manifest && manifest.error,
     isMultipart: getSequenceBehaviors(state, { manifestId }).includes('multi-part'),
     manifest: manifest && getManifestoInstance(state, { manifestId }),
@@ -57,6 +60,9 @@ const styles = theme => ({
   dark: {
     color: '#000000',
   },
+  dialog: {
+    position: 'absolute !important',
+  },
   dialogContent: {
     padding: 0,
   },
diff --git a/src/containers/PrimaryWindow.js b/src/containers/PrimaryWindow.js
index 4c90a1294..50332d7c8 100644
--- a/src/containers/PrimaryWindow.js
+++ b/src/containers/PrimaryWindow.js
@@ -1,8 +1,18 @@
 import { compose } from 'redux';
+import { connect } from 'react-redux';
 import { withStyles } from '@material-ui/core/styles';
 import { withPlugins } from '../extend/withPlugins';
+import { getManifestoInstance } from '../state/selectors';
 import { PrimaryWindow } from '../components/PrimaryWindow';
 
+/** */
+const mapStateToProps = (state, { windowId }) => {
+  const manifestoInstance = getManifestoInstance(state, { windowId });
+  return {
+    isCollection: manifestoInstance && manifestoInstance.isCollection(),
+  };
+};
+
 const styles = {
   primaryWindow: {
     display: 'flex',
@@ -13,6 +23,7 @@ const styles = {
 
 const enhance = compose(
   withStyles(styles),
+  connect(mapStateToProps),
   withPlugins('PrimaryWindow'),
 );
 
diff --git a/src/containers/SelectCollection.js b/src/containers/SelectCollection.js
new file mode 100644
index 000000000..446c32711
--- /dev/null
+++ b/src/containers/SelectCollection.js
@@ -0,0 +1,36 @@
+import { compose } from 'redux';
+import { connect } from 'react-redux';
+import { withTranslation } from 'react-i18next';
+import { withStyles } from '@material-ui/core/styles';
+import * as actions from '../state/actions';
+import { withPlugins } from '../extend/withPlugins';
+import {
+  getWindow,
+} from '../state/selectors';
+import { SelectCollection } from '../components/SelectCollection';
+
+/** */
+const mapStateToProps = (state, { windowId }) => {
+  const { collectionPath, manifestId } = (getWindow(state, { windowId }) || {});
+
+  return {
+    collectionPath,
+    manifestId,
+  };
+};
+
+const mapDispatchToProps = {
+  showCollectionDialog: actions.showCollectionDialog,
+};
+/** */
+const styles = (theme) => ({
+});
+
+const enhance = compose(
+  withTranslation(),
+  withStyles(styles),
+  connect(mapStateToProps, mapDispatchToProps),
+  withPlugins('SelectCollection'),
+);
+
+export default enhance(SelectCollection);
diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json
index 8c0756f50..c6c0ef9d2 100644
--- a/src/locales/en/translation.json
+++ b/src/locales/en/translation.json
@@ -90,6 +90,7 @@
     "moveCompanionWindowToBottom": "Move to bottom",
     "moveCompanionWindowToRight": "Move to right",
     "nextCanvas": "Next item",
+    "noItemSelected": "No item selected",
     "numItems": "{{number}} items",
     "off": "Off",
     "openCompanionWindow_annotations": "Annotations",
diff --git a/src/state/actions/workspace.js b/src/state/actions/workspace.js
index 47740062c..29c52e0f1 100644
--- a/src/state/actions/workspace.js
+++ b/src/state/actions/workspace.js
@@ -95,7 +95,6 @@ export function toggleDraggingEnabled() {
 
 /** */
 export function showCollectionDialog(manifestId, collectionPath = [], windowId = null) {
-  console.log(manifestId, collectionPath);
   return {
     collectionPath,
     manifestId,
-- 
GitLab