From f057e3b08ddedaae8d73add33e7359523d513048 Mon Sep 17 00:00:00 2001 From: Chris Beer Date: Tue, 28 Mar 2023 09:37:50 -0700 Subject: [PATCH] Use context to pass the windowId prop around --- .../components/CompanionWindowFactory.test.js | 3 +- __tests__/src/components/GalleryView.test.js | 2 +- .../src/components/PrimaryWindow.test.js | 11 +-- .../src/components/SearchResults.test.js | 1 + .../src/components/WindowSideBar.test.js | 2 +- .../WindowSideBarAnnotationsPanel.test.js | 3 +- __tests__/utils/test-utils.js | 20 ++++-- src/components/AnnotationSettings.js | 1 - src/components/AttributionPanel.js | 3 - src/components/CompanionArea.js | 2 +- src/components/CompanionWindowFactory.js | 10 ++- src/components/CustomPanel.js | 4 +- src/components/GalleryView.js | 5 +- src/components/IIIFAuthentication.js | 1 - src/components/LayersPanel.js | 5 +- src/components/OpenSeadragonViewer.js | 2 +- src/components/PrimaryWindow.js | 33 +++------ src/components/SearchPanel.js | 7 +- src/components/SearchPanelControls.js | 2 +- src/components/SearchPanelNavigation.js | 1 - src/components/SearchResults.js | 4 -- src/components/ThumbnailNavigation.js | 4 +- src/components/Window.js | 33 +++++---- .../WindowCanvasNavigationControls.js | 13 ++-- src/components/WindowSideBar.js | 5 +- .../WindowSideBarAnnotationsPanel.js | 7 +- src/components/WindowSideBarCanvasPanel.js | 5 -- .../WindowSideBarCollectionPanel.js | 3 - src/components/WindowSideBarInfoPanel.js | 10 +-- src/components/WindowTopBar.js | 13 ++-- src/components/WindowTopMenu.js | 7 +- src/components/WindowTopMenuButton.js | 8 +-- src/components/WindowViewer.js | 13 +--- src/containers/AnnotationSettings.js | 2 + src/containers/AnnotationsOverlay.js | 2 + src/containers/AttributionPanel.js | 2 + src/containers/AudioViewer.js | 2 + src/containers/CanvasAnnotations.js | 2 + src/containers/CanvasInfo.js | 2 + src/containers/CanvasLayers.js | 2 + src/containers/CollectionDialog.js | 2 + src/containers/CollectionInfo.js | 2 + src/containers/CompanionArea.js | 2 + src/containers/CompanionWindow.js | 2 + src/containers/CustomPanel.js | 2 + src/containers/ErrorContent.js | 2 + src/containers/GalleryView.js | 2 + src/containers/GalleryViewThumbnail.js | 2 + src/containers/IIIFAuthentication.js | 2 + src/containers/LayersPanel.js | 2 + src/containers/ManifestInfo.js | 2 + src/containers/ManifestRelatedLinks.js | 2 + src/containers/MinimalWindow.js | 2 + src/containers/OpenSeadragonViewer.js | 2 + src/containers/PrimaryWindow.js | 2 + src/containers/SearchHit.js | 2 + src/containers/SearchPanel.js | 2 + src/containers/SearchPanelControls.js | 2 + src/containers/SearchPanelNavigation.js | 2 + src/containers/SearchResults.js | 2 + src/containers/SelectCollection.js | 2 + src/containers/SidebarIndexList.js | 2 + src/containers/SidebarIndexTableOfContents.js | 2 + src/containers/ThumbnailCanvasGrouping.js | 10 +-- src/containers/ThumbnailNavigation.js | 2 + src/containers/VideoViewer.js | 2 + src/containers/ViewerInfo.js | 2 + src/containers/ViewerNavigation.js | 2 + src/containers/WindowAuthenticationBar.js | 2 + .../WindowCanvasNavigationControls.js | 2 + src/containers/WindowSideBar.js | 2 + .../WindowSideBarAnnotationsPanel.js | 2 + src/containers/WindowSideBarButtons.js | 2 + src/containers/WindowSideBarCanvasPanel.js | 2 + .../WindowSideBarCollectionPanel.js | 2 + src/containers/WindowSideBarInfoPanel.js | 2 + src/containers/WindowThumbnailSettings.js | 2 + src/containers/WindowTopBar.js | 2 + src/containers/WindowTopBarPluginArea.js | 4 +- src/containers/WindowTopBarPluginMenu.js | 2 + src/containers/WindowTopBarTitle.js | 2 + src/containers/WindowTopMenu.js | 2 + src/containers/WindowTopMenuButton.js | 2 + src/containers/WindowViewSettings.js | 2 + src/containers/WindowViewer.js | 2 + src/containers/ZoomControls.js | 2 + src/contexts/WindowContext.js | 71 +++++++++++++++++++ 87 files changed, 271 insertions(+), 159 deletions(-) create mode 100644 src/contexts/WindowContext.js diff --git a/__tests__/src/components/CompanionWindowFactory.test.js b/__tests__/src/components/CompanionWindowFactory.test.js index 1d25c8970d..036783d4c6 100644 --- a/__tests__/src/components/CompanionWindowFactory.test.js +++ b/__tests__/src/components/CompanionWindowFactory.test.js @@ -6,12 +6,11 @@ import { CompanionWindowFactory } from '../../../src/components/CompanionWindowF function createWrapper({ content = 'closed', ...props }) { return render( , - { preloadedState: { companionWindows: { 123: { content }, thumb: {} }, windows: { x: { thumbnailNavigationId: 'thumb' } } } }, + { preloadedState: { companionWindows: { 123: { content }, thumb: {} }, windows: { x: { thumbnailNavigationId: 'thumb' } } }, windowId: 'x' }, ); } diff --git a/__tests__/src/components/GalleryView.test.js b/__tests__/src/components/GalleryView.test.js index 852f216de3..c436eb19f4 100644 --- a/__tests__/src/components/GalleryView.test.js +++ b/__tests__/src/components/GalleryView.test.js @@ -9,10 +9,10 @@ function createWrapper(props) { return render( , + { windowId: '1234' }, ); } diff --git a/__tests__/src/components/PrimaryWindow.test.js b/__tests__/src/components/PrimaryWindow.test.js index 15c636988d..726b4b12ca 100644 --- a/__tests__/src/components/PrimaryWindow.test.js +++ b/__tests__/src/components/PrimaryWindow.test.js @@ -6,10 +6,9 @@ function createWrapper(props) { return render( , - { preloadedState: { windows: { xyz: { collectionPath: [{}], companionWindowIds: [] } } } }, + { preloadedState: { windows: { xyz: { collectionPath: [{}], companionWindowIds: [] } } }, windowId: 'xyz' }, ); } @@ -30,10 +29,7 @@ describe('PrimaryWindow', () => { }); it('should render if fetching is complete and view is gallery', async () => { createWrapper({ isFetching: false, view: 'gallery' }); - await screen.findByTestId('test-window'); - await waitFor(() => { - expect(document.querySelector('#xyz-gallery')).toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access - }); + expect(await screen.findByRole('region', { accessibleName: 'gallery section' })).toBeInTheDocument(); }); it('should render and if manifest is collection and isCollectionDialogVisible', async () => { render(
); @@ -42,9 +38,8 @@ describe('PrimaryWindow', () => { classes={{}} isCollection isCollectionDialogVisible - windowId="xyz" />, - { preloadedState: { windows: { xyz: { collectionPath: [{}] } } } }, + { preloadedState: { windows: { xyz: { collectionPath: [{}] } } }, windowId: 'xyz' }, ); await screen.findByRole('button', { accessibleName: 'show collection' }); }); diff --git a/__tests__/src/components/SearchResults.test.js b/__tests__/src/components/SearchResults.test.js index c9ffce0af3..4e1526d79c 100644 --- a/__tests__/src/components/SearchResults.test.js +++ b/__tests__/src/components/SearchResults.test.js @@ -64,6 +64,7 @@ function createWrapper(props) { window: {}, }, }, + windowId: 'window', }, ); } diff --git a/__tests__/src/components/WindowSideBar.test.js b/__tests__/src/components/WindowSideBar.test.js index e8e1db11b4..e1474e77f1 100644 --- a/__tests__/src/components/WindowSideBar.test.js +++ b/__tests__/src/components/WindowSideBar.test.js @@ -5,7 +5,6 @@ import { WindowSideBar } from '../../../src/components/WindowSideBar'; function createWrapper({ ...props }) { return render( , { @@ -17,6 +16,7 @@ function createWrapper({ ...props }) { }, }, }, + windowId: 'xyz', }, ); } diff --git a/__tests__/src/components/WindowSideBarAnnotationsPanel.test.js b/__tests__/src/components/WindowSideBarAnnotationsPanel.test.js index 0f67d2ea1c..4e7756dca9 100644 --- a/__tests__/src/components/WindowSideBarAnnotationsPanel.test.js +++ b/__tests__/src/components/WindowSideBarAnnotationsPanel.test.js @@ -9,10 +9,9 @@ function createWrapper(props, state) { annotationCount={4} classes={{}} id="xyz" - windowId="abc" {...props} />, - { preloadedState: { companionWindows: { xyz: { content: 'annotations' } }, windows: { abc: {} }, ...state } }, + { preloadedState: { companionWindows: { xyz: { content: 'annotations' } }, windows: { abc: {} }, ...state }, windowId: 'abc' }, ); } diff --git a/__tests__/utils/test-utils.js b/__tests__/utils/test-utils.js index e084208905..43f4ebb790 100644 --- a/__tests__/utils/test-utils.js +++ b/__tests__/utils/test-utils.js @@ -8,6 +8,7 @@ import { I18nextProvider } from 'react-i18next'; import createRootReducer from '../../src/state/reducers/rootReducer'; import settings from '../../src/config/settings'; import createI18nInstance from '../../src/i18n'; +import WindowContext from '../../src/contexts/WindowContext'; /** Mirador viewer setup for Integration tests */ import Mirador from '../../src/index'; @@ -29,19 +30,24 @@ function renderWithProviders( preloadedState = {}, // Automatically create a store instance if no store was passed in store = createStore(rootReducer, preloadedState, applyMiddleware(thunk)), + windowId, ...renderOptions } = {}, ) { + const windowContext = windowId ? { id: windowId } : {}; + /** :nodoc: */ function Wrapper({ children }) { return ( - - - - {children} - - - + + + + + {children} + + + + ); } diff --git a/src/components/AnnotationSettings.js b/src/components/AnnotationSettings.js index 8604a2f17d..2f2ed59682 100644 --- a/src/components/AnnotationSettings.js +++ b/src/components/AnnotationSettings.js @@ -28,5 +28,4 @@ AnnotationSettings.propTypes = { displayAll: PropTypes.bool.isRequired, displayAllDisabled: PropTypes.bool.isRequired, toggleAnnotationDisplay: PropTypes.func.isRequired, - windowId: PropTypes.string.isRequired, // eslint-disable-line react/no-unused-prop-types }; diff --git a/src/components/AttributionPanel.js b/src/components/AttributionPanel.js index ce662d79b3..3537757815 100644 --- a/src/components/AttributionPanel.js +++ b/src/components/AttributionPanel.js @@ -26,7 +26,6 @@ export function AttributionPanel({ manifestLogo = null, requiredStatement = null, rights = null, - windowId, id, }) { const { t } = useTranslation(); @@ -37,7 +36,6 @@ export function AttributionPanel({ @@ -86,5 +84,4 @@ AttributionPanel.propTypes = { value: PropTypes.string, })), rights: PropTypes.arrayOf(PropTypes.string), - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/CompanionArea.js b/src/components/CompanionArea.js index 35e17b4d49..c664be1bbb 100644 --- a/src/components/CompanionArea.js +++ b/src/components/CompanionArea.js @@ -97,7 +97,7 @@ export function CompanionArea({ className={`${ns('companion-windows')}`} > {companionWindowIds.map((id) => ( - + ))} diff --git a/src/components/CompanionWindowFactory.js b/src/components/CompanionWindowFactory.js index b3511dabd9..a09aea0f48 100644 --- a/src/components/CompanionWindowFactory.js +++ b/src/components/CompanionWindowFactory.js @@ -10,18 +10,17 @@ import ErrorContent from '../containers/ErrorContent'; * Render a companion window using the appropriate component for the content */ export function CompanionWindowFactory({ - content = null, id, windowId, + content = null, id, }) { const { t } = useTranslation(); const ErroredCompanionWindow = useCallback(({ error }) => ( - + - ), [windowId, t, id]); + ), [t, id]); const DynamicCompanionWindowType = CompanionWindowRegistry[content]; @@ -29,7 +28,7 @@ export function CompanionWindowFactory({ return ( - + ); } @@ -37,5 +36,4 @@ export function CompanionWindowFactory({ CompanionWindowFactory.propTypes = { content: PropTypes.string, id: PropTypes.string.isRequired, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/CustomPanel.js b/src/components/CustomPanel.js index 62378958a0..6107bf8892 100644 --- a/src/components/CustomPanel.js +++ b/src/components/CustomPanel.js @@ -6,14 +6,13 @@ import CompanionWindow from '../containers/CompanionWindow'; * a custom panel that can be used for anything */ export function CustomPanel({ - id, children = null, title, windowId, + id, children = null, title, }) { const { t } = useTranslation(); return ( {children} @@ -24,5 +23,4 @@ CustomPanel.propTypes = { children: PropTypes.node, id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/GalleryView.js b/src/components/GalleryView.js index 0896966f96..37bee0710c 100644 --- a/src/components/GalleryView.js +++ b/src/components/GalleryView.js @@ -17,7 +17,7 @@ const Root = styled(Paper, { name: 'GalleryView', slot: 'root' })(({ theme }) => /** * Renders a GalleryView overview of the manifest. */ -export function GalleryView({ canvases, viewingDirection = '', windowId }) { +export function GalleryView({ canvases, viewingDirection = '' }) { const htmlDir = viewingDirection === 'right-to-left' ? 'rtl' : 'ltr'; return ( { canvases.map(canvas => ( )) @@ -44,5 +42,4 @@ export function GalleryView({ canvases, viewingDirection = '', windowId }) { GalleryView.propTypes = { canvases: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types viewingDirection: PropTypes.string, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/IIIFAuthentication.js b/src/components/IIIFAuthentication.js index b680592cb5..1a9b67fd55 100644 --- a/src/components/IIIFAuthentication.js +++ b/src/components/IIIFAuthentication.js @@ -26,7 +26,6 @@ export function IIIFAuthentication({ authServiceId, hasLogoutService: !!logoutServiceId, status, - windowId, }); /** handle the IIIF logout workflow */ diff --git a/src/components/LayersPanel.js b/src/components/LayersPanel.js index f2638236a6..b47c98fbbf 100644 --- a/src/components/LayersPanel.js +++ b/src/components/LayersPanel.js @@ -7,14 +7,13 @@ import CanvasLayers from '../containers/CanvasLayers'; * a panel showing the canvases for a given manifest */ export function LayersPanel({ - canvasIds = [], id, windowId, + canvasIds = [], id, }) { const { t } = useTranslation(); return ( {canvasIds.map((canvasId, index) => ( ))} @@ -32,5 +30,4 @@ export function LayersPanel({ LayersPanel.propTypes = { canvasIds: PropTypes.arrayOf(PropTypes.string), id: PropTypes.string.isRequired, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/OpenSeadragonViewer.js b/src/components/OpenSeadragonViewer.js index 0e7d7fd3d1..65386b9f73 100644 --- a/src/components/OpenSeadragonViewer.js +++ b/src/components/OpenSeadragonViewer.js @@ -135,7 +135,7 @@ export function OpenSeadragonViewer({ ); })} { drawAnnotations - && } + && } { enhancedChildren } diff --git a/src/components/PrimaryWindow.js b/src/components/PrimaryWindow.js index c89fe1f4b7..9ac8596ed9 100644 --- a/src/components/PrimaryWindow.js +++ b/src/components/PrimaryWindow.js @@ -26,41 +26,31 @@ const Root = styled('div', { name: 'PrimaryWindow', slot: 'root' })(() => ({ /** */ const TypeSpecificViewer = ({ audioResources = [], isCollection = false, - isFetching = false, videoResources = [], view = undefined, windowId, + isFetching = false, videoResources = [], view = undefined, }) => { if (isCollection) { return ( - + ); } if (isFetching === false) { if (view === 'gallery') { return ( - + ); } if (videoResources.length > 0) { return ( - + ); } if (audioResources.length > 0) { return ( - + ); } return ( - + ); } return null; @@ -72,7 +62,6 @@ TypeSpecificViewer.propTypes = { isFetching: PropTypes.bool, videoResources: PropTypes.arrayOf(PropTypes.object), // eslint-disable-line react/forbid-prop-types view: PropTypes.string, - windowId: PropTypes.string.isRequired, }; /** @@ -81,7 +70,7 @@ TypeSpecificViewer.propTypes = { */ export function PrimaryWindow({ audioResources = undefined, isCollection = false, isFetching = false, videoResources = undefined, - view = undefined, windowId, isCollectionDialogVisible = false, children = null, className = undefined, + view = undefined, isCollectionDialogVisible = false, children = null, className = undefined, }) { const viewerProps = { audioResources, @@ -89,14 +78,13 @@ export function PrimaryWindow({ isFetching, videoResources, view, - windowId, }; return ( - - - { isCollectionDialogVisible && } + + + { isCollectionDialogVisible && } }> {children || } @@ -113,5 +101,4 @@ PrimaryWindow.propTypes = { isFetching: PropTypes.bool, videoResources: PropTypes.arrayOf(PropTypes.object), // eslint-disable-line react/forbid-prop-types view: PropTypes.string, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/SearchPanel.js b/src/components/SearchPanel.js index 8ea3775f47..53472733f5 100644 --- a/src/components/SearchPanel.js +++ b/src/components/SearchPanel.js @@ -10,7 +10,7 @@ import SearchResults from '../containers/SearchResults'; /** */ export function SearchPanel({ - fetchSearch = undefined, id, query = '', removeSearch, searchService, suggestedSearches = [], windowId, + fetchSearch = undefined, id, query = '', removeSearch, searchService, suggestedSearches = [], }) { const { t } = useTranslation(); const containerRef = useRef(null); @@ -38,15 +38,13 @@ export function SearchPanel({ } )} - windowId={windowId} id={id} - titleControls={} + titleControls={} ref={containerRef} > { fetchSearch && suggestedSearches && query === '' && suggestedSearches.map(search => ( @@ -74,5 +72,4 @@ SearchPanel.propTypes = { id: PropTypes.string, }).isRequired, suggestedSearches: PropTypes.arrayOf(PropTypes.string), - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/SearchPanelControls.js b/src/components/SearchPanelControls.js index 6c1e0d777c..547ff653a6 100644 --- a/src/components/SearchPanelControls.js +++ b/src/components/SearchPanelControls.js @@ -145,7 +145,7 @@ export function SearchPanelControls({ )} /> - + ); } diff --git a/src/components/SearchPanelNavigation.js b/src/components/SearchPanelNavigation.js index dda62b236e..77a6283e68 100644 --- a/src/components/SearchPanelNavigation.js +++ b/src/components/SearchPanelNavigation.js @@ -79,5 +79,4 @@ SearchPanelNavigation.propTypes = { }).isRequired, selectAnnotation: PropTypes.func.isRequired, selectedContentSearchAnnotation: PropTypes.arrayOf(PropTypes.string).isRequired, - windowId: PropTypes.string.isRequired, // eslint-disable-line react/no-unused-prop-types }; diff --git a/src/components/SearchResults.js b/src/components/SearchResults.js index ec2b903447..5826f05a8c 100644 --- a/src/components/SearchResults.js +++ b/src/components/SearchResults.js @@ -18,7 +18,6 @@ function SearchHitsAndAnnotations({ containerRef, searchAnnotations, searchHits, - windowId, focused, toggleFocus, }) { @@ -33,7 +32,6 @@ function SearchHitsAndAnnotations({ focused={focused} index={index} total={searchAnnotations.length} - windowId={windowId} showDetails={toggleFocus} /> )); @@ -49,7 +47,6 @@ function SearchHitsAndAnnotations({ hit={hit} index={index} total={searchHits.length} - windowId={windowId} showDetails={toggleFocus} /> )); @@ -105,7 +102,6 @@ export function SearchResults({ containerRef={containerRef} searchAnnotations={searchAnnotations} searchHits={searchHits} - windowId={windowId} focused={focused} toggleFocus={toggleFocus} /> diff --git a/src/components/ThumbnailNavigation.js b/src/components/ThumbnailNavigation.js index 8bf4445129..fe68c9531e 100644 --- a/src/components/ThumbnailNavigation.js +++ b/src/components/ThumbnailNavigation.js @@ -12,7 +12,7 @@ import ns from '../config/css-ns'; */ export function ThumbnailNavigation({ canvasGroupings, canvasIndex, hasNextCanvas = false, hasPreviousCanvas = false, position, - setNextCanvas = () => {}, setPreviousCanvas = () => {}, thumbnailNavigation, view = undefined, viewingDirection = '', windowId, + setNextCanvas = () => {}, setPreviousCanvas = () => {}, thumbnailNavigation, view = undefined, viewingDirection = '', }) { const { t } = useTranslation(); const scrollbarSize = 15; @@ -145,7 +145,6 @@ export function ThumbnailNavigation({ canvasGroupings, height: thumbnailNavigation.height - spacing - scrollbarSize, position, - windowId, }; return ( { ); }; +/** a minimal window for displaying an error message */ +const ErrorWindow = ({ error }) => ( + + + +); + +ErrorWindow.propTypes = { + error: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types +}; + /** * Represents a Window in the mirador workspace * @param {object} window @@ -87,11 +99,6 @@ export function Window({ }) { const { t } = useTranslation(); const ownerState = arguments[0]; // eslint-disable-line prefer-rest-params - const ErrorWindow = useCallback(({ error }) => ( - - - - ), [windowId]); return ( @@ -99,34 +106,32 @@ export function Window({ onFocus={focusWindow} ownerState={ownerState} component="section" - elevation={1} id={windowId} + elevation={1} className={ns('window')} aria-label={t('window', { label })} > - - { manifestError && } + + { manifestError && } - + - - + + - + diff --git a/src/components/WindowCanvasNavigationControls.js b/src/components/WindowCanvasNavigationControls.js index a6b0a97217..f03a27e4bb 100644 --- a/src/components/WindowCanvasNavigationControls.js +++ b/src/components/WindowCanvasNavigationControls.js @@ -34,19 +34,19 @@ const Root = styled(Paper, { name: 'WindowCanvasNavigationControls', slot: 'root * Represents the viewer controls in the mirador workspace. */ export const WindowCanvasNavigationControls = forwardRef(({ - showZoomControls = false, visible = true, windowId, zoomToWorld, ...rest + showZoomControls = false, visible = true, zoomToWorld, ...rest }, ref) => { const [sizeRef, size] = useElementSize(); const pluginProps = { - showZoomControls, size, visible, windowId, ...rest, + showZoomControls, size, visible, ...rest, }; /** * Determine if canvasNavControls are stacked (based on a hard-coded width) */ const canvasNavControlsAreStacked = (size && size.width && size.width <= 253); - if (!visible) return (); + if (!visible) return (); return ( } spacing={0} > - { showZoomControls && } - + { showZoomControls && } + - + @@ -79,7 +79,6 @@ WindowCanvasNavigationControls.propTypes = { showZoomControls: PropTypes.bool, size: PropTypes.shape({ width: PropTypes.number }).isRequired, visible: PropTypes.bool, - windowId: PropTypes.string.isRequired, zoomToWorld: PropTypes.func.isRequired, }; diff --git a/src/components/WindowSideBar.js b/src/components/WindowSideBar.js index 041b23c1c2..0e1f418760 100644 --- a/src/components/WindowSideBar.js +++ b/src/components/WindowSideBar.js @@ -19,7 +19,7 @@ const Nav = styled('nav', { name: 'WindowSideBar', slot: 'nav' })({ * WindowSideBar */ export function WindowSideBar({ - classes = {}, direction, windowId, sideBarOpen = false, + classes = {}, direction, sideBarOpen = false, }) { const { t } = useTranslation(); return ( @@ -35,7 +35,7 @@ export function WindowSideBar({ SlideProps={{ direction: direction === 'rtl' ? 'left' : 'right', mountOnEnter: true, unmountOnExit: true }} open={sideBarOpen} > - + ); } @@ -44,5 +44,4 @@ WindowSideBar.propTypes = { classes: PropTypes.objectOf(PropTypes.string), direction: PropTypes.string.isRequired, sideBarOpen: PropTypes.bool, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/WindowSideBarAnnotationsPanel.js b/src/components/WindowSideBarAnnotationsPanel.js index c22f069eae..5219839c17 100644 --- a/src/components/WindowSideBarAnnotationsPanel.js +++ b/src/components/WindowSideBarAnnotationsPanel.js @@ -12,7 +12,7 @@ import ns from '../config/css-ns'; * WindowSideBarAnnotationsPanel ~ */ export function WindowSideBarAnnotationsPanel({ - annotationCount, canvasIds = [], windowId, id, + annotationCount, canvasIds = [], id, }) { const { t } = useTranslation(); const containerRef = createRef(); @@ -20,10 +20,9 @@ export function WindowSideBarAnnotationsPanel({ } + titleControls={} > {t('showingNumAnnotations', { count: annotationCount, number: annotationCount })} @@ -36,7 +35,6 @@ export function WindowSideBarAnnotationsPanel({ key={canvasId} index={index} totalSize={canvasIds.length} - windowId={windowId} /> ))} @@ -47,5 +45,4 @@ WindowSideBarAnnotationsPanel.propTypes = { annotationCount: PropTypes.number.isRequired, canvasIds: PropTypes.arrayOf(PropTypes.string), id: PropTypes.string.isRequired, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/WindowSideBarCanvasPanel.js b/src/components/WindowSideBarCanvasPanel.js index 59953f2275..5e9bf8e6b6 100644 --- a/src/components/WindowSideBarCanvasPanel.js +++ b/src/components/WindowSideBarCanvasPanel.js @@ -45,7 +45,6 @@ export function WindowSideBarCanvasPanel({ showToc = false, updateSequence, updateVariant, - windowId, }) { const { t } = useTranslation(); const containerRef = useRef(); @@ -67,7 +66,6 @@ export function WindowSideBarCanvasPanel({ ); } else { @@ -75,7 +73,6 @@ export function WindowSideBarCanvasPanel({ ); } @@ -84,7 +81,6 @@ export function WindowSideBarCanvasPanel({ @@ -162,5 +158,4 @@ WindowSideBarCanvasPanel.propTypes = { updateSequence: PropTypes.func.isRequired, updateVariant: PropTypes.func.isRequired, variant: PropTypes.oneOf(['item', 'thumbnail', 'tableOfContents']).isRequired, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/WindowSideBarCollectionPanel.js b/src/components/WindowSideBarCollectionPanel.js index 6f71e38ab5..c31bebe1fd 100644 --- a/src/components/WindowSideBarCollectionPanel.js +++ b/src/components/WindowSideBarCollectionPanel.js @@ -72,7 +72,6 @@ export function WindowSideBarCollectionPanel({ updateCompanionWindow, updateWindow, variant = null, - windowId, }) { const { t } = useTranslation(); /** */ @@ -89,7 +88,6 @@ export function WindowSideBarCollectionPanel({ return ( @@ -188,5 +186,4 @@ WindowSideBarCollectionPanel.propTypes = { updateCompanionWindow: PropTypes.func.isRequired, updateWindow: PropTypes.func.isRequired, variant: PropTypes.string, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/WindowSideBarInfoPanel.js b/src/components/WindowSideBarInfoPanel.js index fc367a7c7f..b664a496b1 100644 --- a/src/components/WindowSideBarInfoPanel.js +++ b/src/components/WindowSideBarInfoPanel.js @@ -13,7 +13,6 @@ import ns from '../config/css-ns'; * WindowSideBarInfoPanel */ export function WindowSideBarInfoPanel({ - windowId, id, canvasIds = [], collectionPath = [], @@ -27,7 +26,6 @@ export function WindowSideBarInfoPanel({ )) } { collectionPath.length > 0 && ( - + )} - + - + ); @@ -80,5 +77,4 @@ WindowSideBarInfoPanel.propTypes = { locale: PropTypes.string, setLocale: PropTypes.func, showLocalePicker: PropTypes.bool, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/WindowTopBar.js b/src/components/WindowTopBar.js index fe3d7bf978..000dbf4769 100644 --- a/src/components/WindowTopBar.js +++ b/src/components/WindowTopBar.js @@ -36,7 +36,7 @@ const StyledToolbar = styled(Toolbar, { name: 'WindowTopBar', slot: 'toolbar' }) * WindowTopBar */ export function WindowTopBar({ - removeWindow, windowId, toggleWindowSideBar, + removeWindow, toggleWindowSideBar, maximizeWindow = () => {}, maximized = false, minimizeWindow = () => {}, allowClose = true, allowMaximize = true, focusWindow = () => {}, allowFullscreen = false, allowTopMenuButton = true, allowWindowSideBar = true, component = 'nav', @@ -62,14 +62,12 @@ export function WindowTopBar({ )} - + {allowTopMenuButton && ( - + )} - - + + {allowMaximize && ( - + {showThumbnailNavigationSettings - && } + && } ); @@ -61,5 +61,4 @@ WindowTopMenu.propTypes = { open: PropTypes.bool, showThumbnailNavigationSettings: PropTypes.bool, toggleDraggingEnabled: PropTypes.func.isRequired, - windowId: PropTypes.string.isRequired, }; diff --git a/src/components/WindowTopMenuButton.js b/src/components/WindowTopMenuButton.js index 75a70a5f39..f55b12e2c0 100644 --- a/src/components/WindowTopMenuButton.js +++ b/src/components/WindowTopMenuButton.js @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useId, useState } from 'react'; import PropTypes from 'prop-types'; import { useTranslation } from 'react-i18next'; import WindowTopMenu from '../containers/WindowTopMenu'; @@ -7,7 +7,7 @@ import WindowOptionsIcon from './icons/WindowOptionsIcon'; /** */ -export function WindowTopMenuButton({ classes = {}, windowId }) { +export function WindowTopMenuButton({ classes = {} }) { const { t } = useTranslation(); const [anchorEl, setAnchorEl] = useState(null); const [open, setOpen] = useState(false); @@ -24,7 +24,7 @@ export function WindowTopMenuButton({ classes = {}, windowId }) { setOpen(false); }; - const menuId = `window-menu_${windowId}`; + const menuId = useId(); return ( <> import('../containers/OpenSeadragonViewer')); @@ -9,20 +8,14 @@ const OSDViewer = lazy(() => import('../containers/OpenSeadragonViewer')); * Represents a WindowViewer in the mirador workspace. Responsible for mounting * OSD and Navigation */ -export function WindowViewer({ windowId }) { +export function WindowViewer() { return ( }> - - + + ); } - -WindowViewer.propTypes = { - windowId: PropTypes.string.isRequired, -}; diff --git a/src/containers/AnnotationSettings.js b/src/containers/AnnotationSettings.js index 6388b680bf..cba8245fbc 100644 --- a/src/containers/AnnotationSettings.js +++ b/src/containers/AnnotationSettings.js @@ -7,6 +7,7 @@ import { getWindow, } from '../state/selectors'; import { AnnotationSettings } from '../components/AnnotationSettings'; +import { withWindowContext } from '../contexts/WindowContext'; /** * Mapping redux state to component props using connect @@ -29,6 +30,7 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('AnnotationSettings'), ); diff --git a/src/containers/AnnotationsOverlay.js b/src/containers/AnnotationsOverlay.js index 1199674946..f63b2f6661 100644 --- a/src/containers/AnnotationsOverlay.js +++ b/src/containers/AnnotationsOverlay.js @@ -13,6 +13,7 @@ import { getSelectedAnnotationId, getCurrentCanvasWorld, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - used to hook up connect to action creators @@ -46,6 +47,7 @@ const mapDispatchToProps = { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('AnnotationsOverlay'), ); diff --git a/src/containers/AttributionPanel.js b/src/containers/AttributionPanel.js index 4942c8da64..67345b9ccf 100644 --- a/src/containers/AttributionPanel.js +++ b/src/containers/AttributionPanel.js @@ -7,6 +7,7 @@ import { } from '../state/selectors'; import { withPlugins } from '../extend/withPlugins'; import { AttributionPanel } from '../components/AttributionPanel'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -20,6 +21,7 @@ const mapStateToProps = (state, { id, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps), withPlugins('AttributionPanel'), ); diff --git a/src/containers/AudioViewer.js b/src/containers/AudioViewer.js index ecff307c8e..796d958b96 100644 --- a/src/containers/AudioViewer.js +++ b/src/containers/AudioViewer.js @@ -3,6 +3,7 @@ import { compose } from 'redux'; import { withPlugins } from '../extend/withPlugins'; import { AudioViewer } from '../components/AudioViewer'; import { getConfig, getVisibleCanvasAudioResources, getVisibleCanvasCaptions } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** */ const mapStateToProps = (state, { windowId }) => ( @@ -14,6 +15,7 @@ const mapStateToProps = (state, { windowId }) => ( ); const enhance = compose( + withWindowContext, connect(mapStateToProps, null), withPlugins('AudioViewer'), ); diff --git a/src/containers/CanvasAnnotations.js b/src/containers/CanvasAnnotations.js index 697f961949..baa5656a39 100644 --- a/src/containers/CanvasAnnotations.js +++ b/src/containers/CanvasAnnotations.js @@ -9,6 +9,7 @@ import { getConfig, } from '../state/selectors'; import { CanvasAnnotations } from '../components/CanvasAnnotations'; +import { withWindowContext } from '../contexts/WindowContext'; /** * @param {Array} resources @@ -48,6 +49,7 @@ const mapDispatchToProps = { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('CanvasAnnotations'), ); diff --git a/src/containers/CanvasInfo.js b/src/containers/CanvasInfo.js index 554af62eb4..9e9d4560a6 100644 --- a/src/containers/CanvasInfo.js +++ b/src/containers/CanvasInfo.js @@ -8,6 +8,7 @@ import { getCanvasDescription, } from '../state/selectors'; import { CanvasInfo } from '../components/CanvasInfo'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -23,6 +24,7 @@ const mapStateToProps = (state, { canvasId, id, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps), withPlugins('CanvasInfo'), ); diff --git a/src/containers/CanvasLayers.js b/src/containers/CanvasLayers.js index eb830966de..c36a6bde65 100644 --- a/src/containers/CanvasLayers.js +++ b/src/containers/CanvasLayers.js @@ -7,6 +7,7 @@ import { getSortedLayers, } from '../state/selectors'; import { CanvasLayers } from '../components/CanvasLayers'; +import { withWindowContext } from '../contexts/WindowContext'; /** For connect */ const mapStateToProps = (state, { canvasId, windowId }) => ({ @@ -25,6 +26,7 @@ const mapDispatchToProps = { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), ); diff --git a/src/containers/CollectionDialog.js b/src/containers/CollectionDialog.js index abf7693dca..b22e96a0f1 100644 --- a/src/containers/CollectionDialog.js +++ b/src/containers/CollectionDialog.js @@ -6,6 +6,7 @@ import { getManifest, getManifestoInstance, getSequenceBehaviors, getWindow, } from '../state/selectors'; import { CollectionDialog } from '../components/CollectionDialog'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapDispatchToProps - used to hook up connect to action creators @@ -46,6 +47,7 @@ const mapStateToProps = (state, { windowId }) => { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('CollectionDialog'), ); diff --git a/src/containers/CollectionInfo.js b/src/containers/CollectionInfo.js index 0c17a32323..ecc07ee678 100644 --- a/src/containers/CollectionInfo.js +++ b/src/containers/CollectionInfo.js @@ -7,6 +7,7 @@ import { } from '../state/selectors'; import * as actions from '../state/actions'; import { CollectionInfo } from '../components/CollectionInfo'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -28,6 +29,7 @@ const mapDispatchToProps = { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('CollectionInfo'), ); diff --git a/src/containers/CompanionArea.js b/src/containers/CompanionArea.js index 9830c77c3b..9f56d5d075 100644 --- a/src/containers/CompanionArea.js +++ b/src/containers/CompanionArea.js @@ -6,6 +6,7 @@ import { } from '../state/selectors'; import * as actions from '../state/actions'; import { CompanionArea } from '../components/CompanionArea'; +import { withWindowContext } from '../contexts/WindowContext'; /** */ const mapStateToProps = (state, { windowId, position }) => ({ @@ -20,6 +21,7 @@ const mapDispatchToProps = ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('CompanionArea'), ); diff --git a/src/containers/CompanionWindow.js b/src/containers/CompanionWindow.js index b3eff06072..8e491f54ef 100644 --- a/src/containers/CompanionWindow.js +++ b/src/containers/CompanionWindow.js @@ -4,6 +4,7 @@ import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getCompanionWindow, getThemeDirection, getWindowConfig } from '../state/selectors'; import { CompanionWindow } from '../components/CompanionWindow'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -42,6 +43,7 @@ const mapDispatchToProps = (dispatch, { windowId, id }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('CompanionWindow'), ); diff --git a/src/containers/CustomPanel.js b/src/containers/CustomPanel.js index 5ce78ce41b..bd512628da 100644 --- a/src/containers/CustomPanel.js +++ b/src/containers/CustomPanel.js @@ -2,6 +2,7 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withPlugins } from '../extend/withPlugins'; import { CustomPanel } from '../components/CustomPanel'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -10,6 +11,7 @@ const mapStateToProps = (state, { id, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps), withPlugins('CustomPanel'), ); diff --git a/src/containers/ErrorContent.js b/src/containers/ErrorContent.js index 4f4fa76401..fc520bdf84 100644 --- a/src/containers/ErrorContent.js +++ b/src/containers/ErrorContent.js @@ -9,6 +9,7 @@ import { getViewer, getConfig, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** mapStateToProps */ const mapStateToProps = (state, { companionWindowId, windowId }) => ({ @@ -22,6 +23,7 @@ const mapStateToProps = (state, { companionWindowId, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps), withPlugins('ErrorContent'), ); diff --git a/src/containers/GalleryView.js b/src/containers/GalleryView.js index 9c54be5a4b..a3b15b8838 100644 --- a/src/containers/GalleryView.js +++ b/src/containers/GalleryView.js @@ -3,6 +3,7 @@ import { connect } from 'react-redux'; import { withPlugins } from '../extend/withPlugins'; import { GalleryView } from '../components/GalleryView'; import { getCanvases, getSequenceViewingDirection } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -17,6 +18,7 @@ const mapStateToProps = (state, { windowId }) => ( ); const enhance = compose( + withWindowContext, connect(mapStateToProps), withPlugins('GalleryView'), // further HOC go here diff --git a/src/containers/GalleryViewThumbnail.js b/src/containers/GalleryViewThumbnail.js index c0306777ce..a26449e2fa 100644 --- a/src/containers/GalleryViewThumbnail.js +++ b/src/containers/GalleryViewThumbnail.js @@ -10,6 +10,7 @@ import { getPresentAnnotationsOnSelectedCanvases, getCompanionWindowsForContent, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** */ const mapStateToProps = (state, { canvas, windowId }) => { @@ -57,6 +58,7 @@ const mapDispatchToProps = (dispatch, { canvas, id, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), // further HOC go here ); diff --git a/src/containers/IIIFAuthentication.js b/src/containers/IIIFAuthentication.js index caff30f20c..1874277301 100644 --- a/src/containers/IIIFAuthentication.js +++ b/src/containers/IIIFAuthentication.js @@ -10,6 +10,7 @@ import { getAccessTokens, } from '../state/selectors'; import { IIIFAuthentication } from '../components/IIIFAuthentication'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -90,6 +91,7 @@ const mapDispatchToProps = { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('IIIFAuthentication'), ); diff --git a/src/containers/LayersPanel.js b/src/containers/LayersPanel.js index 3f8900be7b..3518cd8f95 100644 --- a/src/containers/LayersPanel.js +++ b/src/containers/LayersPanel.js @@ -5,6 +5,7 @@ import { LayersPanel } from '../components/LayersPanel'; import { getVisibleCanvasIds, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -14,6 +15,7 @@ const mapStateToProps = (state, { id, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps), withPlugins('LayersPanel'), ); diff --git a/src/containers/ManifestInfo.js b/src/containers/ManifestInfo.js index 89e202bb70..2a2e5fcbeb 100644 --- a/src/containers/ManifestInfo.js +++ b/src/containers/ManifestInfo.js @@ -8,6 +8,7 @@ import { getManifestMetadata, } from '../state/selectors'; import { ManifestInfo } from '../components/ManifestInfo'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -26,6 +27,7 @@ const mapStateToProps = (state, { id, manifestId, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps), withPlugins('ManifestInfo'), ); diff --git a/src/containers/ManifestRelatedLinks.js b/src/containers/ManifestRelatedLinks.js index d4e1da7081..a84c162f5d 100644 --- a/src/containers/ManifestRelatedLinks.js +++ b/src/containers/ManifestRelatedLinks.js @@ -9,6 +9,7 @@ import { getManifestUrl, } from '../state/selectors'; import { ManifestRelatedLinks } from '../components/ManifestRelatedLinks'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -24,6 +25,7 @@ const mapStateToProps = (state, { id, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps), withPlugins('ManifestRelatedLinks'), ); diff --git a/src/containers/MinimalWindow.js b/src/containers/MinimalWindow.js index 08218d5666..25493866b1 100644 --- a/src/containers/MinimalWindow.js +++ b/src/containers/MinimalWindow.js @@ -4,6 +4,7 @@ import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { MinimalWindow } from '../components/MinimalWindow'; import { getWindowConfig } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** mapStateToProps */ const mapStateToProps = (state, { windowId }) => ({ @@ -21,6 +22,7 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('MinimalWindow'), ); diff --git a/src/containers/OpenSeadragonViewer.js b/src/containers/OpenSeadragonViewer.js index e03bc8bef4..fc517e9b87 100644 --- a/src/containers/OpenSeadragonViewer.js +++ b/src/containers/OpenSeadragonViewer.js @@ -14,6 +14,7 @@ import { selectInfoResponses, getCurrentCanvasWorld, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - used to hook up connect to action creators @@ -54,6 +55,7 @@ const mapDispatchToProps = { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('OpenSeadragonViewer'), ); diff --git a/src/containers/PrimaryWindow.js b/src/containers/PrimaryWindow.js index 1895e80539..afe55c5f11 100644 --- a/src/containers/PrimaryWindow.js +++ b/src/containers/PrimaryWindow.js @@ -5,6 +5,7 @@ import { getManifestoInstance, getVisibleCanvasAudioResources, getVisibleCanvasVideoResources, getWindow, } from '../state/selectors'; import { PrimaryWindow } from '../components/PrimaryWindow'; +import { withWindowContext } from '../contexts/WindowContext'; /** */ const mapStateToProps = (state, { windowId }) => { @@ -18,6 +19,7 @@ const mapStateToProps = (state, { windowId }) => { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, null), withPlugins('PrimaryWindow'), ); diff --git a/src/containers/SearchHit.js b/src/containers/SearchHit.js index 66f31bb863..929c7dce73 100644 --- a/src/containers/SearchHit.js +++ b/src/containers/SearchHit.js @@ -11,6 +11,7 @@ import { getSelectedContentSearchAnnotationIds, getSelectedAnnotationId, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - used to hook up connect to state @@ -69,6 +70,7 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('SearchHit'), ); diff --git a/src/containers/SearchPanel.js b/src/containers/SearchPanel.js index b92fe4d0ad..d915b4fe6a 100644 --- a/src/containers/SearchPanel.js +++ b/src/containers/SearchPanel.js @@ -4,6 +4,7 @@ import * as actions from '../state/actions'; import { withPlugins } from '../extend/withPlugins'; import { SearchPanel } from '../components/SearchPanel'; import { getManifestSearchService, getSearchQuery, getWindow } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** */ const mapStateToProps = (state, { id, windowId }) => ({ @@ -21,6 +22,7 @@ const mapDispatchToProps = (dispatch, props) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('SearchPanel'), ); diff --git a/src/containers/SearchPanelControls.js b/src/containers/SearchPanelControls.js index ab71f26107..f32d6d3987 100644 --- a/src/containers/SearchPanelControls.js +++ b/src/containers/SearchPanelControls.js @@ -9,6 +9,7 @@ import { getSearchIsFetching, getSearchQuery, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - used to hook up connect to state @@ -32,6 +33,7 @@ const mapDispatchToProps = { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('SearchPanelControls'), ); diff --git a/src/containers/SearchPanelNavigation.js b/src/containers/SearchPanelNavigation.js index 8a77cf28cd..526c9f58a1 100644 --- a/src/containers/SearchPanelNavigation.js +++ b/src/containers/SearchPanelNavigation.js @@ -9,6 +9,7 @@ import { getSortedSearchHitsForCompanionWindow, getThemeDirection, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - used to hook up connect to state @@ -36,6 +37,7 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('SearchPanelNavigation'), ); diff --git a/src/containers/SearchResults.js b/src/containers/SearchResults.js index 9fd30f1d56..c9cbea0191 100644 --- a/src/containers/SearchResults.js +++ b/src/containers/SearchResults.js @@ -11,6 +11,7 @@ import { getSortedSearchHitsForCompanionWindow, getSortedSearchAnnotationsForCompanionWindow, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - used to hook up connect to state @@ -32,6 +33,7 @@ const mapDispatchToProps = { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('SearchResults'), ); diff --git a/src/containers/SelectCollection.js b/src/containers/SelectCollection.js index 39fcc3d80a..9b064c00c3 100644 --- a/src/containers/SelectCollection.js +++ b/src/containers/SelectCollection.js @@ -6,6 +6,7 @@ import { getWindow, } from '../state/selectors'; import { SelectCollection } from '../components/SelectCollection'; +import { withWindowContext } from '../contexts/WindowContext'; /** */ const mapStateToProps = (state, { windowId }) => { @@ -22,6 +23,7 @@ const mapDispatchToProps = { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('SelectCollection'), ); diff --git a/src/containers/SidebarIndexList.js b/src/containers/SidebarIndexList.js index 21b69418f1..e7501346f5 100644 --- a/src/containers/SidebarIndexList.js +++ b/src/containers/SidebarIndexList.js @@ -8,6 +8,7 @@ import { getVisibleCanvasIds, } from '../state/selectors'; import { SidebarIndexList } from '../components/SidebarIndexList'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -28,6 +29,7 @@ const mapDispatchToProps = (dispatch, { id, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('SidebarIndexList'), ); diff --git a/src/containers/SidebarIndexTableOfContents.js b/src/containers/SidebarIndexTableOfContents.js index be46b4037a..840e71040a 100644 --- a/src/containers/SidebarIndexTableOfContents.js +++ b/src/containers/SidebarIndexTableOfContents.js @@ -9,6 +9,7 @@ import { getNodeIdToScrollTo, } from '../state/selectors'; import * as actions from '../state/actions'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -32,6 +33,7 @@ const mapDispatchToProps = (dispatch, { id, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('SidebarIndexTableOfContents'), ); diff --git a/src/containers/ThumbnailCanvasGrouping.js b/src/containers/ThumbnailCanvasGrouping.js index a8e7c595da..43613eb3c7 100644 --- a/src/containers/ThumbnailCanvasGrouping.js +++ b/src/containers/ThumbnailCanvasGrouping.js @@ -4,14 +4,15 @@ import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getCurrentCanvas } from '../state/selectors'; import { ThumbnailCanvasGrouping } from '../components/ThumbnailCanvasGrouping'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapDispatchToProps - used to hook up connect to action creators * @memberof ThumbnailCanvasGrouping * @private */ -const mapDispatchToProps = (dispatch, { data }) => ({ - setCanvas: (...args) => dispatch(actions.setCanvas(data.windowId, ...args)), +const mapDispatchToProps = (dispatch, { windowId }) => ({ + setCanvas: (...args) => dispatch(actions.setCanvas(windowId, ...args)), }); /** @@ -19,11 +20,12 @@ const mapDispatchToProps = (dispatch, { data }) => ({ * @memberof ThumbnailCanvasGrouping * @private */ -const mapStateToProps = (state, { data }) => ({ - currentCanvasId: (getCurrentCanvas(state, { windowId: data.windowId }) || {}).id, +const mapStateToProps = (state, { windowId }) => ({ + currentCanvasId: (getCurrentCanvas(state, { windowId }) || {}).id, }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('ThumbnailCanvasGrouping'), ); diff --git a/src/containers/ThumbnailNavigation.js b/src/containers/ThumbnailNavigation.js index 3b23c2ae98..84fbcce36b 100644 --- a/src/containers/ThumbnailNavigation.js +++ b/src/containers/ThumbnailNavigation.js @@ -9,6 +9,7 @@ import { getCanvasGroupings, getCanvasIndex, getWindowViewType, getSequenceViewingDirection, getConfig, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - used to hook up state to props @@ -39,6 +40,7 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('ThumbnailNavigation'), ); diff --git a/src/containers/VideoViewer.js b/src/containers/VideoViewer.js index eeb49e0a76..a062040735 100644 --- a/src/containers/VideoViewer.js +++ b/src/containers/VideoViewer.js @@ -3,6 +3,7 @@ import { compose } from 'redux'; import { withPlugins } from '../extend/withPlugins'; import { VideoViewer } from '../components/VideoViewer'; import { getConfig, getVisibleCanvasCaptions, getVisibleCanvasVideoResources } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** */ const mapStateToProps = (state, { windowId }) => ( @@ -14,6 +15,7 @@ const mapStateToProps = (state, { windowId }) => ( ); const enhance = compose( + withWindowContext, connect(mapStateToProps, null), withPlugins('VideoViewer'), ); diff --git a/src/containers/ViewerInfo.js b/src/containers/ViewerInfo.js index aace450c9d..344024503e 100644 --- a/src/containers/ViewerInfo.js +++ b/src/containers/ViewerInfo.js @@ -5,6 +5,7 @@ import { ViewerInfo } from '../components/ViewerInfo'; import { getCanvasLabel, getCanvases, getCanvasIndex, getCurrentCanvas, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -28,6 +29,7 @@ const mapStateToProps = (state, props) => { }; const enhance = compose( + withWindowContext, connect(mapStateToProps, null), withPlugins('ViewerInfo'), ); diff --git a/src/containers/ViewerNavigation.js b/src/containers/ViewerNavigation.js index 66b2145e24..12feb59ee6 100644 --- a/src/containers/ViewerNavigation.js +++ b/src/containers/ViewerNavigation.js @@ -8,6 +8,7 @@ import { getPreviousCanvasGrouping, } from '../state/selectors'; import { ViewerNavigation } from '../components/ViewerNavigation'; +import { withWindowContext } from '../contexts/WindowContext'; /** */ const mapStateToProps = (state, { windowId }) => ({ @@ -27,6 +28,7 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('ViewerNavigation'), // further HOC go here diff --git a/src/containers/WindowAuthenticationBar.js b/src/containers/WindowAuthenticationBar.js index db3240da47..b5aa674047 100644 --- a/src/containers/WindowAuthenticationBar.js +++ b/src/containers/WindowAuthenticationBar.js @@ -1,8 +1,10 @@ import { compose } from 'redux'; import { withPlugins } from '../extend/withPlugins'; import { WindowAuthenticationBar } from '../components/WindowAuthenticationBar'; +import { withWindowContext } from '../contexts/WindowContext'; const enhance = compose( + withWindowContext, withPlugins('WindowAuthenticationBar'), ); diff --git a/src/containers/WindowCanvasNavigationControls.js b/src/containers/WindowCanvasNavigationControls.js index 7cb1c13788..c832bdd2d4 100644 --- a/src/containers/WindowCanvasNavigationControls.js +++ b/src/containers/WindowCanvasNavigationControls.js @@ -3,6 +3,7 @@ import { compose } from 'redux'; import { withPlugins } from '../extend/withPlugins'; import { getShowZoomControlsConfig, getWorkspace } from '../state/selectors'; import { WindowCanvasNavigationControls } from '../components/WindowCanvasNavigationControls'; +import { withWindowContext } from '../contexts/WindowContext'; /** */ const mapStateToProps = (state, { windowId }) => ({ @@ -11,6 +12,7 @@ const mapStateToProps = (state, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps), withPlugins('WindowCanvasNavigationControls'), ); diff --git a/src/containers/WindowSideBar.js b/src/containers/WindowSideBar.js index 26b3ee2169..975a3ac1dc 100644 --- a/src/containers/WindowSideBar.js +++ b/src/containers/WindowSideBar.js @@ -3,6 +3,7 @@ import { compose } from 'redux'; import { withPlugins } from '../extend/withPlugins'; import { WindowSideBar } from '../components/WindowSideBar'; import { getThemeDirection, getWindow } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -18,6 +19,7 @@ const mapStateToProps = (state, { windowId }) => ( ); const enhance = compose( + withWindowContext, connect(mapStateToProps, null), withPlugins('WindowSideBar'), ); diff --git a/src/containers/WindowSideBarAnnotationsPanel.js b/src/containers/WindowSideBarAnnotationsPanel.js index 71c73ca1ec..536797cf12 100644 --- a/src/containers/WindowSideBarAnnotationsPanel.js +++ b/src/containers/WindowSideBarAnnotationsPanel.js @@ -6,6 +6,7 @@ import { getAnnotationResourcesByMotivation, } from '../state/selectors'; import { WindowSideBarAnnotationsPanel } from '../components/WindowSideBarAnnotationsPanel'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -21,6 +22,7 @@ const mapStateToProps = (state, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, null), withPlugins('WindowSideBarAnnotationsPanel'), // further HOC diff --git a/src/containers/WindowSideBarButtons.js b/src/containers/WindowSideBarButtons.js index 5bb2e69efb..9ada51a95e 100644 --- a/src/containers/WindowSideBarButtons.js +++ b/src/containers/WindowSideBarButtons.js @@ -14,6 +14,7 @@ import { getWindowConfig, } from '../state/selectors'; import { WindowSideBarButtons } from '../components/WindowSideBarButtons'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapDispatchToProps - used to hook up connect to action creators @@ -64,6 +65,7 @@ const mapStateToProps = (state, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowSideBarButtons'), ); diff --git a/src/containers/WindowSideBarCanvasPanel.js b/src/containers/WindowSideBarCanvasPanel.js index 902cac8c65..80d3fb2800 100644 --- a/src/containers/WindowSideBarCanvasPanel.js +++ b/src/containers/WindowSideBarCanvasPanel.js @@ -12,6 +12,7 @@ import { getSequence, getSequences, } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -52,6 +53,7 @@ const mapDispatchToProps = (dispatch, { id, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowSideBarCanvasPanel'), ); diff --git a/src/containers/WindowSideBarCollectionPanel.js b/src/containers/WindowSideBarCollectionPanel.js index 050509165f..9c8fc0beb1 100644 --- a/src/containers/WindowSideBarCollectionPanel.js +++ b/src/containers/WindowSideBarCollectionPanel.js @@ -10,6 +10,7 @@ import { getWindow, } from '../state/selectors'; import { WindowSideBarCollectionPanel } from '../components/WindowSideBarCollectionPanel'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -55,6 +56,7 @@ const mapDispatchToProps = (dispatch, { id, windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowSideBarCollectionPanel'), ); diff --git a/src/containers/WindowSideBarInfoPanel.js b/src/containers/WindowSideBarInfoPanel.js index c8bee5c5b0..0e08d06381 100644 --- a/src/containers/WindowSideBarInfoPanel.js +++ b/src/containers/WindowSideBarInfoPanel.js @@ -11,6 +11,7 @@ import { getWindow, } from '../state/selectors'; import { WindowSideBarInfoPanel } from '../components/WindowSideBarInfoPanel'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -32,6 +33,7 @@ const mapDispatchToProps = (dispatch, { windowId, id }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowSideBarInfoPanel'), ); diff --git a/src/containers/WindowThumbnailSettings.js b/src/containers/WindowThumbnailSettings.js index 3217d6812e..3662d229d0 100644 --- a/src/containers/WindowThumbnailSettings.js +++ b/src/containers/WindowThumbnailSettings.js @@ -4,6 +4,7 @@ import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getThumbnailNavigationPosition, getThemeDirection } from '../state/selectors'; import { WindowThumbnailSettings } from '../components/WindowThumbnailSettings'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapDispatchToProps - used to hook up connect to action creators @@ -25,6 +26,7 @@ const mapStateToProps = (state, { windowId }) => ( ); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true }), withPlugins('WindowThumbnailSettings'), // further HOC go here diff --git a/src/containers/WindowTopBar.js b/src/containers/WindowTopBar.js index 990007620d..3f44559a42 100644 --- a/src/containers/WindowTopBar.js +++ b/src/containers/WindowTopBar.js @@ -4,6 +4,7 @@ import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getWindowConfig, isFocused } from '../state/selectors'; import { WindowTopBar } from '../components/WindowTopBar'; +import { withWindowContext } from '../contexts/WindowContext'; /** mapStateToProps */ const mapStateToProps = (state, { windowId }) => { @@ -34,6 +35,7 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowTopBar'), ); diff --git a/src/containers/WindowTopBarPluginArea.js b/src/containers/WindowTopBarPluginArea.js index fd54047cbe..6dc64f247b 100644 --- a/src/containers/WindowTopBarPluginArea.js +++ b/src/containers/WindowTopBarPluginArea.js @@ -1,10 +1,10 @@ import { compose } from 'redux'; -import { connect } from 'react-redux'; import { withPlugins } from '../extend/withPlugins'; import { WindowTopBarPluginArea } from '../components/WindowTopBarPluginArea'; +import { withWindowContext } from '../contexts/WindowContext'; const enhance = compose( - connect(null, null), + withWindowContext, withPlugins('WindowTopBarPluginArea'), ); diff --git a/src/containers/WindowTopBarPluginMenu.js b/src/containers/WindowTopBarPluginMenu.js index ed52de094c..1ca6e7ecb3 100644 --- a/src/containers/WindowTopBarPluginMenu.js +++ b/src/containers/WindowTopBarPluginMenu.js @@ -1,8 +1,10 @@ import { compose } from 'redux'; import { withPlugins } from '../extend/withPlugins'; import { WindowTopBarPluginMenu } from '../components/WindowTopBarPluginMenu'; +import { withWindowContext } from '../contexts/WindowContext'; const enhance = compose( + withWindowContext, withPlugins('WindowTopBarPluginMenu'), ); diff --git a/src/containers/WindowTopBarTitle.js b/src/containers/WindowTopBarTitle.js index 88adb8be39..30972f407f 100644 --- a/src/containers/WindowTopBarTitle.js +++ b/src/containers/WindowTopBarTitle.js @@ -3,6 +3,7 @@ import { connect } from 'react-redux'; import { withPlugins } from '../extend/withPlugins'; import { getManifestStatus, getManifestTitle, getWindowConfig } from '../state/selectors'; import { WindowTopBarTitle } from '../components/WindowTopBarTitle'; +import { withWindowContext } from '../contexts/WindowContext'; /** mapStateToProps */ const mapStateToProps = (state, { windowId }) => ({ @@ -13,6 +14,7 @@ const mapStateToProps = (state, { windowId }) => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, null), withPlugins('WindowTopBarTitle'), ); diff --git a/src/containers/WindowTopMenu.js b/src/containers/WindowTopMenu.js index f4916086bc..a5b35f47d2 100644 --- a/src/containers/WindowTopMenu.js +++ b/src/containers/WindowTopMenu.js @@ -4,6 +4,7 @@ import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { WindowTopMenu } from '../components/WindowTopMenu'; import { getConfig } from '../state/selectors'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -24,6 +25,7 @@ const mapDispatchToProps = dispatch => ({ }); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowTopMenu'), ); diff --git a/src/containers/WindowTopMenuButton.js b/src/containers/WindowTopMenuButton.js index 7aba4484c4..2d61410078 100644 --- a/src/containers/WindowTopMenuButton.js +++ b/src/containers/WindowTopMenuButton.js @@ -1,8 +1,10 @@ import { compose } from 'redux'; import { withPlugins } from '../extend/withPlugins'; import { WindowTopMenuButton } from '../components/WindowTopMenuButton'; +import { withWindowContext } from '../contexts/WindowContext'; const enhance = compose( + withWindowContext, withPlugins('WindowTopMenuButton'), ); diff --git a/src/containers/WindowViewSettings.js b/src/containers/WindowViewSettings.js index 98ba9c9347..7e5766f5af 100644 --- a/src/containers/WindowViewSettings.js +++ b/src/containers/WindowViewSettings.js @@ -4,6 +4,7 @@ import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getAllowedWindowViewTypes, getWindowViewType } from '../state/selectors'; import { WindowViewSettings } from '../components/WindowViewSettings'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapDispatchToProps - used to hook up connect to action creators @@ -25,6 +26,7 @@ const mapStateToProps = (state, { windowId }) => ( ); const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true }), withPlugins('WindowViewSettings'), ); diff --git a/src/containers/WindowViewer.js b/src/containers/WindowViewer.js index b6c396b2ef..e55dcbebb9 100644 --- a/src/containers/WindowViewer.js +++ b/src/containers/WindowViewer.js @@ -1,8 +1,10 @@ import { compose } from 'redux'; import { withPlugins } from '../extend/withPlugins'; import { WindowViewer } from '../components/WindowViewer'; +import { withWindowContext } from '../contexts/WindowContext'; const enhance = compose( + withWindowContext, withPlugins('WindowViewer'), // further HOC go here ); diff --git a/src/containers/ZoomControls.js b/src/containers/ZoomControls.js index 35eb2757a0..9f52b9359c 100644 --- a/src/containers/ZoomControls.js +++ b/src/containers/ZoomControls.js @@ -4,6 +4,7 @@ import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getViewer } from '../state/selectors'; import { ZoomControls } from '../components/ZoomControls'; +import { withWindowContext } from '../contexts/WindowContext'; /** * mapStateToProps - to hook up connect @@ -24,6 +25,7 @@ const mapStateToProps = (state, { windowId }) => ( const mapDispatchToProps = { updateViewport: actions.updateViewport }; const enhance = compose( + withWindowContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('ZoomControls'), ); diff --git a/src/contexts/WindowContext.js b/src/contexts/WindowContext.js new file mode 100644 index 0000000000..fa108f0123 --- /dev/null +++ b/src/contexts/WindowContext.js @@ -0,0 +1,71 @@ +import { + useContext, + createContext, + forwardRef, + useMemo, +} from 'react'; +import PropTypes from 'prop-types'; + +const WindowContext = createContext({ id: null }); + +/** + * Set up the window context for a given window; this is + * done as a HOC so that we can wrap the component + * at the container in a backwards-compatible way. + */ +export const setWindowContext = (Component) => { + /** + * Wrap the component with the context + */ + function ContextHoc({ windowId, ...props }, ref) { + const passDownProps = { + ...props, + ...(ref ? { ref } : {}), + }; + + const value = useMemo(() => ({ id: windowId }), [windowId]); + + return ( + + + + ); + } + + ContextHoc.propTypes = { + windowId: PropTypes.string.isRequired, + }; + + const whatever = forwardRef(ContextHoc); + whatever.displayName = `WithSetWindowContext(${Component.displayName || Component.name || 'Component'})`; + return whatever; +}; + +/** + * @returns HOC that injects the workspace ref into the component + */ +export const withWindowContext = (Component) => { + /** + * Wrap the component with the context + */ + function ContextHoc({ windowId = null, ...props }, ref) { + const { id } = useContext(WindowContext); + + const passDownProps = { + ...props, + ...(ref ? { ref } : {}), + }; + + ContextHoc.propTypes = { + windowId: PropTypes.string, + }; + + return ; + } + + const whatever = forwardRef(ContextHoc); + whatever.displayName = `WithWindowContext(${Component.displayName || Component.name || 'Component'})`; + return whatever; +}; + +export default WindowContext;