Skip to content
Snippets Groups Projects
Unverified Commit 93dfdc4f authored by aeschylus's avatar aeschylus Committed by GitHub
Browse files

Merge pull request #2053 from ProjectMirador/issue-1703-modal-approach

Maximize/Minimize Window
parents 43d4b6d4 ee802d05
No related branches found
No related tags found
No related merge requests found
......@@ -17,6 +17,7 @@ describe('window actions', () => {
collectionIndex: 0,
companionWindowIds: [],
manifestId: null,
maximized: false,
rangeId: null,
thumbnailNavigationPosition: 'bottom',
x: 2700,
......@@ -55,6 +56,28 @@ describe('window actions', () => {
});
});
describe('maximizeWindow', () => {
it('maximizes the window', () => {
const maxWindowId = 'abc123';
const maximizeWindowAction = {
type: ActionTypes.MAXIMIZE_WINDOW,
windowId: maxWindowId,
};
expect(actions.maximizeWindow(maxWindowId)).toEqual(maximizeWindowAction);
});
});
describe('minimizeWindow', () => {
it('minimizes the window and renders current layout', () => {
const minWindowId = 'abc123';
const minimizeWindowAction = {
type: ActionTypes.MINIMIZE_WINDOW,
windowId: minWindowId,
};
expect(actions.minimizeWindow(minWindowId)).toEqual(minimizeWindowAction);
});
});
describe('toggleWindowSideBar', () => {
it('returns the appropriate action type', () => {
const id = 'abc123';
......
......@@ -27,6 +27,7 @@ describe('Window', () => {
y: 2700,
width: 400,
height: 400,
maximized: false,
};
it('should render nothing, if provided with no window data', () => {
wrapper = shallow(<Window t={k => k} />);
......
......@@ -19,6 +19,9 @@ function createWrapper(props) {
windowId="xyz"
classes={{}}
t={str => str}
maximizeWindow={() => {}}
maximized={false}
minimizeWindow={() => {}}
closeWindow={() => {}}
toggleWindowSideBar={() => {}}
{...props}
......@@ -31,7 +34,7 @@ describe('WindowTopBar', () => {
const wrapper = createWrapper();
expect(wrapper.find(AppBar).length).toBe(1);
expect(wrapper.find(Toolbar).length).toBe(1);
expect(wrapper.find(IconButton).length).toBe(2);
expect(wrapper.find(IconButton).length).toBe(3);
expect(wrapper.find(MenuIcon).length).toBe(1);
expect(wrapper.find(Typography).length).toBe(1);
expect(wrapper.find(WindowTopBarButtons).length).toBe(1);
......@@ -64,4 +67,10 @@ describe('WindowTopBar', () => {
const wrapper = createWrapper({ closeWindow });
expect(wrapper.find(IconButton).last().props().onClick).toBe(closeWindow);
});
it('passes correct props to <Button/>', () => {
const maximizeWindow = jest.fn();
const wrapper = createWrapper({ maximizeWindow });
expect(wrapper.find(IconButton).at(1).props().onClick).toBe(maximizeWindow);
});
});
......@@ -7,6 +7,7 @@ import Window from '../../../src/containers/Window';
import { Workspace } from '../../../src/components/Workspace';
const windows = { 1: { id: 1 }, 2: { id: 2 } };
const maximizedWindows = { 1: { id: 1, maximized: true }, 2: { id: 2, maximized: false } };
/**
* Utility function to create a Worksapce
......@@ -52,7 +53,6 @@ describe('Workspace', () => {
describe('if workspace type is unknown', () => {
it('should render <Window/> components as list', () => {
const wrapper = createWrapper({ workspaceType: 'bubu' });
expect(wrapper.matchesElement(
<div className="mirador-workspace-viewport mirador-workspace-with-control-panel">
<Typography>miradorViewer</Typography>
......@@ -62,6 +62,17 @@ describe('Workspace', () => {
)).toBe(true);
});
});
describe('if any windows are maximized', () => {
it('should render only maximized <Window/> components', () => {
const wrapper = createWrapper({ windows: maximizedWindows });
expect(wrapper.matchesElement(
<div className="mirador-workspace-viewport mirador-workspace-with-control-panel">
<Typography>miradorViewer</Typography>
<Window window={{ id: 1, maximized: true }} className="mirador-workspace-maximized-window" />
</div>,
)).toBe(true);
});
});
describe('when the workspace control panel is displayed', () => {
it('has the *-with-control-panel class applied', () => {
......
......@@ -29,7 +29,38 @@ describe('windows reducer', () => {
},
});
});
it('should handle MAXIMIZE_WINDOW', () => {
const action = {
type: ActionTypes.MAXIMIZE_WINDOW,
windowId: 'abc123',
};
const before = {
abc123: { maximized: false },
abc321: { maximized: false },
};
const after = {
abc123: { maximized: true },
abc321: { maximized: false },
};
expect(windowsReducer(before, action)).toEqual(after);
});
it('should handle MINIMIZE_WINDOW', () => {
const action = {
type: ActionTypes.MINIMIZE_WINDOW,
windowId: 'abc123',
};
const before = {
abc123: { maximized: true },
abc321: { maximized: false },
};
const after = {
abc123: { maximized: false },
abc321: { maximized: false },
};
expect(windowsReducer(before, action)).toEqual(after);
});
it('should handle TOGGLE_WINDOW_SIDE_BAR by toggling the sideBarOpen attribute', () => {
const action = {
type: ActionTypes.TOGGLE_WINDOW_SIDE_BAR,
......
......@@ -2,7 +2,8 @@
"collectCoverage": true,
"collectCoverageFrom": [
"src/**/*.{js,jsx}",
"!src/**/index*.js"
"!src/**/index*.js",
"!src/containers/**/*.{js,jsx}"
],
"coverageDirectory": "<rootDir>/coverage",
"coverageReporters": ["html", "lcov"],
......
......@@ -28,11 +28,13 @@ export class Window extends Component {
/>
</div>
);
if (workspaceType !== 'mosaic') return topBar;
if (workspaceType === 'mosaic' && window.maximized === false) {
return mosaicWindowActions.connectDragSource(
topBar,
);
}
return topBar;
}
/**
* Renders things
......@@ -47,7 +49,13 @@ export class Window extends Component {
}
return (
<section id={window.id} className={cn(classes.window, ns('window'))} aria-label={t('window', { label })}>
<section
id={window.id}
className={
cn(classes.window, ns('window'),
window.maximized ? ns('workspace-maximized-window') : null)}
aria-label={t('window', { label })}
>
{this.wrappedTopBar()}
<div className={classes.middle}>
<div className={classes.middleLeft}>
......
......@@ -4,6 +4,8 @@ import Typography from '@material-ui/core/Typography';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/MenuSharp';
import CloseIcon from '@material-ui/icons/CloseSharp';
import FullscreenIcon from '@material-ui/icons/FullscreenSharp';
import FullscreenExitIcon from '@material-ui/icons/FullscreenExitSharp';
import Toolbar from '@material-ui/core/Toolbar';
import AppBar from '@material-ui/core/AppBar';
import classNames from 'classnames';
......@@ -23,6 +25,7 @@ export class WindowTopBar extends Component {
render() {
const {
closeWindow, windowId, classes, toggleWindowSideBar, t, manifestTitle,
maximizeWindow, maximized, minimizeWindow,
} = this.props;
return (
<AppBar position="relative">
......@@ -39,6 +42,16 @@ export class WindowTopBar extends Component {
</Typography>
<WindowTopBarButtons windowId={windowId} />
<WindowTopMenuButton className={ns('window-menu-btn')} windowId={windowId} />
<IconButton
color="inherit"
className={ns('window-maximize')}
aria-label={t('maximizeWindow')}
onClick={(maximized ? minimizeWindow : maximizeWindow)}
>
{maximized
? <FullscreenExitIcon />
: <FullscreenIcon />}
</IconButton>
<IconButton
color="inherit"
className={ns('window-close')}
......@@ -55,6 +68,9 @@ export class WindowTopBar extends Component {
WindowTopBar.propTypes = {
manifestTitle: PropTypes.string,
maximizeWindow: PropTypes.func,
maximized: PropTypes.bool,
minimizeWindow: PropTypes.func,
closeWindow: PropTypes.func.isRequired,
windowId: PropTypes.string.isRequired,
classes: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
......@@ -64,5 +80,8 @@ WindowTopBar.propTypes = {
WindowTopBar.defaultProps = {
manifestTitle: '',
maximizeWindow: () => {},
maximized: false,
minimizeWindow: () => {},
t: key => key,
};
......@@ -18,6 +18,9 @@ export class Workspace extends React.Component {
*/
workspaceByType() {
const { workspaceType, windows } = this.props;
if (this.maximizedWindows()) {
return this.maximizedWindows();
}
switch (workspaceType) {
case 'elastic':
return <WorkspaceElastic />;
......@@ -33,6 +36,27 @@ export class Workspace extends React.Component {
}
}
/**
* Determine whether or not there are maximized windows
*/
maximizedWindows() {
const { windows } = this.props;
const windowKeys = Object.keys(windows).sort();
const maximizedWindows = windowKeys
.map(id => windows[id])
.filter(window => window.maximized === true);
if (maximizedWindows.length) {
return Object.values(maximizedWindows).map(window => (
<Window
key={window.id}
window={window}
className={classNames(ns('workspace-maximized-window'))}
/>
));
}
return false;
}
/**
* render
*/
......
......@@ -10,6 +10,7 @@ import { WindowTopBar } from '../components/WindowTopBar';
/** mapStateToProps */
const mapStateToProps = (state, { windowId }) => ({
manifestTitle: getManifestTitle(getWindowManifest(state, windowId)),
maximized: state.windows[windowId].maximized,
});
/**
......@@ -19,6 +20,8 @@ const mapStateToProps = (state, { windowId }) => ({
*/
const mapDispatchToProps = (dispatch, { windowId }) => ({
closeWindow: () => dispatch(actions.closeWindow(windowId)),
maximizeWindow: () => dispatch(actions.maximizeWindow(windowId)),
minimizeWindow: () => dispatch(actions.minimizeWindow(windowId)),
toggleWindowSideBar: () => dispatch(actions.toggleWindowSideBar(windowId)),
});
......
......@@ -15,6 +15,8 @@ const ActionTypes = {
ADD_MANIFEST: 'ADD_MANIFEST',
ADD_WINDOW: 'ADD_WINDOW',
SET_CANVAS: 'SET_CANVAS',
MAXIMIZE_WINDOW: 'MAXIMIZE_WINDOW',
MINIMIZE_WINDOW: 'MINIMIZE_WINDOW',
UPDATE_WINDOW_POSITION: 'UPDATE_WINDOW_POSITION',
SET_WINDOW_SIZE: 'SET_WINDOW_SIZE',
REMOVE_WINDOW: 'REMOVE_WINDOW',
......
......@@ -33,10 +33,29 @@ export function addWindow(options) {
companionWindowIds: [],
rotation: null,
view: 'single',
maximized: false,
};
return { type: ActionTypes.ADD_WINDOW, window: { ...defaultOptions, ...options } };
}
/**
* maximizeWindow
* @param {String} windowId
* @memberof ActionCreators
*/
export function maximizeWindow(windowId, layout) {
return { type: ActionTypes.MAXIMIZE_WINDOW, windowId };
}
/**
* minimizeWindow
* @param {String} windowId
* @memberof ActionCreators
*/
export function minimizeWindow(windowId) {
return { type: ActionTypes.MINIMIZE_WINDOW, windowId };
}
/** */
export function updateWindow(id, payload) {
return { type: ActionTypes.UPDATE_WINDOW, id, payload };
......
......@@ -9,6 +9,23 @@ export const windowsReducer = (state = {}, action) => {
case ActionTypes.ADD_WINDOW:
return { ...state, [action.window.id]: action.window };
case ActionTypes.MAXIMIZE_WINDOW:
return {
...state,
[action.windowId]: {
...state[action.windowId],
maximized: true,
},
};
case ActionTypes.MINIMIZE_WINDOW:
return {
...state,
[action.windowId]: {
...state[action.windowId],
maximized: false,
},
};
case ActionTypes.UPDATE_WINDOW:
return updateIn(state, [action.id], orig => merge(orig, action.payload));
......
......@@ -46,6 +46,13 @@
padding-top: 74px; // The height of the control panel
}
&-workspace-maximized-window {
position: absolute;
left: 0px;
top: 0px;
z-index: 10000;
}
&-workspace-add {
height: 100%;
overflow: auto;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment