Skip to content
Snippets Groups Projects
Unverified Commit 6b1d1af0 authored by Camille Villa's avatar Camille Villa Committed by GitHub
Browse files

Merge pull request #1755 from ProjectMirador/1648-themable-mui

Set up basic theming using light and dark themes 
parents e890da44 a197f241
Branches
Tags
No related merge requests found
......@@ -4,14 +4,26 @@ import App from '../../../src/components/App';
describe('App', () => {
it('renders without an error', () => {
const wrapper = shallow(<App manifests={[]} workspace={{}} />);
expect(wrapper.find('div.mirador-app').length).toBe(1);
const wrapper = shallow(
<App
manifests={[]}
workspace={{}}
config={{ theme: 'light' }}
/>,
);
expect(wrapper.dive().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 }} />);
expect(wrapper.find('FullScreen').first().prop('enabled')).toEqual(true);
it('is enabled by the workspace.fullscreen state', () => {
const wrapper = shallow(
<App
manifests={[]}
workspace={{ isFullscreenEnabled: true }}
config={{ theme: 'light' }}
/>,
);
expect(wrapper.dive().find('FullScreen').first().prop('enabled')).toEqual(true);
});
});
});
......@@ -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();
});
});
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import CssBaseline from '@material-ui/core/CssBaseline';
import classNames from 'classnames';
import { MuiThemeProvider, createMuiTheme, withStyles } from '@material-ui/core/styles';
import Fullscreen from 'react-fullscreen-crossbrowser';
import WorkspaceControlPanel from './WorkspaceControlPanel';
import Workspace from '../containers/Workspace';
......@@ -16,24 +17,38 @@ class App extends Component {
* @return {String} - HTML markup for the component
*/
render() {
const { workspace, setWorkspaceFullscreen } = this.props;
const {
workspace, setWorkspaceFullscreen, config, classes,
} = this.props;
const theme = createMuiTheme({
palette: {
type: config.theme,
},
typography: {
useNextVariants: true,
},
});
return (
<div className={ns('app')}>
<CssBaseline />
<Fullscreen
enabled={workspace.isFullscreenEnabled}
onChange={isFullscreenEnabled => setWorkspaceFullscreen(isFullscreenEnabled)}
>
<Workspace />
</Fullscreen>
<WorkspaceControlPanel />
<div className={classNames(classes.background, ns('app'))}>
<MuiThemeProvider theme={theme}>
<Fullscreen
enabled={workspace.isFullscreenEnabled}
onChange={isFullscreenEnabled => setWorkspaceFullscreen(isFullscreenEnabled)}
>
<Workspace />
</Fullscreen>
<WorkspaceControlPanel />
</MuiThemeProvider>
</div>
);
}
}
App.propTypes = {
config: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
workspace: PropTypes.object, // eslint-disable-line react/forbid-prop-types
classes: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types,
setWorkspaceFullscreen: PropTypes.func,
};
......@@ -42,4 +57,14 @@ App.defaultProps = {
setWorkspaceFullscreen: () => {},
};
export default App;
/**
Material UI style overrides
@private
*/
const styles = theme => ({
background: {
background: theme.palette.background.default,
},
});
export default withStyles(styles)(App);
......@@ -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';
/**
......
......@@ -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 = {
......
export default {
theme: 'light', // dark also available
windows: [],
thumbnailNavigation: {
defaultPosition: 'bottom',
......
......@@ -10,6 +10,7 @@ import App from '../components/App';
*/
const mapStateToProps = state => (
{
config: state.config,
workspace: state.workspace,
manifests: state.manifests,
}
......
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);
@import 'variables';
body {
background: $white;
height: 100%;
}
.mirador {
&-workspace {
bottom: 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment