Skip to content

Commit

Permalink
ENCD-3546 Create 'save and add' button to add forms (#2100)
Browse files Browse the repository at this point in the history
  • Loading branch information
davisagli authored and caseylitton committed Jan 8, 2018
1 parent ca1208f commit 136bdc8
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 13 deletions.
54 changes: 42 additions & 12 deletions src/encoded/static/components/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import jsonschema from 'jsonschema';
import _ from 'underscore';
import offset from '../libs/offset';
import { FetchedData, Param } from './fetched';
import { parseAndLogError } from './globals';
import { parseAndLogError, listingTitles } from './globals';
import { FileInput, ItemPreview, ObjectPicker } from './inputs';
import Layout from './layout';
import DropdownButton from '../libs/bootstrap/button';
Expand Down Expand Up @@ -791,10 +791,11 @@ export class Form extends React.Component {
componentDidUpdate(prevProps, prevState) {
// If form error state changed, scroll to first error message
// to make sure the user notices it.
if (!_.isEqual(prevState.errors, this.state.errors)) {
const error = document.querySelector('.rf-Message');
if (error) {
window.scrollTo(0, offset(error).top - document.getElementById('navbar').clientHeight);
if (!_.isEqual(prevState.errors, this.state.errors) ||
(this.state.message && (this.state.message !== prevState.message))) {
const message = document.querySelector('.rf-Message,.alert');
if (message) {
window.scrollTo(0, offset(message).top - document.getElementById('navbar').clientHeight);
}
}
}
Expand Down Expand Up @@ -871,6 +872,8 @@ export class Form extends React.Component {
e.preventDefault();
e.stopPropagation();

const button = e.target.getAttribute('data-button');

// Filter out `schema_version` property
const value = filterValue(this.state.value);

Expand All @@ -892,15 +895,17 @@ export class Form extends React.Component {
return response.json();
})
.catch(parseAndLogError.bind(undefined, 'putRequest'))
.then(this.receive);
.then(this.receive.bind(this, button));
// Set `communicating` to true so the Save button becomes disabled.
this.setState({
message: null,
error: null,
communicating: true,
putRequest: request,
});
}

receive(data) {
receive(button, data) {
// Handle a response that is not an HTTP error status.

// Handle server-side validation errors using `this.showErrors`.
Expand All @@ -909,7 +914,7 @@ export class Form extends React.Component {
return this.showErrors(data);
}
// Handle a successful form submission using `this.finish`.
return this.finish(data);
return this.finish(button, data);
}

showErrors(data) {
Expand Down Expand Up @@ -954,7 +959,7 @@ export class Form extends React.Component {
});
}

finish(data) {
finish(button, data) {
// Handle a successful form submission.

// Let the app know navigation is now allowed again
Expand All @@ -965,8 +970,17 @@ export class Form extends React.Component {
this.setState({ unsavedToken: null });
}

// Call the `onFinish` prop, if specified.
if (this.props.onFinish) {
if (button === 'saveAndAdd') {
const context = data['@graph'][0];
const title = listingTitles.lookup(context)({ context });
let message = `Created ${title}`;
if (context.accession && context.accession !== title) {
message += ` with accession ${context.accession}`;
}
message += '.';
this.setState({ message });
} else if (this.props.onFinish) {
// Default action: defer to the `onFinish` prop.
this.props.onFinish(data);
}
}
Expand All @@ -977,6 +991,7 @@ export class Form extends React.Component {
className="rf-Form"
onSubmit={this.save}
>
{this.state.message ? <div className="alert alert-success">{this.state.message}</div> : ''}
<Field
schema={this.props.schema}
value={this.state.value}
Expand All @@ -990,8 +1005,17 @@ export class Form extends React.Component {
onClick={this.save}
disabled={!this.canSave()}
>{this.props.submitLabel}</button>
{' '}
{this.props.showSaveAndAdd ?
<button
data-button="saveAndAdd"
className="btn btn-success"
onClick={this.save}
disabled={!this.canSave()}
>Save & Add Another</button>
: ''}
</div>
{this.state.error ? <div className="rf-Message">{this.state.error}</div> : ''}
{this.state.error ? <div className="alert alert-danger">{this.state.error}</div> : ''}
</form>
);
}
Expand All @@ -1003,6 +1027,7 @@ Form.propTypes = {
schemas: PropTypes.object,
schema: PropTypes.object.isRequired,
showReadOnly: PropTypes.bool,
showSaveAndAdd: PropTypes.bool,
id: PropTypes.string,
method: PropTypes.string.isRequired,
action: PropTypes.string.isRequired,
Expand All @@ -1017,6 +1042,7 @@ Form.defaultProps = {
id: '',
etag: '',
showReadOnly: true,
showSaveAndAdd: false,
submitLabel: 'Save',
};

Expand Down Expand Up @@ -1064,6 +1090,7 @@ export class JSONSchemaForm extends React.Component {
action={this.props.action} method={this.props.method} etag={this.props.etag}
schemas={this.props.schemas} schema={this.state.schema}
defaultValue={this.state.value} showReadOnly={this.props.showReadOnly}
showSaveAndAdd={this.props.showSaveAndAdd}
id={this.props.id} onFinish={this.props.onFinish}
/>);
}
Expand All @@ -1078,13 +1105,16 @@ JSONSchemaForm.propTypes = {
method: PropTypes.string.isRequired,
etag: PropTypes.string,
showReadOnly: PropTypes.bool,
showSaveAndAdd: PropTypes.bool,
id: PropTypes.string,
onFinish: PropTypes.func.isRequired,
};

JSONSchemaForm.defaultProps = {
schemas: null,
context: null,
id: null,
etag: '',
showReadOnly: true,
showSaveAndAdd: false,
};
5 changes: 4 additions & 1 deletion src/encoded/static/components/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ class ItemEdit extends React.Component {
fetchedForm = (
<FetchedData>
<Param name="schemas" url="/profiles/" />
<JSONSchemaForm type={type} action={action} method="POST" onFinish={this.finished} showReadOnly={false} />
<JSONSchemaForm
type={type} action={action} method="POST"
onFinish={this.finished} showReadOnly={false} showSaveAndAdd
/>
</FetchedData>
);
} else { // edit form
Expand Down

0 comments on commit 136bdc8

Please # to comment.