mirror of
https://github.com/ascribe/onion.git
synced 2025-01-03 18:35:09 +01:00
Fetch piece data in AdditionalDetailForm
Although this moves state further down the hierarchy, it allows the AdditionalDataForm to be used more easily. Parent components would otherwise have to have the piece prop carried down through multiple levels or create a makeshift object.
This commit is contained in:
parent
3fb4ae55bf
commit
adf0d411d6
@ -31,7 +31,10 @@ let Property = React.createClass({
|
||||
footer: React.PropTypes.element,
|
||||
handleChange: React.PropTypes.func,
|
||||
ignoreFocus: React.PropTypes.bool,
|
||||
name: React.PropTypes.string.isRequired,
|
||||
name: React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.number
|
||||
]).isRequired,
|
||||
className: React.PropTypes.string,
|
||||
|
||||
onClick: React.PropTypes.func,
|
||||
|
@ -9,18 +9,14 @@ import LumenusAclButtonList from '../lumenus_buttons/lumenus_acl_button_list';
|
||||
import EditionContainer from '../../../../../ascribe_detail/edition_container';
|
||||
|
||||
let LumenusEditionContainer = React.createClass({
|
||||
propTypes: {
|
||||
params: React.PropTypes.object,
|
||||
location: React.PropTypes.object
|
||||
},
|
||||
propTypes: EditionContainer.propTypes,
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EditionContainer
|
||||
params={this.props.params}
|
||||
{...this.props}
|
||||
actionPanelButtonListType={LumenusAclButtonList}
|
||||
furtherDetailsType={LumenusFurtherDetails}
|
||||
location={this.props.location} />
|
||||
furtherDetailsType={LumenusFurtherDetails} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -4,43 +4,20 @@ import React from 'react';
|
||||
|
||||
import LumenusAdditionalDataForm from '../lumenus_forms/lumenus_additional_data_form'
|
||||
|
||||
import GlobalNotificationModel from '../../../../../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
|
||||
|
||||
let FurtherDetails = React.createClass({
|
||||
let LumenusFurtherDetails = React.createClass({
|
||||
propTypes: {
|
||||
pieceId: React.PropTypes.number,
|
||||
extraData: React.PropTypes.object,
|
||||
otherData: React.PropTypes.arrayOf(React.PropTypes.object),
|
||||
handleSuccess: React.PropTypes.func,
|
||||
location: React.PropTypes.object
|
||||
},
|
||||
|
||||
showNotification() {
|
||||
this.props.handleSuccess();
|
||||
let notification = new GlobalNotificationModel('Further details updated', 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
render() {
|
||||
const { pieceId, extraData, otherData, handleSuccess, location } = this.props;
|
||||
|
||||
// Instead of grabbing the entire piece from the PieceStore and making this component
|
||||
// stateful, we can put together a piece for the additional form solely based on the props
|
||||
const piece = {
|
||||
id: pieceId,
|
||||
extra_data: extraData,
|
||||
other_data: otherData
|
||||
};
|
||||
|
||||
return (
|
||||
<LumenusAdditionalDataForm
|
||||
piece={piece}
|
||||
handleSuccess={this.showNotification}
|
||||
{...this.props}
|
||||
isInline
|
||||
location={location} />
|
||||
showNotification />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default FurtherDetails;
|
||||
export default LumenusFurtherDetails;
|
||||
|
@ -7,17 +7,13 @@ import LumenusFurtherDetails from './lumenus_further_details';
|
||||
import PieceContainer from '../../../../../ascribe_detail/piece_container';
|
||||
|
||||
let LumenusPieceContainer = React.createClass({
|
||||
propTypes: {
|
||||
params: React.PropTypes.object,
|
||||
location: React.PropTypes.object
|
||||
},
|
||||
propTypes: PieceContainer.propTypes,
|
||||
|
||||
render() {
|
||||
return (
|
||||
<PieceContainer
|
||||
params={this.props.params}
|
||||
furtherDetailsType={LumenusFurtherDetails}
|
||||
location={this.props.location} />
|
||||
{...this.props}
|
||||
furtherDetailsType={LumenusFurtherDetails} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -14,38 +14,70 @@ import GlobalNotificationActions from '../../../../../../actions/global_notifica
|
||||
|
||||
import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_s3_fine_uploader_utils';
|
||||
|
||||
import PieceActions from '../../../../../../actions/piece_actions';
|
||||
import PieceStore from '../../../../../../stores/piece_store';
|
||||
|
||||
import ApiUrls from '../../../../../../constants/api_urls';
|
||||
import AppConstants from '../../../../../../constants/application_constants';
|
||||
|
||||
import requests from '../../../../../../utils/requests';
|
||||
import { mergeOptions } from '../../../../../../utils/general_utils';
|
||||
import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
|
||||
let LumenusAdditionalDataForm = React.createClass({
|
||||
propTypes: {
|
||||
handleSuccess: React.PropTypes.func,
|
||||
piece: React.PropTypes.shape({
|
||||
id: React.PropTypes.number,
|
||||
extra_data: React.PropTypes.object,
|
||||
other_data: React.PropTypes.arrayOf(React.PropTypes.object)
|
||||
}).isRequired,
|
||||
isInline: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
isInline: false
|
||||
};
|
||||
pieceId: React.PropTypes.oneOfType([
|
||||
React.PropTypes.number,
|
||||
React.PropTypes.string
|
||||
]),
|
||||
isInline: React.PropTypes.bool,
|
||||
showHeading: React.PropTypes.bool,
|
||||
showNotification: React.PropTypes.bool,
|
||||
handleSuccess: React.PropTypes.func
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
isUploadReady: false
|
||||
};
|
||||
const pieceStore = PieceStore.getState();
|
||||
|
||||
return mergeOptions(
|
||||
pieceStore,
|
||||
{
|
||||
// Allow the form to be submitted if there's already an additional image uploaded
|
||||
isUploadReady: this.isUploadReadyOnChange(pieceStore.piece),
|
||||
forceUpdateKey: 0,
|
||||
});
|
||||
},
|
||||
|
||||
handleSuccess() {
|
||||
let notification = new GlobalNotificationModel(getLangText('Further details successfully updated'), 'success', 10000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
componentDidMount() {
|
||||
PieceStore.listen(this.onChange);
|
||||
|
||||
// If the Piece store doesn't already have the piece we want loaded, load it
|
||||
const { pieceId } = this.props;
|
||||
if (pieceId && this.state.piece.id !== pieceId) {
|
||||
PieceActions.fetchOne(pieceId);
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
PieceStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
|
||||
this.setState({
|
||||
// Allow the form to be submitted if the updated piece already has an additional image uploaded
|
||||
isUploadReady: this.isUploadReadyOnChange(state.piece),
|
||||
|
||||
/**
|
||||
* Increment the forceUpdateKey to force the form to rerender on each change
|
||||
*
|
||||
* THIS IS A HACK TO MAKE SURE THE FORM ALWAYS DISPLAYS THE MOST RECENT STATE
|
||||
* BECAUSE SOME OF OUR FORM ELEMENTS DON'T UPDATE FROM PROP CHANGES (ie.
|
||||
* InputTextAreaToggable).
|
||||
*/
|
||||
forceUpdateKey: this.state.forceUpdateKey + 1
|
||||
});
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
@ -61,10 +93,23 @@ let LumenusAdditionalDataForm = React.createClass({
|
||||
|
||||
return {
|
||||
extradata: extradata,
|
||||
piece_id: this.props.piece.id
|
||||
piece_id: this.state.piece.id
|
||||
};
|
||||
},
|
||||
|
||||
isUploadReadyOnChange(piece) {
|
||||
return piece && piece.other_data && piece.other_data.length > 0 ? true : false;
|
||||
},
|
||||
|
||||
handleSuccessWithNotification() {
|
||||
if (typeof this.props.handleSuccess === 'function') {
|
||||
this.props.handleSuccess();
|
||||
}
|
||||
|
||||
let notification = new GlobalNotificationModel(getLangText('Further details successfully updated'), 'success', 10000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
uploadStarted() {
|
||||
this.setState({
|
||||
isUploadReady: false
|
||||
@ -78,7 +123,8 @@ let LumenusAdditionalDataForm = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
let { piece, isInline, handleSuccess } = this.props;
|
||||
const { isInline, handleSuccess, showHeading, showNotification } = this.props;
|
||||
const { piece } = this.state;
|
||||
let buttons, spinner, heading;
|
||||
|
||||
if (!isInline) {
|
||||
@ -97,13 +143,13 @@ let LumenusAdditionalDataForm = React.createClass({
|
||||
</div>
|
||||
);
|
||||
|
||||
heading = (
|
||||
heading = showHeading ? (
|
||||
<div className="ascribe-form-header">
|
||||
<h3>
|
||||
{getLangText('Provide additional details')}
|
||||
</h3>
|
||||
</div>
|
||||
);
|
||||
) : null;
|
||||
}
|
||||
|
||||
if (piece && piece.id) {
|
||||
@ -111,8 +157,9 @@ let LumenusAdditionalDataForm = React.createClass({
|
||||
<Form
|
||||
className="ascribe-form-bordered"
|
||||
ref='form'
|
||||
key={this.state.forceUpdateKey}
|
||||
url={requests.prepareUrl(ApiUrls.piece_extradata, {piece_id: piece.id})}
|
||||
handleSuccess={handleSuccess || this.handleSuccess}
|
||||
handleSuccess={showNotification ? this.handleSuccessWithNotification : handleSuccess}
|
||||
getFormData={this.getFormData}
|
||||
buttons={buttons}
|
||||
spinner={spinner}>
|
||||
@ -144,11 +191,11 @@ let LumenusAdditionalDataForm = React.createClass({
|
||||
required />
|
||||
</Property>
|
||||
<Property
|
||||
name='tech_details'
|
||||
name='technology_details'
|
||||
label={getLangText('Technology Details')}>
|
||||
<InputTextAreaToggable
|
||||
rows={1}
|
||||
defaultValue={piece.extra_data.tech_details}
|
||||
defaultValue={piece.extra_data.technology_details}
|
||||
placeholder={getLangText('Enter technological details about the work was produced...')}
|
||||
required />
|
||||
</Property>
|
||||
|
@ -13,7 +13,6 @@ import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece';
|
||||
|
||||
import UserStore from '../../../../../stores/user_store';
|
||||
import UserActions from '../../../../../actions/user_actions';
|
||||
import PieceStore from '../../../../../stores/piece_store';
|
||||
import PieceActions from '../../../../../actions/piece_actions';
|
||||
import PieceListStore from '../../../../../stores/piece_list_store';
|
||||
import PieceListActions from '../../../../../actions/piece_list_actions';
|
||||
@ -35,7 +34,6 @@ let LumenusRegisterPiece = React.createClass({
|
||||
return mergeOptions(
|
||||
UserStore.getState(),
|
||||
PieceListStore.getState(),
|
||||
PieceStore.getState(),
|
||||
{
|
||||
selectedLicense: 0,
|
||||
isFineUploaderActive: false,
|
||||
@ -46,33 +44,22 @@ let LumenusRegisterPiece = React.createClass({
|
||||
componentDidMount() {
|
||||
PieceListStore.listen(this.onChange);
|
||||
UserStore.listen(this.onChange);
|
||||
PieceStore.listen(this.onChange);
|
||||
UserActions.fetchCurrentUser();
|
||||
|
||||
let queryParams = this.props.location.query;
|
||||
|
||||
// Since every step of this register process is atomic,
|
||||
// we may need to enter the process at step 1 or 2.
|
||||
// If this is the case, we'll need the piece number to complete submission.
|
||||
// It is encoded in the URL as a queryParam and we're checking for it here.
|
||||
//
|
||||
// We're using 'in' here as we want to know if 'piece_id' is present in the url,
|
||||
// we don't care about the value.
|
||||
if(queryParams && 'piece_id' in queryParams) {
|
||||
PieceActions.fetchOne(queryParams.piece_id);
|
||||
}
|
||||
// Reset the piece store to make sure that we don't display old data
|
||||
// if the user repeatedly registers works
|
||||
PieceActions.updatePiece({});
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
PieceListStore.unlisten(this.onChange);
|
||||
UserStore.unlisten(this.onChange);
|
||||
PieceStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
|
||||
if(this.state.currentUser && this.state.currentUser.email) {
|
||||
if (this.state.currentUser && this.state.currentUser.email) {
|
||||
// we should also make the fineuploader component editable again
|
||||
this.setState({
|
||||
isFineUploaderActive: true
|
||||
@ -80,26 +67,21 @@ let LumenusRegisterPiece = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
handleRegisterSuccess(response){
|
||||
handleRegisterSuccess(response) {
|
||||
this.refreshPieceList();
|
||||
|
||||
// also start loading the piece for the next step
|
||||
if(response && response.piece) {
|
||||
PieceActions.updatePiece({});
|
||||
// Use the response's piece for the next step if available
|
||||
let pieceId = null;
|
||||
if (response && response.piece) {
|
||||
pieceId = response.piece.id;
|
||||
PieceActions.updatePiece(response.piece);
|
||||
}
|
||||
|
||||
this.incrementStep();
|
||||
|
||||
this.refs.slidesContainer.nextSlide({ piece_id: response.piece.id });
|
||||
this.refs.slidesContainer.nextSlide({ piece_id: pieceId });
|
||||
},
|
||||
|
||||
handleAdditionalDataSuccess() {
|
||||
// We need to refetch the piece again after submitting the additional data
|
||||
// since we want it's otherData to be displayed when the user choses to click
|
||||
// on the browsers back button.
|
||||
PieceActions.fetchOne(this.state.piece.id);
|
||||
|
||||
this.refreshPieceList();
|
||||
|
||||
this.history.pushState(null, `/collection`);
|
||||
@ -107,13 +89,21 @@ let LumenusRegisterPiece = React.createClass({
|
||||
|
||||
// We need to increase the step to lock the forms that are already filled out
|
||||
incrementStep() {
|
||||
// also increase step
|
||||
let newStep = this.state.step + 1;
|
||||
this.setState({
|
||||
step: newStep
|
||||
step: this.state.step + 1
|
||||
});
|
||||
},
|
||||
|
||||
getPieceFromQueryParam() {
|
||||
const queryParams = this.props.location.query;
|
||||
|
||||
// Since every step of this register process is atomic,
|
||||
// we may need to enter the process at step 1 or 2.
|
||||
// If this is the case, we'll need the piece number to complete submission.
|
||||
// It is encoded in the URL as a queryParam and we're checking for it here.
|
||||
return queryParams && queryParams.piece_id;
|
||||
},
|
||||
|
||||
refreshPieceList() {
|
||||
PieceListActions.fetchPieceList(
|
||||
this.state.page,
|
||||
@ -161,7 +151,7 @@ let LumenusRegisterPiece = React.createClass({
|
||||
type="number"
|
||||
placeholder="(e.g. 32)"
|
||||
min={0}
|
||||
required/>
|
||||
required />
|
||||
</Property>
|
||||
</RegisterPieceForm>
|
||||
</Col>
|
||||
@ -172,8 +162,8 @@ let LumenusRegisterPiece = React.createClass({
|
||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||
<LumenusAdditionalDataForm
|
||||
handleSuccess={this.handleAdditionalDataSuccess}
|
||||
piece={this.state.piece}
|
||||
location={this.props.location}/>
|
||||
pieceId={this.getPieceFromQueryParam()}
|
||||
showHeading />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user