Skip to content
Snippets Groups Projects
Unverified Commit ef6daa43 authored by Jessie Keck's avatar Jessie Keck Committed by GitHub
Browse files

Merge pull request #1982 from ProjectMirador/1856-draggable-windows

Updates react-mosaic and makes WindowTopBar draggable
parents edb3df3b bcc8469d
Branches
Tags
No related merge requests found
...@@ -5,8 +5,14 @@ import WindowTopBar from '../../../src/containers/WindowTopBar'; ...@@ -5,8 +5,14 @@ import WindowTopBar from '../../../src/containers/WindowTopBar';
import WindowMiddleContent from '../../../src/containers/WindowMiddleContent'; import WindowMiddleContent from '../../../src/containers/WindowMiddleContent';
/** create wrapper */ /** create wrapper */
function createWrapper(window) { function createWrapper(props, context) {
return shallow(<Window window={window} />); return shallow(
<Window
window={window}
{...props}
/>,
{ context },
);
} }
describe('Window', () => { describe('Window', () => {
...@@ -17,19 +23,27 @@ describe('Window', () => { ...@@ -17,19 +23,27 @@ describe('Window', () => {
expect(wrapper.find('.mirador-window')).toHaveLength(0); expect(wrapper.find('.mirador-window')).toHaveLength(0);
}); });
it('should render outer element', () => { it('should render outer element', () => {
wrapper = createWrapper(window); wrapper = createWrapper({ window });
expect(wrapper.find('.mirador-window')).toHaveLength(1); expect(wrapper.find('.mirador-window')).toHaveLength(1);
}); });
it('should render <WindowTopBar>', () => { it('should render <WindowTopBar>', () => {
wrapper = createWrapper(window); wrapper = createWrapper({ window });
expect(wrapper.find(WindowTopBar)).toHaveLength(1); expect(wrapper.find(WindowTopBar)).toHaveLength(1);
}); });
it('should render <WindowMiddleContent>', () => { it('should render <WindowMiddleContent>', () => {
wrapper = createWrapper(window); wrapper = createWrapper({ window });
expect(wrapper.find(WindowMiddleContent)).toHaveLength(1); expect(wrapper.find(WindowMiddleContent)).toHaveLength(1);
}); });
it('should render bottom companions window areas', () => { it('should render bottom companions window areas', () => {
wrapper = createWrapper(window); wrapper = createWrapper({ window });
expect(wrapper.find('.mirador-companion-bottom')).toHaveLength(1); expect(wrapper.find('.mirador-companion-bottom')).toHaveLength(1);
}); });
describe('when workspaceType is mosaic', () => {
it('calls the context mosaicWindowActions connectDragSource method to make WindowTopBar draggable', () => {
const connectDragSource = jest.fn(component => component);
wrapper = createWrapper({ window, workspaceType: 'mosaic' }, { mosaicWindowActions: { connectDragSource } });
expect(wrapper.find(WindowTopBar)).toHaveLength(1);
expect(connectDragSource).toHaveBeenCalled();
});
});
}); });
...@@ -50,7 +50,21 @@ describe('WorkspaceMosaic', () => { ...@@ -50,7 +50,21 @@ describe('WorkspaceMosaic', () => {
}); });
describe('tileRenderer', () => { describe('tileRenderer', () => {
it('when window is available', () => { it('when window is available', () => {
expect(wrapper.instance().tileRenderer('1')).not.toBeNull(); const renderedTile = wrapper.instance().tileRenderer('1', 'foo');
expect(renderedTile).not.toBeNull();
expect(shallow(renderedTile).find('DropTarget(DragSource(InternalMosaicWindow))').length).toEqual(1);
expect(shallow(renderedTile).props()).toEqual(expect.objectContaining({
toolbarControls: [],
additionalControls: [],
path: 'foo',
}));
expect(shallow(shallow(renderedTile).props().renderPreview()).matchesElement(
<div className="mosaic-preview">
<div className="mosaic-window-body">
<h4>previewWindowTitle</h4>
</div>
</div>,
)).toBe(true);
}); });
it('when window is not available', () => { it('when window is not available', () => {
expect(wrapper.instance().tileRenderer('bar')).toBeNull(); expect(wrapper.instance().tileRenderer('bar')).toBeNull();
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
"openWindows": "Fenster öffnen", "openWindows": "Fenster öffnen",
"openInCompanionWindow": "In Hilfsfenster öffnen", "openInCompanionWindow": "In Hilfsfenster öffnen",
"position": "Position", "position": "Position",
"previewWindowTitle": "Mirador",
"right": "Rechts", "right": "Rechts",
"single": "Einzeln", "single": "Einzeln",
"settings": "Einstellungen", "settings": "Einstellungen",
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
"openWindows": "Open windows", "openWindows": "Open windows",
"openInCompanionWindow": "Open in companion window", "openInCompanionWindow": "Open in companion window",
"position": "Position", "position": "Position",
"previewWindowTitle": "Mirador",
"right": "Right", "right": "Right",
"single": "Single", "single": "Single",
"settings": "Settings", "settings": "Settings",
......
...@@ -10,19 +10,36 @@ import ThumbnailNavigation from '../containers/ThumbnailNavigation'; ...@@ -10,19 +10,36 @@ import ThumbnailNavigation from '../containers/ThumbnailNavigation';
* @param {object} window * @param {object} window
*/ */
export class Window extends Component { export class Window extends Component {
/**
* wrappedTopBar - will conditionally wrap a WindowTopBar for needed
* additional functionality based on workspace type
*/
wrappedTopBar() {
const { manifest, window, workspaceType } = this.props;
const { mosaicWindowActions } = this.context;
const topBar = (
<div>
<WindowTopBar
windowId={window.id}
manifest={manifest}
/>
</div>
);
if (workspaceType !== 'mosaic') return topBar;
return mosaicWindowActions.connectDragSource(
topBar,
);
}
/** /**
* Renders things * Renders things
*/ */
render() { render() {
const { manifest, window } = this.props; const { manifest, window } = this.props;
if (!window) return <></>; if (!window) return <></>;
return ( return (
<div id={window.id} className={ns('window')}> <div id={window.id} className={ns('window')}>
<WindowTopBar {this.wrappedTopBar()}
windowId={window.id}
manifest={manifest}
/>
<WindowMiddleContent <WindowMiddleContent
window={window} window={window}
manifest={manifest} manifest={manifest}
...@@ -39,12 +56,21 @@ export class Window extends Component { ...@@ -39,12 +56,21 @@ export class Window extends Component {
} }
} }
Window.contextTypes = {
mosaicWindowActions: PropTypes.oneOfType([
PropTypes.func,
PropTypes.object,
]),
};
Window.propTypes = { Window.propTypes = {
window: PropTypes.object, // eslint-disable-line react/forbid-prop-types window: PropTypes.object, // eslint-disable-line react/forbid-prop-types
manifest: PropTypes.object, // eslint-disable-line react/forbid-prop-types manifest: PropTypes.object, // eslint-disable-line react/forbid-prop-types
workspaceType: PropTypes.string,
}; };
Window.defaultProps = { Window.defaultProps = {
window: null, window: null,
manifest: null, manifest: null,
workspaceType: null,
}; };
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import {
Mosaic, getLeaves, createBalancedTreeFromLeaves, Mosaic, MosaicWindow, getLeaves, createBalancedTreeFromLeaves,
} from 'react-mosaic-component'; } from 'react-mosaic-component';
import 'react-mosaic-component/react-mosaic-component.css'; import 'react-mosaic-component/react-mosaic-component.css';
import Window from '../containers/Window'; import Window from '../containers/Window';
...@@ -65,14 +65,28 @@ export class WorkspaceMosaic extends React.Component { ...@@ -65,14 +65,28 @@ export class WorkspaceMosaic extends React.Component {
* Render a tile (Window) in the Mosaic. * Render a tile (Window) in the Mosaic.
*/ */
tileRenderer(id, path) { tileRenderer(id, path) {
const { windows } = this.props; const { windows, t } = this.props;
const window = windows[id]; const window = windows[id];
if (!window) return null; if (!window) return null;
return ( return (
<MosaicWindow
toolbarControls={[]}
additionalControls={[]}
path={path}
windowId={window.id}
renderPreview={() => (
<div className="mosaic-preview">
<div className="mosaic-window-body">
<h4>{t('previewWindowTitle')}</h4>
</div>
</div>
)}
>
<Window <Window
key={window.id} key={window.id}
window={window} window={window}
/> />
</MosaicWindow>
); );
} }
...@@ -101,7 +115,12 @@ export class WorkspaceMosaic extends React.Component { ...@@ -101,7 +115,12 @@ export class WorkspaceMosaic extends React.Component {
} }
WorkspaceMosaic.propTypes = { WorkspaceMosaic.propTypes = {
t: PropTypes.func,
updateWorkspaceMosaicLayout: PropTypes.func.isRequired, updateWorkspaceMosaicLayout: PropTypes.func.isRequired,
windows: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types windows: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
workspace: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types workspace: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
}; };
WorkspaceMosaic.defaultProps = {
t: key => key,
};
...@@ -7,9 +7,10 @@ import { Window } from '../components/Window'; ...@@ -7,9 +7,10 @@ import { Window } from '../components/Window';
* @memberof Window * @memberof Window
* @private * @private
*/ */
const mapStateToProps = ({ manifests, windows }, props) => ({ const mapStateToProps = ({ manifests, windows, config }, props) => ({
manifest: manifests[props.window.manifestId], manifest: manifests[props.window.manifestId],
window: windows[props.window.id], window: windows[props.window.id],
workspaceType: config.workspace.type,
}); });
const enhance = compose( const enhance = compose(
......
import { compose } from 'redux'; import { compose } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { withTranslation } from 'react-i18next';
import * as actions from '../state/actions'; import * as actions from '../state/actions';
import { WorkspaceMosaic } from '../components/WorkspaceMosaic'; import { WorkspaceMosaic } from '../components/WorkspaceMosaic';
...@@ -23,6 +24,7 @@ const mapStateToProps = state => ( ...@@ -23,6 +24,7 @@ const mapStateToProps = state => (
const mapDispatchToProps = { updateWorkspaceMosaicLayout: actions.updateWorkspaceMosaicLayout }; const mapDispatchToProps = { updateWorkspaceMosaicLayout: actions.updateWorkspaceMosaicLayout };
const enhance = compose( const enhance = compose(
withTranslation(),
connect(mapStateToProps, mapDispatchToProps), connect(mapStateToProps, mapDispatchToProps),
// further HOC go here // further HOC go here
); );
......
...@@ -5,6 +5,16 @@ ...@@ -5,6 +5,16 @@
height: 100%; height: 100%;
position: relative; position: relative;
width: 100%; width: 100%;
.mosaic-window-toolbar {
display: none;
}
.mosaic-window-body {
.mirador-window-top-bar {
cursor: move;
}
}
} }
&-workspace { &-workspace {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment