mirror of
https://github.com/ascribe/onion.git
synced 2025-02-14 21:10:27 +01:00
Fix detachment of DOM <-> browser state
This commit is contained in:
parent
56d8268ceb
commit
59244f208a
58
js/components/ascribe_buttons/form_submit_button.js
Normal file
58
js/components/ascribe_buttons/form_submit_button.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react/addons';
|
||||||
|
|
||||||
|
const { string, object } = React.PropTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Originally, this button was introduced for `RegisterPieceForm`.
|
||||||
|
* The underlying problem that lead to the implementation was that multiple `InputFineuploader`s
|
||||||
|
* where displayed in one form.
|
||||||
|
* For the form's submit button always to represent an applicable state we had to save
|
||||||
|
* the ready states of the multiple uploaders in `RegisterPieceForm`.
|
||||||
|
* However, on each invocation of `this.setState`, we were re-rendering the form again,
|
||||||
|
* which caused (if the user had the file-selector open) a detachment between user input and
|
||||||
|
* displayed page.
|
||||||
|
*
|
||||||
|
* This button helps to outsource the state of the form's readiness to another component,
|
||||||
|
* to solve the problem.
|
||||||
|
*/
|
||||||
|
const FormSubmitButton = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
defaultReadyStates: object.isRequired,
|
||||||
|
label: string.isRequired
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
readyStates: this.props.defaultReadyStates
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
setReadyStateForKey(key, state) {
|
||||||
|
const readyStates = React.addons.update(this.state.readyStates, { [key]: { $set: state } });
|
||||||
|
this.setState({ readyStates });
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { label } = this.props;
|
||||||
|
const { readyStates } = this.state;
|
||||||
|
|
||||||
|
// Reduce all readyStates to a single boolean
|
||||||
|
const ready = Object.keys(readyStates)
|
||||||
|
.reduce((defaultState, stateKey) => {
|
||||||
|
return defaultState && readyStates[stateKey];
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-default btn-wide"
|
||||||
|
disabled={!ready}>
|
||||||
|
{label}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default FormSubmitButton;
|
@ -9,6 +9,7 @@ import Form from './form';
|
|||||||
import Property from './property';
|
import Property from './property';
|
||||||
import InputFineUploader from './input_fineuploader';
|
import InputFineUploader from './input_fineuploader';
|
||||||
import UploadButton from '../ascribe_uploader/ascribe_upload_button/upload_button';
|
import UploadButton from '../ascribe_uploader/ascribe_upload_button/upload_button';
|
||||||
|
import FormSubmitButton from '../ascribe_buttons/form_submit_button';
|
||||||
|
|
||||||
import ApiUrls from '../../constants/api_urls';
|
import ApiUrls from '../../constants/api_urls';
|
||||||
import AppConstants from '../../constants/application_constants';
|
import AppConstants from '../../constants/application_constants';
|
||||||
@ -77,9 +78,9 @@ let RegisterPieceForm = React.createClass({
|
|||||||
*/
|
*/
|
||||||
setIsUploadReady(uploaderKey) {
|
setIsUploadReady(uploaderKey) {
|
||||||
return (isUploadReady) => {
|
return (isUploadReady) => {
|
||||||
this.setState({
|
// See documentation of `FormSubmitButton` for more detailed information
|
||||||
[uploaderKey]: isUploadReady
|
// on this.
|
||||||
});
|
this.refs.submitButton.setReadyStateForKey(uploaderKey, isUploadReady);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ let RegisterPieceForm = React.createClass({
|
|||||||
if(validFiles.length > 0) {
|
if(validFiles.length > 0) {
|
||||||
const { type: mimeType } = validFiles[0];
|
const { type: mimeType } = validFiles[0];
|
||||||
const mimeSubType = mimeType && mimeType.split('/').length ? mimeType.split('/')[1]
|
const mimeSubType = mimeType && mimeType.split('/').length ? mimeType.split('/')[1]
|
||||||
: 'unknown';
|
: 'unknown';
|
||||||
const thumbnailKeyDialogExpanded = AppConstants.supportedThumbnailFileFormats.indexOf(mimeSubType) === -1;
|
const thumbnailKeyDialogExpanded = AppConstants.supportedThumbnailFileFormats.indexOf(mimeSubType) === -1;
|
||||||
this.setState({ thumbnailKeyDialogExpanded });
|
this.setState({ thumbnailKeyDialogExpanded });
|
||||||
} else {
|
} else {
|
||||||
@ -122,8 +123,6 @@ let RegisterPieceForm = React.createClass({
|
|||||||
children,
|
children,
|
||||||
enableLocalHashing } = this.props;
|
enableLocalHashing } = this.props;
|
||||||
const { currentUser,
|
const { currentUser,
|
||||||
digitalWorkKeyReady,
|
|
||||||
thumbnailKeyReady,
|
|
||||||
thumbnailKeyDialogExpanded } = this.state;
|
thumbnailKeyDialogExpanded } = this.state;
|
||||||
|
|
||||||
const profileHashLocally = currentUser && currentUser.profile ? currentUser.profile.hash_locally : false;
|
const profileHashLocally = currentUser && currentUser.profile ? currentUser.profile.hash_locally : false;
|
||||||
@ -137,12 +136,13 @@ let RegisterPieceForm = React.createClass({
|
|||||||
url={ApiUrls.pieces_list}
|
url={ApiUrls.pieces_list}
|
||||||
handleSuccess={handleSuccess}
|
handleSuccess={handleSuccess}
|
||||||
buttons={
|
buttons={
|
||||||
<button
|
<FormSubmitButton
|
||||||
type="submit"
|
ref="submitButton"
|
||||||
className="btn btn-default btn-wide"
|
defaultReadyStates={{
|
||||||
disabled={!(digitalWorkKeyReady && thumbnailKeyReady)}>
|
digitalWorkKeyReady: false,
|
||||||
{submitMessage}
|
thumbnailKeyReady: true
|
||||||
</button>
|
}}
|
||||||
|
label={submitMessage}/>
|
||||||
}
|
}
|
||||||
spinner={
|
spinner={
|
||||||
<span className="btn btn-default btn-wide btn-spinner">
|
<span className="btn btn-default btn-wide btn-spinner">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user