Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2079: Disable submit buttons and adds error notification #2096

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"react-day-picker": "^7.0.7",
"react-dom": "^15.4.0",
"react-select": "^2.0.0",
"react-toastify": "^4.5.2",
"scriptjs": "^2.5.7",
"shivie8": "^1.0.0",
"source-map-support": "^0.4.6",
Expand Down
3 changes: 3 additions & 0 deletions src/clincoded/static/components/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import url from 'url';
import { ToastContainer } from 'react-toastify';
import { content_views } from './globals';
import { Auth0, HistoryAndTriggers } from './mixins';
import { NavbarMixin, Nav, Navbar, NavItem } from '../libs/bootstrap/navigation';
Expand Down Expand Up @@ -268,13 +269,15 @@ var App = module.exports = createReactClass({
<script data-prop-name="inline" dangerouslySetInnerHTML={{__html: this.props.inline}}></script>
<link rel="stylesheet" href="@@cssFile" />
<link rel="stylesheet" href="https://unpkg.com/react-day-picker/lib/style.css" />
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/ReactToastify.css" />
<script src="@@bundleJsFile"></script>
</head>
<body onClick={this.handleClick} onSubmit={this.handleSubmit} className={this.state.demoWarning ? "demo-background" : ""}>
<script data-prop-name="context" type="application/ld+json" dangerouslySetInnerHTML={{
__html: '\n\n' + jsonScriptEscape(JSON.stringify(this.props.context)) + '\n\n'
}}></script>
<div>
<ToastContainer />
<Header session={this.state.session} href={this.props.href} affiliation={affiliation} />
{this.state.demoWarning ?
<Notice noticeType='demo' noticeMessage={<span><strong>Note:</strong> This is a demo version of the site. Data entered will be deleted upon release of updated versions, which occurs roughly once per month. Please contact us with any questions at <a href="mailto:[email protected]" style={{color: '#FFFFFF'}}>[email protected] <i className="icon icon-envelope"></i></a></span>} />
Expand Down
18 changes: 14 additions & 4 deletions src/clincoded/static/components/case_control_curation.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { RestMixin } from './rest';
import { Form, FormMixin, Input } from '../libs/bootstrap/form';
import { PanelGroup, Panel } from '../libs/bootstrap/panel';
import { parsePubmed } from '../libs/parse-pubmed';
import { showErrorNotification } from '../libs/error_notification';
import * as methods from './methods';
import * as CaseControlEvalScore from './case_control/evaluation_score';
import * as CuratorHistory from './curator_history';
Expand Down Expand Up @@ -1557,6 +1558,12 @@ var CaseControlViewer = createReactClass({
window.location.href = '/curation-central/?gdm=' + tempGdm.uuid + '&pmid=' + tempPmid;
},

handleScoreSubmitError: function(err) {
this.setState({ submitBusy: false });
showErrorNotification();
console.log('Case-control score submit error: ', err);
},

scoreSubmit: function(e) {
let caseControl = this.props.context;
/*****************************************************/
Expand All @@ -1572,10 +1579,11 @@ var CaseControlViewer = createReactClass({
// Update and create score object when the score object has the scoreStatus key/value pair
if (this.state.userScoreObj.uuid) {
return this.putRestData('/evidencescore/' + this.state.userScoreObj.uuid, newUserScoreObj).then(modifiedScoreObj => {
this.setState({submitBusy: false});
return Promise.resolve(modifiedScoreObj['@graph'][0]['@id']);
}).then(data => {
this.handlePageRedirect();
}).catch(err => {
this.handleScoreSubmitError(err);
});
} else {
return this.postRestData('/evidencescore/', newUserScoreObj).then(newScoreObject => {
Expand All @@ -1596,12 +1604,13 @@ var CaseControlViewer = createReactClass({
newCaseControl.scores.push(newScoreObjectUuid);

return this.putRestData('/casecontrol/' + caseControl.uuid, newCaseControl).then(updatedCaseControlObj => {
this.setState({submitBusy: false});
return Promise.resolve(updatedCaseControlObj['@graph'][0]);
});
});
}).then(data => {
this.handlePageRedirect();
}).catch(err => {
this.handleScoreSubmitError(err);
});
}
} else if (Object.keys(newUserScoreObj).length && !newUserScoreObj.hasOwnProperty('score')) {
Expand Down Expand Up @@ -1633,12 +1642,13 @@ var CaseControlViewer = createReactClass({
});
}
return this.putRestData('/casecontrol/' + caseControl.uuid, newCaseControl).then(updatedCaseControlObj => {
this.setState({submitBusy: false});
return Promise.resolve(updatedCaseControlObj['@graph'][0]);
});
});
}).then(data => {
this.handlePageRedirect();
}).catch(err => {
this.handleScoreSubmitError(err);
});
}
}
Expand Down Expand Up @@ -2118,7 +2128,7 @@ var CaseControlViewer = createReactClass({
</Panel>
<Panel title="Case-Control Score" panelClassName="case-control-evidence-score-viewer" open>
{isEvidenceScored || (!isEvidenceScored && affiliation && affiliatedCaseControl) || (!isEvidenceScored && !affiliation && userCaseControl) ?
<ScoreCaseControl evidence={context} evidenceType="Case control" session={this.props.session}
<ScoreCaseControl evidence={context} evidenceType="Case control" session={this.props.session} submitBusy={this.state.submitBusy}
handleUserScoreObj={this.handleUserScoreObj} scoreSubmit={this.scoreSubmit} affiliation={affiliation}
isDisabled={this.state.scoreDisabled} />
: null}
Expand Down
15 changes: 11 additions & 4 deletions src/clincoded/static/components/create_gene_disease.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ var CreateGeneDisease = createReactClass({
diseaseUuid: null,
diseaseError: null,
adjectives: [],
adjectiveDisabled: true
adjectiveDisabled: true,
submitBusy: false,
};
},

Expand Down Expand Up @@ -113,6 +114,7 @@ var CreateGeneDisease = createReactClass({
this.saveFormValue('moiAdjective', moiAdjectiveValue);
}
if (this.validateForm()) {
this.setState({ submitBusy: true });
// Get the free-text values for the Orphanet ID and the Gene ID to check against the DB
/**
* FIXME: Need to delete orphanet reference
Expand All @@ -128,7 +130,10 @@ var CreateGeneDisease = createReactClass({
this.getRestDatas([
'/genes/' + geneId
], [
function() { this.setFormErrors('hgncgene', 'HGNC gene symbol not found'); }.bind(this)
function() {
this.setState({ submitBusy: false });
this.setFormErrors('hgncgene', 'HGNC gene symbol not found');
}.bind(this)
]).then(response => {
return this.getRestData('/search?type=disease&diseaseId=' + diseaseObj.diseaseId).then(diseaseSearch => {
let diseaseUuid;
Expand Down Expand Up @@ -189,13 +194,14 @@ var CreateGeneDisease = createReactClass({
});
} else {
// Found matching GDM. See of the user wants to curate it.
this.setState({gdm: gdmSearch['@graph'][0]});
this.setState({ gdm: gdmSearch['@graph'][0], submitBusy: false });
this.child.openModal();
}
});
}).catch(e => {
// Some unexpected error happened
parseAndLogError.bind(undefined, 'fetchedRequest');
this.setState({ submitBusy: false });
});
}
},
Expand Down Expand Up @@ -230,6 +236,7 @@ var CreateGeneDisease = createReactClass({
let adjectiveDisabled = this.state.adjectiveDisabled;
const moiKeys = Object.keys(modesOfInheritance);
let gdm = this.state.gdm;
const { submitBusy } = this.state;

return (
<div className="container">
Expand Down Expand Up @@ -267,7 +274,7 @@ var CreateGeneDisease = createReactClass({
</Input>
<div><p className="alert alert-warning">The above options (gene, disease, mode of inheritance, or adjective) can be altered for a Gene:Disease record up until a PMID has been added to the record. This includes
adding an adjective to a Gene:Disease:Mode of inheritance record that has already been created or editing an adjective associated with a record.</p></div>
<Input type="submit" inputClassName="btn-default pull-right" id="submit" />
<Input type="submit" inputClassName="btn-default pull-right" submitBusy={submitBusy} id="submit" />
</div>
</Form>
{gdm && gdm.gene && gdm.disease && gdm.modeInheritance ?
Expand Down
18 changes: 14 additions & 4 deletions src/clincoded/static/components/experimental_curation.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { curator_page, content_views, history_views, queryKeyValue, dbxref_prefi
import { RestMixin } from './rest';
import { Form, FormMixin, Input } from '../libs/bootstrap/form';
import { PanelGroup, Panel } from '../libs/bootstrap/panel';
import { showErrorNotification } from '../libs/error_notification';
import { AddResourceId } from './add_external_resource';
import * as CuratorHistory from './curator_history';
import * as methods from './methods';
Expand Down Expand Up @@ -2571,6 +2572,12 @@ const ExperimentalViewer = createReactClass({
window.location.href = '/curation-central/?gdm=' + tempGdm.uuid + '&pmid=' + tempPmid;
},

handleScoreSubmitError: function(err) {
this.setState({ submitBusy: false });
showErrorNotification();
console.log('Experimental score submit error: ', err);
},

// Handle the score submit button
scoreSubmit: function(e) {
let experimental = this.props.context;
Expand All @@ -2592,10 +2599,11 @@ const ExperimentalViewer = createReactClass({
// Update and create score object when the score object has the scoreStatus key/value pair
if (this.state.userScoreObj.uuid) {
return this.putRestData('/evidencescore/' + this.state.userScoreObj.uuid, newUserScoreObj).then(modifiedScoreObj => {
this.setState({submitBusy: false});
return Promise.resolve(modifiedScoreObj['@graph'][0]['@id']);
}).then(data => {
this.handlePageRedirect();
}).catch(err => {
this.handleScoreSubmitError(err);
});
} else {
return this.postRestData('/evidencescore/', newUserScoreObj).then(newScoreObject => {
Expand All @@ -2616,12 +2624,13 @@ const ExperimentalViewer = createReactClass({
newExperimental.scores.push(newScoreObjectUuid);

return this.putRestData('/experimental/' + experimental.uuid, newExperimental).then(updatedExperimentalObj => {
this.setState({submitBusy: false});
return Promise.resolve(updatedExperimentalObj['@graph'][0]);
});
});
}).then(data => {
this.handlePageRedirect();
}).catch(err => {
this.handleScoreSubmitError(err);
});
}
} else if (!newUserScoreObj.scoreStatus) {
Expand Down Expand Up @@ -2653,12 +2662,13 @@ const ExperimentalViewer = createReactClass({
});
}
return this.putRestData('/experimental/' + experimental.uuid, newExperimental).then(updatedExperimentalObj => {
this.setState({submitBusy: false});
return Promise.resolve(updatedExperimentalObj['@graph'][0]);
});
});
}).then(data => {
this.handlePageRedirect();
}).catch(err => {
this.handleScoreSubmitError(err);
});
}
}
Expand Down Expand Up @@ -3273,7 +3283,7 @@ const ExperimentalViewer = createReactClass({
{isEvidenceScored || (!isEvidenceScored && affiliation && affiliatedExperimental) || (!isEvidenceScored && !affiliation && userExperimental) ?
<ScoreExperimental evidence={experimental} experimentalType={experimental.evidenceType} experimentalEvidenceType={experimentalEvidenceType}
evidenceType="Experimental" session={this.props.session} handleUserScoreObj={this.handleUserScoreObj} scoreSubmit={this.scoreSubmit}
formError={this.state.formError} affiliation={affiliation} />
formError={this.state.formError} affiliation={affiliation} submitBusy={this.state.submitBusy} />
: null}
{!isEvidenceScored && ((affiliation && !affiliatedExperimental) || (!affiliation && !userExperimental)) ?
<div className="row">
Expand Down
18 changes: 14 additions & 4 deletions src/clincoded/static/components/individual_curation.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Form, FormMixin, Input } from '../libs/bootstrap/form';
import { PanelGroup, Panel } from '../libs/bootstrap/panel';
import { parseAndLogError } from './mixins';
import { parsePubmed } from '../libs/parse-pubmed';
import { showErrorNotification } from '../libs/error_notification';
import { AddResourceId } from './add_external_resource';
import * as CuratorHistory from './curator_history';
import * as methods from './methods';
Expand Down Expand Up @@ -1765,6 +1766,12 @@ const IndividualViewer = createReactClass({
window.location.href = '/curation-central/?gdm=' + tempGdm.uuid + '&pmid=' + tempPmid;
},

handleScoreSubmitError: function(err) {
this.setState({ submitBusy: false });
showErrorNotification();
console.log('Individual score submit error: ', err);
},

scoreSubmit: function(e) {
let individual = this.props.context;
/*****************************************************/
Expand Down Expand Up @@ -1794,10 +1801,11 @@ const IndividualViewer = createReactClass({
// Update and create score object when the score object has the scoreStatus key/value pair
if (this.state.userScoreObj.uuid) {
return this.putRestData('/evidencescore/' + this.state.userScoreObj.uuid, newUserScoreObj).then(modifiedScoreObj => {
this.setState({submitBusy: false});
return Promise.resolve(modifiedScoreObj['@graph'][0]['@id']);
}).then(data => {
this.handlePageRedirect();
}).catch(err => {
this.handleScoreSubmitError(err);
});
} else {
return this.postRestData('/evidencescore/', newUserScoreObj).then(newScoreObject => {
Expand All @@ -1818,12 +1826,13 @@ const IndividualViewer = createReactClass({
newIndividual.scores.push(newScoreObjectUuid);

return this.putRestData('/individual/' + individual.uuid, newIndividual).then(updatedIndividualObj => {
this.setState({submitBusy: false});
return Promise.resolve(updatedIndividualObj['@graph'][0]);
});
});
}).then(data => {
this.handlePageRedirect();
}).catch(err => {
this.handleScoreSubmitError(err);
});
}
} else if (!newUserScoreObj.scoreStatus) {
Expand Down Expand Up @@ -1855,12 +1864,13 @@ const IndividualViewer = createReactClass({
});
}
return this.putRestData('/individual/' + individual.uuid, newIndividual).then(updatedIndividualObj => {
this.setState({submitBusy: false});
return Promise.resolve(updatedIndividualObj['@graph'][0]);
});
});
}).then(data => {
this.handlePageRedirect();
}).catch(err => {
this.handleScoreSubmitError(err);
});
}
}
Expand Down Expand Up @@ -2167,7 +2177,7 @@ const IndividualViewer = createReactClass({
<ScoreIndividual evidence={individual} modeInheritance={tempGdm? tempGdm.modeInheritance : null} evidenceType="Individual"
session={this.props.session} handleUserScoreObj={this.handleUserScoreObj} scoreSubmit={this.scoreSubmit}
scoreError={this.state.scoreError} scoreErrorMsg={this.state.scoreErrorMsg} affiliation={affiliation}
variantInfo={variants} gdm={this.state.gdm} pmid={tempPmid ? tempPmid : null} />
variantInfo={variants} gdm={this.state.gdm} pmid={tempPmid ? tempPmid : null} submitBusy={this.state.submitBusy} />
: null}
{!isEvidenceScored && ((affiliation && !affiliatedIndividual) || (!affiliation && !userIndividual)) ?
<div className="row">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ var ScoreCaseControl = module.exports.ScoreCaseControl = createReactClass({
</div>
{this.props.scoreSubmit ?
<div className="curation-submit clearfix">
<Input type="button" inputClassName="btn-primary pull-right" clickHandler={this.props.scoreSubmit}
<Input type="submit" inputClassName="btn-primary pull-right" submitHandler={this.props.scoreSubmit}
title="Save" submitBusy={this.props.submitBusy} />
</div>
: null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ var ScoreExperimental = module.exports.ScoreExperimental = createReactClass({
</div>
{this.props.scoreSubmit ?
<div className="curation-submit clearfix">
<Input type="button" inputClassName="btn-primary pull-right" clickHandler={this.props.scoreSubmit}
<Input type="submit" inputClassName="btn-primary pull-right" submitHandler={this.props.scoreSubmit}
title="Save" submitBusy={this.props.submitBusy} />
</div>
: null}
Expand Down
Loading