Skip to content
Snippets Groups Projects
Commit 0909054b authored by Jack Reed's avatar Jack Reed
Browse files

Setup the ability to select single vs bookview

parent f8e06ee8
Branches 3-qcu-features
No related tags found
No related merge requests found
......@@ -20,6 +20,7 @@ describe('window actions', () => {
thumbnailNavigationPosition: 'bottom',
xywh: [0, 0, 400, 400],
rotation: null,
view: 'single',
},
};
expect(actions.addWindow(options)).toEqual(expectedAction);
......@@ -59,6 +60,18 @@ describe('window actions', () => {
});
});
describe('setWindowViewType', () => {
it('returns the appropriate action type', () => {
const id = 'abc123';
const expectedAction = {
type: ActionTypes.SET_WINDOW_VIEW_TYPE,
windowId: id,
viewType: 'book',
};
expect(actions.setWindowViewType(id, 'book')).toEqual(expectedAction);
});
});
describe('toggleWindowSideBarPanel', () => {
it('returns the appropriate action type', () => {
const windowId = 'abc123';
......
......@@ -4,6 +4,7 @@ import ListItem from '@material-ui/core/ListItem';
import Menu from '@material-ui/core/Menu';
import Divider from '@material-ui/core/Divider';
import WindowThumbnailSettings from '../../../src/containers/WindowThumbnailSettings';
import WindowViewSettings from '../../../src/containers/WindowViewSettings';
import WindowTopMenu from '../../../src/components/WindowTopMenu';
/** create wrapper */
......@@ -22,9 +23,10 @@ describe('WindowTopMenu', () => {
it('renders all needed elements', () => {
const wrapper = createWrapper();
expect(wrapper.find(Menu).length).toBe(1);
expect(wrapper.find(ListItem).length).toBe(1);
expect(wrapper.find(ListItem).length).toBe(2);
expect(wrapper.find(WindowThumbnailSettings).length).toBe(1);
expect(wrapper.find(Divider).length).toBe(1);
expect(wrapper.find(WindowViewSettings).length).toBe(1);
expect(wrapper.find(Divider).length).toBe(2);
});
it('passes windowId to <WindowThumbnailSettings/>', () => {
......
import React from 'react';
import { shallow } from 'enzyme';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import RadioGroup from '@material-ui/core/RadioGroup';
import Typography from '@material-ui/core/Typography';
import WindowViewSettings from '../../../src/components/WindowViewSettings';
/** create wrapper */
function createWrapper(props) {
return shallow(
<WindowViewSettings
windowId="xyz"
setWindowViewType={() => {}}
windowViewType="single"
{...props}
/>,
);
}
describe('WindowViewSettings', () => {
it('renders all elements correctly', () => {
const wrapper = createWrapper();
expect(wrapper.find(Typography).length).toBe(1);
expect(wrapper.find(RadioGroup).length).toBe(1);
const labels = wrapper.find(FormControlLabel);
expect(labels.length).toBe(2);
expect(labels.at(0).props().value).toBe('single');
expect(labels.at(1).props().value).toBe('book');
});
it('should set the correct label active', () => {
let wrapper = createWrapper({ windowViewType: 'single' });
expect(wrapper.find(RadioGroup).props().value).toBe('single');
wrapper = createWrapper({ windowViewType: 'book' });
expect(wrapper.find(RadioGroup).props().value).toBe('book');
});
it('updates state when the view config selection changes', () => {
const setWindowViewType = jest.fn();
const wrapper = createWrapper({ setWindowViewType });
wrapper.find(RadioGroup).first().simulate('change', { target: { value: 'book' } });
expect(setWindowViewType).toHaveBeenCalledWith('xyz', 'book');
wrapper.find(RadioGroup).first().simulate('change', { target: { value: 'single' } });
expect(setWindowViewType).toHaveBeenCalledWith('xyz', 'single');
});
});
......@@ -65,6 +65,24 @@ describe('windows reducer', () => {
expect(reducer(before, action)).toEqual(after);
});
it('should handle SET_WINDOW_VIEW_TYPE by changing the view attribute', () => {
const action = {
type: ActionTypes.SET_WINDOW_VIEW_TYPE,
windowId: 'abc123',
viewType: 'book',
};
const before = {
abc123: { view: 'single' },
abc321: { view: 'book' },
};
const after = {
abc123: { view: 'book' },
abc321: { view: 'book' },
};
expect(reducer(before, action)).toEqual(after);
});
describe('TOGGLE_WINDOW_SIDE_BAR_PANEL', () => {
it('sets the sideBarPanel value to the given value when it was changed', () => {
const action = {
......
......@@ -6,6 +6,7 @@ import {
getManifestCanvases,
getThumbnailNavigationPosition,
getManifestTitle,
getWindowViewType,
} from '../../../src/state/selectors';
......@@ -114,3 +115,27 @@ describe('getManifestTitle', () => {
expect(received).toBeUndefined();
});
});
describe('getWindowViewType', () => {
const state = {
windows: {
a: { id: 'a', view: 'single' },
b: { id: 'b' },
},
};
it('should return view type if window exists', () => {
const received = getWindowViewType(state, 'a');
expect(received).toBe('single');
});
it('should return undefined if view type does not exist in window', () => {
const received = getWindowViewType(state, 'b');
expect(received).toBeUndefined();
});
it('should return undefined if window does not exists', () => {
const received = getWindowViewType(state, 'c');
expect(received).toBeUndefined();
});
});
......@@ -2,6 +2,7 @@
"translation": {
"aboutThisItem": "About this item",
"add": "Add",
"book": "Book",
"bottom": "Bottom",
"closeInfoCompanionWindow": "Close information companion window",
"closeMenu": "Close Menu",
......@@ -19,11 +20,13 @@
"openWindows": "Open windows",
"position": "Position",
"right": "Right",
"single": "Single",
"settings": "Settings",
"theme": "Theme",
"thumbnails": "Thumbnails",
"toggleWindowSideBar": "Toggle window sidebar",
"untitled": "[Untitled]",
"view": "View",
"zoomIn": "Zoom in",
"zoomOut": "Zoom out",
"zoomReset": "Reset zoom"
......
......@@ -4,6 +4,7 @@ import Menu from '@material-ui/core/Menu';
import Divider from '@material-ui/core/Divider';
import PropTypes from 'prop-types';
import WindowThumbnailSettings from '../containers/WindowThumbnailSettings';
import WindowViewSettings from '../containers/WindowViewSettings';
/**
*/
......@@ -19,6 +20,10 @@ class WindowTopMenu extends Component {
return (
<>
<Menu id={`window-menu_${windowId}`} anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose}>
<ListItem>
<WindowViewSettings windowId={windowId} />
</ListItem>
<Divider />
<ListItem>
<WindowThumbnailSettings windowId={windowId} />
</ListItem>
......
import React, { Component } from 'react';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Radio from '@material-ui/core/Radio';
import RadioGroup from '@material-ui/core/RadioGroup';
import Typography from '@material-ui/core/Typography';
import PhotoIcon from '@material-ui/icons/Photo';
import ViewAgendaIcon from '@material-ui/icons/ViewAgenda';
import PropTypes from 'prop-types';
/**
*
*/
export default class WindowViewSettings extends Component {
/**
* constructor -
*/
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
/**
* @private
*/
handleChange(event) {
const { windowId, setWindowViewType } = this.props;
setWindowViewType(windowId, event.target.value);
}
/**
* render
*
* @return {type} description
*/
render() {
const { windowViewType, t } = this.props;
return (
<>
<Typography>{t('view')}</Typography>
<RadioGroup aria-label={t('position')} name="position" value={windowViewType} onChange={this.handleChange} row>
<FormControlLabel
value="single"
control={<Radio color="primary" icon={<PhotoIcon />} checkedIcon={<PhotoIcon />} />}
label={t('single')}
labelPlacement="bottom"
/>
<FormControlLabel
value="book"
control={<Radio color="primary" icon={<ViewAgendaIconRotated />} checkedIcon={<ViewAgendaIconRotated />} />}
label={t('book')}
labelPlacement="bottom"
/>
</RadioGroup>
</>
);
}
}
/**
* @private
*/
function ViewAgendaIconRotated(props) {
return (
<ViewAgendaIcon style={{ transform: 'rotate(-90deg)' }} />
);
}
WindowViewSettings.propTypes = {
windowId: PropTypes.string.isRequired,
setWindowViewType: PropTypes.func.isRequired,
windowViewType: PropTypes.string.isRequired,
t: PropTypes.func,
};
WindowViewSettings.defaultProps = {
t: key => key,
};
import { compose } from 'redux';
import { connect } from 'react-redux';
import { withNamespaces } from 'react-i18next';
import miradorWithPlugins from '../lib/miradorWithPlugins';
import * as actions from '../state/actions';
import { getWindowViewType } from '../state/selectors';
import WindowViewSettings from '../components/WindowViewSettings';
/**
* mapDispatchToProps - used to hook up connect to action creators
* @memberof ManifestListItem
* @private
*/
const mapDispatchToProps = { setWindowViewType: actions.setWindowViewType };
/**
* mapStateToProps - to hook up connect
* @memberof WindowViewer
* @private
*/
const mapStateToProps = (state, props) => (
{
windowViewType: getWindowViewType(state, props.windowId),
}
);
const enhance = compose(
connect(mapStateToProps, mapDispatchToProps),
withNamespaces(),
miradorWithPlugins,
// further HOC go here
);
export default enhance(WindowViewSettings);
......@@ -13,6 +13,7 @@ const ActionTypes = {
RECEIVE_MANIFEST_FAILURE: 'RECEIVE_MANIFEST_FAILURE',
SET_CONFIG: 'SET_CONFIG',
SET_WINDOW_THUMBNAIL_POSITION: 'SET_WINDOW_THUMBNAIL_POSITION',
SET_WINDOW_VIEW_TYPE: 'SET_WINDOW_VIEW_TYPE',
TOGGLE_WINDOW_SIDE_BAR: 'TOGGLE_WINDOW_SIDE_BAR',
TOGGLE_WINDOW_SIDE_BAR_PANEL: 'TOGGLE_WINDOW_SIDE_BAR_PANEL',
TOGGLE_ZOOM_CONTROLS: 'TOGGLE_ZOOM_CONTROLS',
......
......@@ -27,6 +27,7 @@ export function addWindow(options) {
thumbnailNavigationPosition: 'bottom', // bottom by default in settings.js
xywh: [0, 0, 400, 400],
rotation: null,
view: 'single',
};
return { type: ActionTypes.ADD_WINDOW, window: { ...defaultOptions, ...options } };
}
......@@ -72,3 +73,14 @@ export function toggleWindowSideBarPanel(windowId, panelType) {
export function setWindowThumbnailPosition(windowId, position) {
return { type: ActionTypes.SET_WINDOW_THUMBNAIL_POSITION, windowId, position };
}
/**
* setWindowViewType - action creator
*
* @param {String} windowId
* @param {String} viewType
* @memberof ActionCreators
*/
export function setWindowViewType(windowId, viewType) {
return { type: ActionTypes.SET_WINDOW_VIEW_TYPE, windowId, viewType };
}
......@@ -22,7 +22,14 @@ const windowsReducer = (state = {}, action) => {
sideBarOpen: !state[action.windowId].sideBarOpen,
},
};
case ActionTypes.SET_WINDOW_VIEW_TYPE:
return {
...state,
[action.windowId]: {
...state[action.windowId],
view: action.viewType,
},
};
case ActionTypes.SET_WINDOW_THUMBNAIL_POSITION:
return {
...state,
......
......@@ -54,3 +54,12 @@ export function getManifestTitle(manifest) {
&& manifest.manifestation
&& manifest.manifestation.getLabel().map(label => label.value)[0];
}
/** Return type of view in a certain window.
* @param {object} state
* @param {String} windowId
* @param {String}
*/
export function getWindowViewType(state, windowId) {
return state.windows[windowId] && state.windows[windowId].view;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment