From 53f57cd3cf40449d781fd594503096b15b45b68e Mon Sep 17 00:00:00 2001
From: Chris Beer <cabeer@stanford.edu>
Date: Wed, 13 Mar 2019 16:35:23 -0700
Subject: [PATCH] Hide the canvas navigation controls unless the window is
 focused; fixes #2160

---
 .../WindowCanvasNavigationControls.test.js    | 38 ++++++++++++++++
 __tests__/src/components/WindowViewer.test.js | 10 +----
 .../WindowCanvasNavigationControls.js         | 45 +++++++++++++++++++
 src/components/WindowViewer.js                | 22 ++-------
 .../WindowCanvasNavigationControls.js         | 23 ++++++++++
 src/containers/WindowViewer.js                |  8 ----
 6 files changed, 111 insertions(+), 35 deletions(-)
 create mode 100644 __tests__/src/components/WindowCanvasNavigationControls.test.js
 create mode 100644 src/components/WindowCanvasNavigationControls.js
 create mode 100644 src/containers/WindowCanvasNavigationControls.js

diff --git a/__tests__/src/components/WindowCanvasNavigationControls.test.js b/__tests__/src/components/WindowCanvasNavigationControls.test.js
new file mode 100644
index 000000000..64394bd2e
--- /dev/null
+++ b/__tests__/src/components/WindowCanvasNavigationControls.test.js
@@ -0,0 +1,38 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import Typography from '@material-ui/core/Typography';
+import { WindowCanvasNavigationControls } from '../../../src/components/WindowCanvasNavigationControls';
+import ViewerNavigation from '../../../src/containers/ViewerNavigation';
+import ZoomControls from '../../../src/containers/ZoomControls';
+
+/** create wrapper */
+function createWrapper(props) {
+  return shallow(
+    <WindowCanvasNavigationControls
+      canvases={[]}
+      canvasLabel="label"
+      window={{}}
+      {...props}
+    />,
+  );
+}
+
+describe('WindowCanvasNavigationControls', () => {
+  let wrapper;
+
+  it('renders properly', () => {
+    wrapper = createWrapper();
+    expect(wrapper.matchesElement(
+      <div>
+        <ZoomControls />
+        <ViewerNavigation />
+        <Typography>label</Typography>
+      </div>,
+    )).toBe(true);
+  });
+
+  it('renders nothing when visible=false', () => {
+    wrapper = createWrapper({ visible: false });
+    expect(wrapper.matchesElement(<></>)).toBe(true);
+  });
+});
diff --git a/__tests__/src/components/WindowViewer.test.js b/__tests__/src/components/WindowViewer.test.js
index f3b21fc89..19054e8b1 100644
--- a/__tests__/src/components/WindowViewer.test.js
+++ b/__tests__/src/components/WindowViewer.test.js
@@ -1,11 +1,9 @@
 import React from 'react';
 import { shallow } from 'enzyme';
 import manifesto from 'manifesto.js';
-import Typography from '@material-ui/core/Typography';
 import { WindowViewer } from '../../../src/components/WindowViewer';
 import OSDViewer from '../../../src/containers/OpenSeadragonViewer';
-import ViewerNavigation from '../../../src/containers/ViewerNavigation';
-import ZoomControls from '../../../src/containers/ZoomControls';
+import WindowCanvasNavigationControls from '../../../src/containers/WindowCanvasNavigationControls';
 import fixture from '../../fixtures/version-2/019.json';
 import emptyCanvasFixture from '../../fixtures/version-2/emptyCanvas.json';
 import otherContentFixture from '../../fixtures/version-2/299843.json';
@@ -44,11 +42,7 @@ describe('WindowViewer', () => {
     expect(wrapper.matchesElement(
       <>
         <OSDViewer>
-          <div>
-            <ZoomControls />
-            <ViewerNavigation />
-            <Typography>label</Typography>
-          </div>
+          <WindowCanvasNavigationControls />
         </OSDViewer>
       </>,
     )).toBe(true);
diff --git a/src/components/WindowCanvasNavigationControls.js b/src/components/WindowCanvasNavigationControls.js
new file mode 100644
index 000000000..6044dd780
--- /dev/null
+++ b/src/components/WindowCanvasNavigationControls.js
@@ -0,0 +1,45 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import Typography from '@material-ui/core/Typography';
+import ZoomControls from '../containers/ZoomControls';
+import ViewerNavigation from '../containers/ViewerNavigation';
+import ns from '../config/css-ns';
+
+/**
+ * Represents the viewer controls in the mirador workspace.
+ */
+export class WindowCanvasNavigationControls extends Component {
+  /** */
+  render() {
+    const {
+      canvases, canvasLabel, visible, window,
+    } = this.props;
+
+    if (!visible) return (<></>);
+
+    return (
+      <div className={ns('canvas-nav')}>
+        <ZoomControls windowId={window.id} />
+        <ViewerNavigation window={window} canvases={canvases} />
+        {
+          canvasLabel && (
+            <Typography variant="caption" className={ns('canvas-label')}>{canvasLabel}</Typography>
+          )
+        }
+      </div>
+    );
+  }
+}
+
+
+WindowCanvasNavigationControls.propTypes = {
+  canvases: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
+  window: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
+  canvasLabel: PropTypes.string,
+  visible: PropTypes.bool,
+};
+
+WindowCanvasNavigationControls.defaultProps = {
+  canvasLabel: undefined,
+  visible: true,
+};
diff --git a/src/components/WindowViewer.js b/src/components/WindowViewer.js
index 5fa7b8176..31f81b43f 100644
--- a/src/components/WindowViewer.js
+++ b/src/components/WindowViewer.js
@@ -1,12 +1,9 @@
 import React, { Component } from 'react';
 import PropTypes from 'prop-types';
-import Typography from '@material-ui/core/Typography';
 import OSDViewer from '../containers/OpenSeadragonViewer';
-import ZoomControls from '../containers/ZoomControls';
-import ViewerNavigation from '../containers/ViewerNavigation';
+import WindowCanvasNavigationControls from '../containers/WindowCanvasNavigationControls';
 import ManifestoCanvas from '../lib/ManifestoCanvas';
 import CanvasGroupings from '../lib/CanvasGroupings';
-import ns from '../config/css-ns';
 
 /**
  * Represents a WindowViewer in the mirador workspace. Responsible for mounting
@@ -124,7 +121,7 @@ export class WindowViewer extends Component {
    * Renders things
    */
   render() {
-    const { canvasLabel, window } = this.props;
+    const { window } = this.props;
     return (
       <>
         <OSDViewer
@@ -132,15 +129,7 @@ export class WindowViewer extends Component {
           currentCanvases={this.currentCanvases()}
           windowId={window.id}
         >
-          <div className={ns('canvas-nav')}>
-            <ZoomControls windowId={window.id} />
-            <ViewerNavigation window={window} canvases={this.canvases} />
-            {
-              canvasLabel && (
-                <Typography variant="caption" className={ns('canvas-label')}>{canvasLabel}</Typography>
-              )
-            }
-          </div>
+          <WindowCanvasNavigationControls windowId={window.id} canvases={this.canvases} />
         </OSDViewer>
       </>
     );
@@ -153,9 +142,4 @@ WindowViewer.propTypes = {
   fetchInfoResponse: PropTypes.func.isRequired,
   manifest: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
   window: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
-  canvasLabel: PropTypes.string,
-};
-
-WindowViewer.defaultProps = {
-  canvasLabel: undefined,
 };
diff --git a/src/containers/WindowCanvasNavigationControls.js b/src/containers/WindowCanvasNavigationControls.js
new file mode 100644
index 000000000..c3d5f0315
--- /dev/null
+++ b/src/containers/WindowCanvasNavigationControls.js
@@ -0,0 +1,23 @@
+import { connect } from 'react-redux';
+import { compose } from 'redux';
+import {
+  getCanvasLabel,
+  getSelectedCanvas,
+} from '../state/selectors';
+import { WindowCanvasNavigationControls } from '../components/WindowCanvasNavigationControls';
+
+/** */
+const mapStateToProps = (state, { windowId }) => ({
+  window: state.windows[windowId],
+  canvasLabel: getCanvasLabel(
+    getSelectedCanvas(state, windowId),
+    state.windows[windowId].canvasIndex,
+  ),
+  visible: state.workspace.focusedWindowId === windowId,
+});
+
+const enhance = compose(
+  connect(mapStateToProps),
+);
+
+export default enhance(WindowCanvasNavigationControls);
diff --git a/src/containers/WindowViewer.js b/src/containers/WindowViewer.js
index a6582987d..2086ef72e 100644
--- a/src/containers/WindowViewer.js
+++ b/src/containers/WindowViewer.js
@@ -1,10 +1,6 @@
 import { compose } from 'redux';
 import { connect } from 'react-redux';
 import * as actions from '../state/actions';
-import {
-  getCanvasLabel,
-  getSelectedCanvas,
-} from '../state/selectors';
 import { WindowViewer } from '../components/WindowViewer';
 
 /**
@@ -14,10 +10,6 @@ import { WindowViewer } from '../components/WindowViewer';
  */
 const mapStateToProps = (state, { window }) => (
   {
-    canvasLabel: getCanvasLabel(
-      getSelectedCanvas(state, window.id),
-      state.windows[window.id].canvasIndex,
-    ),
     infoResponses: state.infoResponses,
   }
 );
-- 
GitLab