1
0
mirror of https://github.com/ascribe/onion.git synced 2024-06-25 18:56:28 +02:00

Fix detachment of DOM <-> browser state

This commit is contained in:
Tim Daubenschütz 2015-11-23 13:59:07 +01:00
parent 56d8268ceb
commit 59244f208a
2 changed files with 70 additions and 12 deletions

View 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;

View File

@ -9,6 +9,7 @@ import Form from './form';
import Property from './property';
import InputFineUploader from './input_fineuploader';
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 AppConstants from '../../constants/application_constants';
@ -77,9 +78,9 @@ let RegisterPieceForm = React.createClass({
*/
setIsUploadReady(uploaderKey) {
return (isUploadReady) => {
this.setState({
[uploaderKey]: isUploadReady
});
// See documentation of `FormSubmitButton` for more detailed information
// on this.
this.refs.submitButton.setReadyStateForKey(uploaderKey, isUploadReady);
};
},
@ -89,7 +90,7 @@ let RegisterPieceForm = React.createClass({
if(validFiles.length > 0) {
const { type: mimeType } = validFiles[0];
const mimeSubType = mimeType && mimeType.split('/').length ? mimeType.split('/')[1]
: 'unknown';
: 'unknown';
const thumbnailKeyDialogExpanded = AppConstants.supportedThumbnailFileFormats.indexOf(mimeSubType) === -1;
this.setState({ thumbnailKeyDialogExpanded });
} else {
@ -122,8 +123,6 @@ let RegisterPieceForm = React.createClass({
children,
enableLocalHashing } = this.props;
const { currentUser,
digitalWorkKeyReady,
thumbnailKeyReady,
thumbnailKeyDialogExpanded } = this.state;
const profileHashLocally = currentUser && currentUser.profile ? currentUser.profile.hash_locally : false;
@ -137,12 +136,13 @@ let RegisterPieceForm = React.createClass({
url={ApiUrls.pieces_list}
handleSuccess={handleSuccess}
buttons={
<button
type="submit"
className="btn btn-default btn-wide"
disabled={!(digitalWorkKeyReady && thumbnailKeyReady)}>
{submitMessage}
</button>
<FormSubmitButton
ref="submitButton"
defaultReadyStates={{
digitalWorkKeyReady: false,
thumbnailKeyReady: true
}}
label={submitMessage}/>
}
spinner={
<span className="btn btn-default btn-wide btn-spinner">