From 656160d30a3cd4ff0d816904f193e66a7c5a1045 Mon Sep 17 00:00:00 2001 From: Chris Beer <cabeer@stanford.edu> Date: Thu, 31 Jan 2019 11:49:56 -0800 Subject: [PATCH] Add a WindowThumbnailSettings control to the window's menu --- .../WindowThumbnailSettings.test.js | 27 +++++++ src/components/WindowThumbnailSettings.js | 71 +++++++++++++++++++ src/components/WindowTopMenu.js | 5 ++ src/containers/WindowThumbnailSettings.js | 29 ++++++++ 4 files changed, 132 insertions(+) create mode 100644 __tests__/src/components/WindowThumbnailSettings.test.js create mode 100644 src/components/WindowThumbnailSettings.js create mode 100644 src/containers/WindowThumbnailSettings.js diff --git a/__tests__/src/components/WindowThumbnailSettings.test.js b/__tests__/src/components/WindowThumbnailSettings.test.js new file mode 100644 index 000000000..6453d313c --- /dev/null +++ b/__tests__/src/components/WindowThumbnailSettings.test.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import WindowThumbnailSettings from '../../../src/components/WindowThumbnailSettings'; + +describe('WindowThumbnailSettings', () => { + let wrapper; + const setWindowThumbnailPosition = jest.fn(); + beforeEach(() => { + wrapper = shallow( + <WindowThumbnailSettings + windowId="xyz" + setWindowThumbnailPosition={setWindowThumbnailPosition} + thumbnailNavigationPosition="bottom" + />, + ); + }); + + it('renders without an error', () => { + expect(wrapper.find('WithStyles(Typography)').dive().dive().text()).toBe('Thumbnails'); + expect(wrapper.find('RadioGroup').props().value).toBe('bottom'); + }); + + it('updates state when the thumbnail config selection changes', () => { + wrapper.find('RadioGroup').first().simulate('change', { target: { value: 'off' } }); + expect(setWindowThumbnailPosition).toHaveBeenCalledWith('xyz', 'off'); + }); +}); diff --git a/src/components/WindowThumbnailSettings.js b/src/components/WindowThumbnailSettings.js new file mode 100644 index 000000000..5f49d4ff3 --- /dev/null +++ b/src/components/WindowThumbnailSettings.js @@ -0,0 +1,71 @@ +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 PropTypes from 'prop-types'; + +/** + * + */ +export default class WindowThumbnailSettings extends Component { + /** + * constructor - + */ + constructor(props) { + super(props); + this.state = { + }; + this.handleChange = this.handleChange.bind(this); + } + + /** + * @private + */ + handleChange(event) { + const { windowId, setWindowThumbnailPosition } = this.props; + + setWindowThumbnailPosition(windowId, event.target.value); + } + + /** + * render + * + * @return {type} description + */ + render() { + const { thumbnailNavigationPosition } = this.props; + + return ( + <> + <Typography>Thumbnails</Typography> + <RadioGroup aria-label="position" name="position" value={thumbnailNavigationPosition} onChange={this.handleChange} row> + <FormControlLabel + value="off" + control={<Radio color="primary" />} + label="Off" + labelPlacement="bottom" + /> + <FormControlLabel + value="bottom" + control={<Radio color="primary" />} + label="Bottom" + labelPlacement="bottom" + /> + <FormControlLabel + value="right" + control={<Radio color="primary" />} + label="Right" + labelPlacement="bottom" + /> + </RadioGroup> + </> + ); + } +} + +WindowThumbnailSettings.propTypes = { + windowId: PropTypes.string.isRequired, + setWindowThumbnailPosition: PropTypes.func.isRequired, + thumbnailNavigationPosition: PropTypes.string.isRequired, +}; diff --git a/src/components/WindowTopMenu.js b/src/components/WindowTopMenu.js index 15aa2c458..a7e41a2f8 100644 --- a/src/components/WindowTopMenu.js +++ b/src/components/WindowTopMenu.js @@ -1,9 +1,11 @@ import React, { Component } from 'react'; import { compose } from 'redux'; +import ListItem from '@material-ui/core/ListItem'; import Menu from '@material-ui/core/Menu'; import Divider from '@material-ui/core/Divider'; import { withStyles } from '@material-ui/core/styles'; import PropTypes from 'prop-types'; +import WindowThumbnailSettings from '../containers/WindowThumbnailSettings'; /** */ @@ -28,6 +30,9 @@ class WindowTopMenu extends Component { return ( <> <Menu id={`window-menu_${windowId}`} anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose}> + <ListItem> + <WindowThumbnailSettings windowId={windowId} /> + </ListItem> <Divider /> </Menu> </> diff --git a/src/containers/WindowThumbnailSettings.js b/src/containers/WindowThumbnailSettings.js new file mode 100644 index 000000000..75b0e9472 --- /dev/null +++ b/src/containers/WindowThumbnailSettings.js @@ -0,0 +1,29 @@ +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import * as actions from '../state/actions'; +import WindowThumbnailSettings from '../components/WindowThumbnailSettings'; + +/** + * mapDispatchToProps - used to hook up connect to action creators + * @memberof ManifestListItem + * @private + */ +const mapDispatchToProps = { setWindowThumbnailPosition: actions.setWindowThumbnailPosition }; + +/** + * mapStateToProps - to hook up connect + * @memberof WindowViewer + * @private + */ +const mapStateToProps = (state, props) => ( + { + thumbnailNavigationPosition: state.windows[props.windowId].thumbnailNavigationPosition, + } +); + +const enhance = compose( + connect(mapStateToProps, mapDispatchToProps), + // further HOC go here +); + +export default enhance(WindowThumbnailSettings); -- GitLab