diff --git a/__tests__/src/components/WindowTopMenu.test.js b/__tests__/src/components/WindowTopMenu.test.js new file mode 100644 index 0000000000000000000000000000000000000000..47851603c78bd7d8081aaa8c8192344d094aae13 --- /dev/null +++ b/__tests__/src/components/WindowTopMenu.test.js @@ -0,0 +1,17 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import WindowTopMenu from '../../../src/components/WindowTopMenu'; + +describe('WindowTopMenu', () => { + let wrapper; + let handleClose; + beforeEach(() => { + handleClose = jest.fn(); + wrapper = shallow(<WindowTopMenu windowId="xyz" handleClose={handleClose} />).dive(); + }); + + it('renders without an error', () => { + expect(wrapper.find('WithStyles(Menu)').length).toBe(1); + expect(wrapper.find('Connect(WindowThumbnailSettings)').length).toBe(1); + }); +}); diff --git a/__tests__/src/components/WindowTopMenuButton.test.js b/__tests__/src/components/WindowTopMenuButton.test.js new file mode 100644 index 0000000000000000000000000000000000000000..c016c58da0146cf137c8b53a7c0b93e8f472f78a --- /dev/null +++ b/__tests__/src/components/WindowTopMenuButton.test.js @@ -0,0 +1,20 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import WindowTopMenuButton from '../../../src/components/WindowTopMenuButton'; + +describe('WindowTopMenuButton', () => { + let wrapper; + beforeEach(() => { + wrapper = shallow( + <WindowTopMenuButton classes={{}} windowId="xyz" />, + ).dive(); + }); + + it('renders without an error', () => { + expect(wrapper.find('WithStyles(IconButton)').length).toBe(1); + }); + it('when clicked, updates the state', () => { + wrapper.find('WithStyles(IconButton)').simulate('click', { currentTarget: 'x' }); + expect(wrapper.find('Connect(miradorWithPlugins(WithStyles(WindowTopMenu)))').props().anchorEl).toBe('x'); + }); +}); diff --git a/src/components/WindowTopBar.js b/src/components/WindowTopBar.js index bf5e0527538421b859da2662fc8118efcf9c51b8..a5f61fdb2009164942a846b237c7fb5d3a9dd65e 100644 --- a/src/components/WindowTopBar.js +++ b/src/components/WindowTopBar.js @@ -7,6 +7,7 @@ import IconButton from '@material-ui/core/IconButton'; import MenuIcon from '@material-ui/icons/Menu'; import Toolbar from '@material-ui/core/Toolbar'; import classNames from 'classnames'; +import WindowTopMenuButton from './WindowTopMenuButton'; import WindowTopBarButtons from '../containers/WindowTopBarButtons'; import ns from '../config/css-ns'; @@ -48,6 +49,7 @@ class WindowTopBar extends Component { {this.titleContent()} </Typography> <WindowTopBarButtons windowId={windowId} /> + <WindowTopMenuButton className={ns('window-menu-btn')} windowId={windowId} /> <Button color="inherit" className={ns('window-close')} aria-label="Close Window" onClick={removeWindow}>×</Button> </Toolbar> ); diff --git a/src/components/WindowTopMenu.js b/src/components/WindowTopMenu.js new file mode 100644 index 0000000000000000000000000000000000000000..15aa2c458d27ad1b8e13352693377515c7e56f28 --- /dev/null +++ b/src/components/WindowTopMenu.js @@ -0,0 +1,59 @@ +import React, { Component } from 'react'; +import { compose } from 'redux'; +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'; + +/** + */ +class WindowTopMenu extends Component { + /** + * constructor - + */ + constructor(props) { + super(props); + this.state = { + }; + } + + /** + * render + * @return + */ + render() { + const { handleClose, anchorEl, windowId } = this.props; + // const {} = this.state; + + return ( + <> + <Menu id={`window-menu_${windowId}`} anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose}> + <Divider /> + </Menu> + </> + ); + } +} + +WindowTopMenu.propTypes = { + windowId: PropTypes.string.isRequired, + handleClose: PropTypes.func.isRequired, + anchorEl: PropTypes.object, // eslint-disable-line react/forbid-prop-types +}; + +WindowTopMenu.defaultProps = { + anchorEl: null, +}; + +/** + * @private + */ +const styles = theme => ({ +}); + +const enhance = compose( + withStyles(styles), + // further HOC go here +); + +export default enhance(WindowTopMenu); diff --git a/src/components/WindowTopMenuButton.js b/src/components/WindowTopMenuButton.js new file mode 100644 index 0000000000000000000000000000000000000000..a8b66b249e84f772ca3e55f0f7670382e37851a7 --- /dev/null +++ b/src/components/WindowTopMenuButton.js @@ -0,0 +1,92 @@ +import React, { Component } from 'react'; +import { compose } from 'redux'; +import IconButton from '@material-ui/core/IconButton'; +import MoreVertIcon from '@material-ui/icons/MoreVert'; +import { withStyles } from '@material-ui/core/styles'; +import PropTypes from 'prop-types'; +import WindowTopMenu from '../containers/WindowTopMenu'; + +/** + */ +class WindowTopMenuButton extends Component { + /** + * constructor - + */ + constructor(props) { + super(props); + this.state = { + anchorEl: null, + }; + this.handleMenuClick = this.handleMenuClick.bind(this); + this.handleMenuClose = this.handleMenuClose.bind(this); + } + + /** + * @private + */ + handleMenuClick(event) { + this.setState({ + anchorEl: event.currentTarget, + }); + } + + /** + * @private + */ + handleMenuClose() { + this.setState({ + anchorEl: null, + }); + } + + /** + * render + * @return + */ + render() { + const { classes, windowId } = this.props; + const { anchorEl } = this.state; + + return ( + <> + <IconButton + color="primary" + aria-label="Menu" + className={classes.ctrlBtn} + aria-haspopup="true" + onClick={this.handleMenuClick} + aria-owns={anchorEl ? `window-menu_${windowId}` : undefined} + > + <MoreVertIcon /> + </IconButton> + <WindowTopMenu + windowId={windowId} + anchorEl={anchorEl} + handleClose={this.handleMenuClose} + /> + </> + ); + } +} + +WindowTopMenuButton.propTypes = { + windowId: PropTypes.string.isRequired, + classes: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types +}; + +/** + * @private + */ +const styles = theme => ({ + ctrlBtn: { + margin: theme.spacing.unit, + }, +}); + + +const enhance = compose( + withStyles(styles), + // further HOC go here +); + +export default enhance(WindowTopMenuButton); diff --git a/src/containers/WindowTopMenu.js b/src/containers/WindowTopMenu.js new file mode 100644 index 0000000000000000000000000000000000000000..cd163f2f530e6929e8cb3b268f4b2e7bc56cb4ae --- /dev/null +++ b/src/containers/WindowTopMenu.js @@ -0,0 +1,4 @@ +import miradorWithPlugins from '../lib/miradorWithPlugins'; +import WindowTopMenu from '../components/WindowTopMenu'; + +export default miradorWithPlugins(WindowTopMenu);