Skip to content
Snippets Groups Projects
Commit f5423b4e authored by Chris Beer's avatar Chris Beer
Browse files

Style the add resource form

parent b287d164
No related branches found
No related tags found
No related merge requests found
import React from 'react';
import { shallow } from 'enzyme';
import ManifestForm from '../../../src/components/ManifestForm';
/** create wrapper */
function createWrapper(props) {
return shallow(
<ManifestForm
fetchManifest={() => {}}
t={str => str}
{...props}
/>,
);
}
describe('ManifestForm', () => {
it('renders', () => {
const wrapper = createWrapper();
expect(wrapper.find('TextField[label="addManifestUrl"]').length).toBe(1);
expect(wrapper.find('WithStyles(Button)[type="submit"]').length).toBe(1);
});
it('has a cancel button when a cancel action is provided', () => {
const onCancel = jest.fn();
const wrapper = createWrapper({ onCancel });
expect(wrapper.find('WithStyles(Button)[onClick]').length).toBe(1);
wrapper.find('WithStyles(Button)[onClick]').simulate('click');
expect(onCancel).toHaveBeenCalled();
});
it('triggers an action when the form is submitted', () => {
const fetchManifest = jest.fn();
const wrapper = createWrapper({ fetchManifest });
wrapper.setState({ formValue: 'http://example.com/iiif' });
wrapper.find('form').simulate('submit', { preventDefault: () => {} });
expect(fetchManifest).toHaveBeenCalledWith('http://example.com/iiif');
});
});
......@@ -13,7 +13,7 @@ function createWrapper(props) {
t={str => str}
{...props}
/>,
);
).dive();
}
describe('WorkspaceAddButton', () => {
......@@ -29,4 +29,33 @@ describe('WorkspaceAddButton', () => {
wrapper.find('Connect(LoadNamespace(WithStyles(ManifestListItem)))').first().props().handleClose();
expect(setWorkspaceAddVisibility).toHaveBeenCalledWith(false);
});
it('has a button to add new resources', () => {
const wrapper = createWrapper();
expect(wrapper.find('WithStyles(Fab)').length).toBe(1);
wrapper.find('WithStyles(Fab)').simulate('click');
expect(wrapper.state().addResourcesOpen).toBe(true);
expect(wrapper.find('WithStyles(Fab)').props().disabled).toBe(true);
});
it('has a toggle-able drawer to add new resources', () => {
const wrapper = createWrapper();
wrapper.setState({ addResourcesOpen: true });
expect(wrapper.find('WithStyles(Drawer)').props().open).toBe(true);
expect(wrapper.find('WithStyles(Drawer) WithStyles(Typography)').dive().dive().text()).toBe('addResource');
wrapper.find('WithStyles(Drawer) WithStyles(AppBar)').simulate('click');
expect(wrapper.find('WithStyles(Drawer)').props().open).toBe(false);
});
it('passes a cancel action through to the form', () => {
const wrapper = createWrapper();
wrapper.setState({ addResourcesOpen: true });
expect(wrapper.find('WithStyles(Drawer) Connect(LoadNamespace(ManifestForm))').length).toBe(1);
wrapper.find('WithStyles(Drawer) Connect(LoadNamespace(ManifestForm))').props().onCancel();
expect(wrapper.find('WithStyles(Drawer)').props().open).toBe(false);
});
});
......@@ -2,16 +2,20 @@
"translation": {
"aboutThisItem": "About this item",
"add": "Add",
"addManifestUrl": "Resource location",
"addManifestUrlHelp": "The URL of a IIIF resource",
"addResource": "Add resource",
"addedFromUrl": "(Added from URL)",
"book": "Book",
"bottom": "Bottom",
"cancel": "Cancel",
"closeInfoCompanionWindow": "Close information companion window",
"closeMenu": "Close Menu",
"closeWindow": "Close window",
"dark": "Dark",
"downloadExport": "Download/Export",
"downloadExportWorkspace": "Download/export workspace",
"fetchManifest": "Fetch Manifest",
"fetchManifest": "Add",
"fullScreen": "Full Screen",
"light": "Light",
"listAllOpenWindows": "List all open windows",
......
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Button from '@material-ui/core/Button';
import Grid from '@material-ui/core/Grid';
import TextField from '@material-ui/core/TextField';
/**
* Provides a form for user input of a manifest url
......@@ -50,16 +53,33 @@ class ManifestForm extends Component {
*/
render() {
const { formValue } = this.state;
const { t } = this.props;
const { t, onCancel } = this.props;
return (
<form onSubmit={this.formSubmit}>
<input
<Grid container spacing={24}>
<Grid item sm={9}>
<TextField
fullWidth
value={formValue}
id="manifestURL"
type="text"
onChange={this.handleInputChange}
variant="filled"
label={t('addManifestUrl')}
helperText={t('addManifestUrlHelp')}
/>
<button id="fetchBtn" type="submit">{t('fetchManifest')}</button>
</Grid>
<Grid item sm={3}>
{ onCancel && (
<Button onClick={onCancel}>
{t('cancel')}
</Button>
)}
<Button id="fetchBtn" type="submit" variant="contained" color="primary">
{t('fetchManifest')}
</Button>
</Grid>
</Grid>
</form>
);
}
......@@ -67,11 +87,13 @@ class ManifestForm extends Component {
ManifestForm.propTypes = {
fetchManifest: PropTypes.func.isRequired,
onCancel: PropTypes.func,
t: PropTypes.func,
};
ManifestForm.defaultProps = {
t: key => key,
onCancel: null,
};
export default ManifestForm;
import React from 'react';
import PropTypes from 'prop-types';
import AddIcon from '@material-ui/icons/Add';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import AppBar from '@material-ui/core/AppBar';
import Drawer from '@material-ui/core/Drawer';
import Fab from '@material-ui/core/Fab';
import IconButton from '@material-ui/core/IconButton';
import Paper from '@material-ui/core/Paper';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import { withStyles } from '@material-ui/core/styles';
import ns from '../config/css-ns';
import ManifestForm from '../containers/ManifestForm';
import ManifestListItem from '../containers/ManifestListItem';
......@@ -11,11 +20,30 @@ import ManifestListItem from '../containers/ManifestListItem';
* @private
*/
class WorkspaceAdd extends React.Component {
/** */
constructor(props) {
super(props);
this.state = { addResourcesOpen: false };
this.setAddResourcesVisibility = this.setAddResourcesVisibility.bind(this);
}
/**
* @private
*/
setAddResourcesVisibility(bool) {
this.setState({ addResourcesOpen: bool });
}
/**
* render
*/
render() {
const { manifests, setWorkspaceAddVisibility } = this.props;
const {
manifests, setWorkspaceAddVisibility, t, classes,
} = this.props;
const { addResourcesOpen } = this.state;
const manifestList = Object.keys(manifests).map(manifest => (
<ManifestListItem
......@@ -29,10 +57,15 @@ class WorkspaceAdd extends React.Component {
<div className={ns('workspace-add')}>
{manifestList}
<Fab variant="extended" disabled={addResourcesOpen} className={classes.fab} color="primary" onClick={() => (this.setAddResourcesVisibility(true))}>
<AddIcon />
{t('addResource')}
</Fab>
<Drawer
variant="permanent"
open
variant="persistent"
anchor="bottom"
open={addResourcesOpen}
PaperProps={{ style: { position: 'absolute', left: 100 } }}
ModalProps={{
disablePortal: true,
......@@ -40,9 +73,21 @@ class WorkspaceAdd extends React.Component {
style: { position: 'absolute' },
}}
>
<ManifestForm
id="add-form"
/>
<Paper
className={classes.form}
>
<AppBar position="absolute" color="primary" onClick={() => (this.setAddResourcesVisibility(false))}>
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label={t('closeMenu')}>
<ExpandMoreIcon />
</IconButton>
<Typography variant="h2" noWrap color="inherit" className={classes.typographyBody}>
{t('addResource')}
</Typography>
</Toolbar>
</AppBar>
<ManifestForm onCancel={() => (this.setAddResourcesVisibility(false))} />
</Paper>
</Drawer>
</div>
);
......@@ -52,6 +97,36 @@ class WorkspaceAdd extends React.Component {
WorkspaceAdd.propTypes = {
manifests: PropTypes.instanceOf(Object).isRequired,
setWorkspaceAddVisibility: PropTypes.func.isRequired,
classes: PropTypes.object, // eslint-disable-line react/forbid-prop-types
t: PropTypes.func,
};
export default WorkspaceAdd;
WorkspaceAdd.defaultProps = {
classes: {},
t: key => key,
};
/** */
const styles = theme => ({
form: {
...theme.mixins.gutters(),
paddingTop: theme.spacing.unit * 2,
paddingBottom: theme.spacing.unit * 2,
marginTop: 64,
},
fab: {
position: 'absolute',
bottom: theme.spacing.unit * 2,
right: theme.spacing.unit * 2,
},
typographyBody: {
flexGrow: 1,
fontSize: '1em',
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
});
export default withStyles(styles)(WorkspaceAdd);
import { compose } from 'redux';
import { connect } from 'react-redux';
import { withNamespaces } from 'react-i18next';
import * as actions from '../state/actions';
import WorkspaceAdd from '../components/WorkspaceAdd';
......@@ -19,6 +20,7 @@ const mapDispatchToProps = { setWorkspaceAddVisibility: actions.setWorkspaceAddV
const enhance = compose(
connect(mapStateToProps, mapDispatchToProps),
withNamespaces(),
// further HOC go here
);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment