From 9eefe93d55a8e85ec16538cedd36ba876a082ecd Mon Sep 17 00:00:00 2001 From: Chris Beer <cabeer@stanford.edu> Date: Thu, 31 Jan 2019 16:00:47 -0800 Subject: [PATCH] Add theme controls to the workspace settings --- __tests__/src/components/App.test.js | 18 +++++++-- .../src/components/WorkspaceSettings.test.js | 9 +++++ src/components/WorkspaceMenu.js | 2 +- src/components/WorkspaceSettings.js | 39 ++++++++++++++++++- src/containers/WorkspaceSettings.js | 31 +++++++++++++++ 5 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 src/containers/WorkspaceSettings.js diff --git a/__tests__/src/components/App.test.js b/__tests__/src/components/App.test.js index 77bf22bb5..049550d33 100644 --- a/__tests__/src/components/App.test.js +++ b/__tests__/src/components/App.test.js @@ -4,13 +4,25 @@ import App from '../../../src/components/App'; describe('App', () => { it('renders without an error', () => { - const wrapper = shallow(<App manifests={[]} workspace={{}} />); + const wrapper = shallow( + <App + manifests={[]} + workspace={{}} + config={{ theme: 'light' }} + />, + ); expect(wrapper.find('div.mirador-app').length).toBe(1); }); describe('FullScreen', () => { - it('is enabled by the workspace.isFullscreenEnabled state', () => { - const wrapper = shallow(<App manifests={[]} workspace={{ isFullscreenEnabled: true }} />); + it('is enabled by the workspace.fullscreen state', () => { + const wrapper = shallow( + <App + manifests={[]} + workspace={{ isFullscreenEnabled: true }} + config={{ theme: 'light' }} + />, + ); expect(wrapper.find('FullScreen').first().prop('enabled')).toEqual(true); }); }); diff --git a/__tests__/src/components/WorkspaceSettings.test.js b/__tests__/src/components/WorkspaceSettings.test.js index 339cc3425..9a265c056 100644 --- a/__tests__/src/components/WorkspaceSettings.test.js +++ b/__tests__/src/components/WorkspaceSettings.test.js @@ -5,19 +5,28 @@ import WorkspaceSettings from '../../../src/components/WorkspaceSettings'; describe('WorkspaceSettings', () => { let wrapper; let handleClose; + let updateConfig; beforeEach(() => { handleClose = jest.fn(); + updateConfig = jest.fn(); wrapper = shallow( <WorkspaceSettings open handleClose={handleClose} + updateConfig={updateConfig} + theme="light" />, ); }); it('renders without an error', () => { expect(wrapper.find('WithStyles(Dialog)').length).toBe(1); + expect(wrapper.find('WithStyles(FormControl)').length).toBe(1); + }); + it('calls updateConfig when selected', () => { + wrapper.instance().handleThemeChange({ target: { value: 'foo' } }); + expect(updateConfig).toHaveBeenCalled(); }); }); diff --git a/src/components/WorkspaceMenu.js b/src/components/WorkspaceMenu.js index 3b8b74a21..bcb016dab 100644 --- a/src/components/WorkspaceMenu.js +++ b/src/components/WorkspaceMenu.js @@ -9,7 +9,7 @@ import SettingsIcon from '@material-ui/icons/Settings'; import ViewHeadlineIcon from '@material-ui/icons/ViewHeadline'; import PropTypes from 'prop-types'; import WindowList from '../containers/WindowList'; -import WorkspaceSettings from './WorkspaceSettings'; +import WorkspaceSettings from '../containers/WorkspaceSettings'; import WorkspaceExport from '../containers/WorkspaceExport'; /** diff --git a/src/components/WorkspaceSettings.js b/src/components/WorkspaceSettings.js index 55aa12ffd..fbd7c3f2c 100644 --- a/src/components/WorkspaceSettings.js +++ b/src/components/WorkspaceSettings.js @@ -2,24 +2,59 @@ import React, { Component } from 'react'; import Dialog from '@material-ui/core/Dialog'; import DialogContent from '@material-ui/core/DialogContent'; import DialogTitle from '@material-ui/core/DialogTitle'; +import FormControl from '@material-ui/core/FormControl'; +import InputLabel from '@material-ui/core/InputLabel'; +import Select from '@material-ui/core/Select'; +import MenuItem from '@material-ui/core/MenuItem'; import PropTypes from 'prop-types'; /** */ class WorkspaceSettings extends Component { + /** + * constructor - + */ + constructor(props) { + super(props); + this.handleThemeChange = this.handleThemeChange.bind(this); + } + + /** + * Propagate theme selection into the global state + */ + handleThemeChange(event) { + const { updateConfig } = this.props; + + updateConfig({ theme: event.target.value }); + } + /** * render * @return */ render() { const { - handleClose, open, children, + handleClose, open, children, theme, } = this.props; return ( <Dialog id="workspace-settings" open={open} onClose={handleClose}> <DialogTitle id="form-dialog-title">Settings</DialogTitle> <DialogContent> {children} + <FormControl> + <InputLabel htmlFor="theme-simple">Theme</InputLabel> + <Select + value={theme} + onChange={this.handleThemeChange} + inputProps={{ + name: 'theme', + id: 'theme-simple', + }} + > + <MenuItem value="light">Light</MenuItem> + <MenuItem value="dark">Dark</MenuItem> + </Select> + </FormControl> </DialogContent> </Dialog> ); @@ -30,6 +65,8 @@ WorkspaceSettings.propTypes = { handleClose: PropTypes.func.isRequired, open: PropTypes.bool, // eslint-disable-line react/forbid-prop-types children: PropTypes.node, + updateConfig: PropTypes.func.isRequired, + theme: PropTypes.string.isRequired, }; WorkspaceSettings.defaultProps = { diff --git a/src/containers/WorkspaceSettings.js b/src/containers/WorkspaceSettings.js new file mode 100644 index 000000000..a52b46300 --- /dev/null +++ b/src/containers/WorkspaceSettings.js @@ -0,0 +1,31 @@ +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import WorkspaceSettings from '../components/WorkspaceSettings'; +import * as actions from '../state/actions'; + +/** + * mapDispatchToProps - used to hook up connect to action creators + * @memberof ManifestListItem + * @private + */ +const mapDispatchToProps = { + updateConfig: actions.updateConfig, +}; + +/** + * mapStateToProps - to hook up connect + * @memberof Workspace + * @private + */ +const mapStateToProps = state => ( + { + theme: state.config.theme, + } +); + +const enhance = compose( + connect(mapStateToProps, mapDispatchToProps), + // further HOC go here +); + +export default enhance(WorkspaceSettings); -- GitLab