diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js
index 4993b129..1eedf5b0 100644
--- a/js/actions/contract_agreement_list_actions.js
+++ b/js/actions/contract_agreement_list_actions.js
@@ -22,8 +22,7 @@ class ContractAgreementListActions {
if (contractAgreementList.count > 0) {
this.actions.updateContractAgreementList(contractAgreementList.results);
resolve(contractAgreementList.results);
- }
- else{
+ } else {
resolve(null);
}
})
@@ -35,13 +34,13 @@ class ContractAgreementListActions {
);
}
- fetchAvailableContractAgreementList(issuer, createContractAgreement) {
+ fetchAvailableContractAgreementList(issuer, createPublicContractAgreement) {
return Q.Promise((resolve, reject) => {
OwnershipFetcher.fetchContractAgreementList(issuer, true, null)
.then((acceptedContractAgreementList) => {
// if there is at least an accepted contract agreement, we're going to
// use it
- if(acceptedContractAgreementList.count > 0) {
+ if (acceptedContractAgreementList.count > 0) {
this.actions.updateContractAgreementList(acceptedContractAgreementList.results);
} else {
// otherwise, we're looking for contract agreements that are still pending
@@ -50,15 +49,13 @@ class ContractAgreementListActions {
// overcomplicate the method
OwnershipFetcher.fetchContractAgreementList(issuer, null, true)
.then((pendingContractAgreementList) => {
- if(pendingContractAgreementList.count > 0) {
+ if (pendingContractAgreementList.count > 0) {
this.actions.updateContractAgreementList(pendingContractAgreementList.results);
- } else {
+ } else if (createPublicContractAgreement) {
// if there was neither a pending nor an active contractAgreement
- // found and createContractAgreement is set to true, we create a
- // new contract agreement
- if(createContractAgreement) {
- this.actions.createContractAgreementFromPublicContract(issuer);
- }
+ // found and createPublicContractAgreement is set to true, we create a
+ // new public contract agreement
+ this.actions.createContractAgreementFromPublicContract(issuer);
}
})
.catch((err) => {
@@ -81,8 +78,7 @@ class ContractAgreementListActions {
// create an agreement with the public contract if there is one
if (publicContract && publicContract.length > 0) {
return this.actions.createContractAgreement(null, publicContract[0]);
- }
- else {
+ } else {
/*
contractAgreementList in the store is already set to null;
*/
@@ -91,21 +87,17 @@ class ContractAgreementListActions {
if (publicContracAgreement) {
this.actions.updateContractAgreementList([publicContracAgreement]);
}
- }).catch((err) => {
- console.logGlobal(err);
- });
+ }).catch(console.logGlobal);
}
createContractAgreement(issuer, contract){
return Q.Promise((resolve, reject) => {
- OwnershipFetcher.createContractAgreement(issuer, contract).then(
- (contractAgreement) => {
- resolve(contractAgreement);
- }
- ).catch((err) => {
- console.logGlobal(err);
- reject(err);
- });
+ OwnershipFetcher
+ .createContractAgreement(issuer, contract).then(resolve)
+ .catch((err) => {
+ console.logGlobal(err);
+ reject(err);
+ });
});
}
}
diff --git a/js/components/ascribe_detail/edition_action_panel.js b/js/components/ascribe_detail/edition_action_panel.js
index 07827fcd..fbc56bee 100644
--- a/js/components/ascribe_detail/edition_action_panel.js
+++ b/js/components/ascribe_detail/edition_action_panel.js
@@ -127,7 +127,7 @@ let EditionActionPanel = React.createClass({
isInline={true}>
+ expanded={false}>
+ expanded={false}>
{
if (child) {
- return ReactAddons.addons.cloneWithProps(child, {
+ // Since refs will be overwritten by this functions return statement,
+ // we still want to be able to define refs for nested `Form` or `Property`
+ // children, which is why we're upfront simply invoking the callback-ref-
+ // function before overwriting it.
+ if(typeof child.ref === 'function' && this.refs[child.props.name]) {
+ child.ref(this.refs[child.props.name]);
+ }
+
+ return React.cloneElement(child, {
handleChange: this.handleChangeChild,
ref: child.props.name,
key: i,
diff --git a/js/components/ascribe_forms/form_consign.js b/js/components/ascribe_forms/form_consign.js
index d88add94..a7c8f016 100644
--- a/js/components/ascribe_forms/form_consign.js
+++ b/js/components/ascribe_forms/form_consign.js
@@ -6,9 +6,13 @@ import Button from 'react-bootstrap/lib/Button';
import Form from './form';
import Property from './property';
+
+import InputContractAgreementCheckbox from './input_contract_agreement_checkbox';
import InputTextAreaToggable from './input_textarea_toggable';
+
import AscribeSpinner from '../ascribe_spinner';
+
import AclInformation from '../ascribe_buttons/acl_information';
import { getLangText } from '../../utils/lang_utils.js';
@@ -21,6 +25,7 @@ let ConsignForm = React.createClass({
email: React.PropTypes.string,
message: React.PropTypes.string,
labels: React.PropTypes.object,
+ createPublicContractAgreement: React.PropTypes.bool,
handleSuccess: React.PropTypes.func
},
@@ -30,12 +35,34 @@ let ConsignForm = React.createClass({
};
},
+ getInitialState() {
+ return {
+ email: this.props.email
+ };
+ },
+
getFormData() {
return this.props.id;
},
+ handleEmailOnChange(event) {
+ // event.target.value is the submitted email of the consignee
+ this.setState({
+ email: event && event.target && event.target.value || ''
+ });
+ },
+
render() {
- const { autoFocusProperty, email, id, handleSuccess, message, labels, url } = this.props;
+ const { email } = this.state;
+ const {
+ autoFocusProperty,
+ createPublicContractAgreement,
+ email: defaultEmail,
+ handleSuccess,
+ id,
+ message,
+ labels,
+ url } = this.props;
return (
+
+
+
diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js
index aac4c5ea..a392fb03 100644
--- a/js/components/ascribe_forms/form_create_contract.js
+++ b/js/components/ascribe_forms/form_create_contract.js
@@ -91,14 +91,14 @@ let CreateContractForm = React.createClass({
+ expanded={false}>
+ expanded={false}>
diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js
index 7a0af7fd..eb709714 100644
--- a/js/components/ascribe_forms/form_loan.js
+++ b/js/components/ascribe_forms/form_loan.js
@@ -1,33 +1,34 @@
'use strict';
import React from 'react';
-
import classnames from 'classnames';
import Button from 'react-bootstrap/lib/Button';
+import ContractAgreementListStore from '../../stores/contract_agreement_list_store';
+
import Form from './form';
import Property from './property';
-import InputTextAreaToggable from './input_textarea_toggable';
-import InputDate from './input_date';
-import InputCheckbox from './input_checkbox';
-import ContractAgreementListStore from '../../stores/contract_agreement_list_store';
-import ContractAgreementListActions from '../../actions/contract_agreement_list_actions';
+import InputDate from './input_date';
+import InputTextAreaToggable from './input_textarea_toggable';
+import InputContractAgreementCheckbox from './input_contract_agreement_checkbox';
import AscribeSpinner from '../ascribe_spinner';
-import { mergeOptions } from '../../utils/general_utils';
-import { getLangText } from '../../utils/lang_utils';
import AclInformation from '../ascribe_buttons/acl_information';
+import { getLangText } from '../../utils/lang_utils';
+import { mergeOptions } from '../../utils/general_utils';
+
+
let LoanForm = React.createClass({
propTypes: {
loanHeading: React.PropTypes.string,
email: React.PropTypes.string,
gallery: React.PropTypes.string,
- startdate: React.PropTypes.object,
- enddate: React.PropTypes.object,
+ startDate: React.PropTypes.object,
+ endDate: React.PropTypes.object,
showPersonalMessage: React.PropTypes.bool,
showEndDate: React.PropTypes.bool,
showStartDate: React.PropTypes.bool,
@@ -36,7 +37,11 @@ let LoanForm = React.createClass({
id: React.PropTypes.object,
message: React.PropTypes.string,
createPublicContractAgreement: React.PropTypes.bool,
- handleSuccess: React.PropTypes.func
+ handleSuccess: React.PropTypes.func,
+ children: React.PropTypes.oneOfType([
+ React.PropTypes.object,
+ React.PropTypes.array
+ ])
},
getDefaultProps() {
@@ -45,148 +50,33 @@ let LoanForm = React.createClass({
showPersonalMessage: true,
showEndDate: true,
showStartDate: true,
- showPassword: true,
- createPublicContractAgreement: true
+ showPassword: true
};
},
getInitialState() {
- return ContractAgreementListStore.getState();
- },
-
- componentDidMount() {
- ContractAgreementListStore.listen(this.onChange);
- this.getContractAgreementsOrCreatePublic(this.props.email);
- },
-
- /**
- * This method needs to be in form_loan as some whitelabel pages (Cyland) load
- * the loanee's email async!
- *
- * SO LEAVE IT IN!
- */
- componentWillReceiveProps(nextProps) {
- if(nextProps && nextProps.email && this.props.email !== nextProps.email) {
- this.getContractAgreementsOrCreatePublic(nextProps.email);
- }
- },
-
- componentWillUnmount() {
- ContractAgreementListStore.unlisten(this.onChange);
+ return {
+ email: this.props.email || ''
+ };
},
onChange(state) {
this.setState(state);
},
- getContractAgreementsOrCreatePublic(email){
- ContractAgreementListActions.flushContractAgreementList.defer();
- if (email) {
- // fetch the available contractagreements (pending/accepted)
- ContractAgreementListActions.fetchAvailableContractAgreementList(email, true);
- }
- },
-
- getFormData(){
- return mergeOptions(
- this.props.id,
- this.getContractAgreementId()
- );
- },
-
- handleOnChange(event) {
+ handleEmailOnChange(event) {
// event.target.value is the submitted email of the loanee
- if(event && event.target && event.target.value && event.target.value.match(/.*@.*\..*/)) {
- this.getContractAgreementsOrCreatePublic(event.target.value);
- } else {
- ContractAgreementListActions.flushContractAgreementList();
- }
+ this.setState({
+ email: event && event.target && event.target.value || ''
+ });
},
- getContractAgreementId() {
- if (this.state.contractAgreementList && this.state.contractAgreementList.length > 0) {
- return {'contract_agreement_id': this.state.contractAgreementList[0].id};
- }
- return {};
+ handleReset() {
+ this.handleEmailOnChange();
},
- getContractCheckbox() {
- if(this.state.contractAgreementList && this.state.contractAgreementList.length > 0) {
- // we need to define a key on the InputCheckboxes as otherwise
- // react is not rerendering them on a store switch and is keeping
- // the default value of the component (which is in that case true)
- let contractAgreement = this.state.contractAgreementList[0];
- let contract = contractAgreement.contract;
-
- if(contractAgreement.datetime_accepted) {
- return (
-
-
-
- {getLangText('Download contract')}
-
- {/* We still need to send the server information that we're accepting */}
-
-
- );
- } else {
- return (
-
-
-
- {getLangText('I agree to the')}
-
- {getLangText('terms of ')} {contract.issuer}
-
-
-
-
- );
- }
- } else {
- return (
-
-
-
- );
- }
- },
-
- getAppendix() {
- if(this.state.contractAgreementList && this.state.contractAgreementList.length > 0) {
- let appendix = this.state.contractAgreementList[0].appendix;
- if (appendix && appendix.default) {
- return (
-
- {appendix.default}
-
- );
- }
- }
- return null;
+ getFormData() {
+ return this.props.id;
},
getButtons() {
@@ -214,14 +104,31 @@ let LoanForm = React.createClass({
},
render() {
+ const { email } = this.state;
+ const {
+ children,
+ createPublicContractAgreement,
+ email: defaultEmail,
+ handleSuccess,
+ gallery,
+ loanHeading,
+ message,
+ showPersonalMessage,
+ endDate,
+ startDate,
+ showEndDate,
+ showStartDate,
+ showPassword,
+ url } = this.props;
+
return (
}>
-
-
{this.props.loanHeading}
+
+
{loanHeading}
+ editable={!defaultEmail}
+ onChange={this.handleEmailOnChange}
+ overrideForm={!!defaultEmail}>
@@ -248,31 +155,31 @@ let LoanForm = React.createClass({
+ editable={!gallery}
+ overrideForm={!!gallery}>
+ editable={!startDate}
+ overrideForm={!!startDate}
+ expanded={showStartDate}>
+ expanded={showEndDate}>
+ expanded={showPersonalMessage}>
+ required={showPersonalMessage}/>
+
+
+
- {this.getContractCheckbox()}
- {this.getAppendix()}
+ expanded={showPassword}>
+ required={showPassword ? 'required' : ''}/>
- {this.props.children}
+ {children}
);
}
diff --git a/js/components/ascribe_forms/form_loan_request_answer.js b/js/components/ascribe_forms/form_loan_request_answer.js
index 1bfe90db..349b4efc 100644
--- a/js/components/ascribe_forms/form_loan_request_answer.js
+++ b/js/components/ascribe_forms/form_loan_request_answer.js
@@ -65,8 +65,8 @@ let LoanRequestAnswerForm = React.createClass({
url={this.props.url}
email={this.state.loanRequest ? this.state.loanRequest.new_owner : null}
gallery={this.state.loanRequest ? this.state.loanRequest.gallery : null}
- startdate={startDate}
- enddate={endDate}
+ startDate={startDate}
+ endDate={endDate}
showPassword={true}
showPersonalMessage={false}
handleSuccess={this.props.handleSuccess}/>
@@ -76,4 +76,4 @@ let LoanRequestAnswerForm = React.createClass({
}
});
-export default LoanRequestAnswerForm;
\ No newline at end of file
+export default LoanRequestAnswerForm;
diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_send_contract_agreement.js
similarity index 97%
rename from js/components/ascribe_forms/form_contract_agreement.js
rename to js/components/ascribe_forms/form_send_contract_agreement.js
index fa73fe42..8d0170fd 100644
--- a/js/components/ascribe_forms/form_contract_agreement.js
+++ b/js/components/ascribe_forms/form_send_contract_agreement.js
@@ -21,7 +21,7 @@ import { getLangText } from '../../utils/lang_utils';
import { mergeOptions } from '../../utils/general_utils';
-let ContractAgreementForm = React.createClass({
+let SendContractAgreementForm = React.createClass({
propTypes: {
handleSuccess: React.PropTypes.func
},
@@ -55,7 +55,7 @@ let ContractAgreementForm = React.createClass({
},
handleSubmitSuccess() {
- let notification = 'Contract agreement send';
+ let notification = 'Contract agreement sent';
notification = new GlobalNotificationModel(notification, 'success', 10000);
GlobalNotificationActions.appendGlobalNotification(notification);
@@ -148,4 +148,4 @@ let ContractAgreementForm = React.createClass({
}
});
-export default ContractAgreementForm;
\ No newline at end of file
+export default SendContractAgreementForm;
diff --git a/js/components/ascribe_forms/input_contract_agreement_checkbox.js b/js/components/ascribe_forms/input_contract_agreement_checkbox.js
new file mode 100644
index 00000000..c609786e
--- /dev/null
+++ b/js/components/ascribe_forms/input_contract_agreement_checkbox.js
@@ -0,0 +1,201 @@
+'use strict';
+
+import React from 'react/addons';
+
+import InputCheckbox from './input_checkbox';
+
+import ContractAgreementListStore from '../../stores/contract_agreement_list_store';
+import ContractAgreementListActions from '../../actions/contract_agreement_list_actions';
+
+import { getLangText } from '../../utils/lang_utils';
+import { mergeOptions } from '../../utils/general_utils';
+import { isEmail } from '../../utils/regex_utils';
+
+
+const InputContractAgreementCheckbox = React.createClass({
+ propTypes: {
+ createPublicContractAgreement: React.PropTypes.bool,
+ email: React.PropTypes.string,
+
+ required: React.PropTypes.bool,
+
+ // provided by Property
+ disabled: React.PropTypes.bool,
+ onChange: React.PropTypes.func,
+ name: React.PropTypes.string,
+ setExpanded: React.PropTypes.func,
+
+ // can be used to style the component from the outside
+ style: React.PropTypes.object
+ },
+
+ getDefaultProps() {
+ return {
+ createPublicContractAgreement: true
+ };
+ },
+
+ getInitialState() {
+ return mergeOptions(
+ ContractAgreementListStore.getState(),
+ {
+ value: {
+ terms: null,
+ contract_agreement_id: null
+ }
+ }
+ );
+ },
+
+ componentDidMount() {
+ ContractAgreementListStore.listen(this.onStoreChange);
+ this.getContractAgreementsOrCreatePublic(this.props.email);
+ },
+
+ componentWillReceiveProps({ email: nextEmail }) {
+ const { contractAgreementList } = this.state;
+
+ if (this.props.email !== nextEmail) {
+ if (isEmail(nextEmail)) {
+ this.getContractAgreementsOrCreatePublic(nextEmail);
+ } else if (contractAgreementList && contractAgreementList.length > 0) {
+ ContractAgreementListActions.flushContractAgreementList();
+ }
+ }
+ },
+
+ componentWillUnmount() {
+ ContractAgreementListStore.unlisten(this.onStoreChange);
+ },
+
+ onStoreChange(state) {
+ const contractAgreement = this.getContractAgreement(state.contractAgreementList);
+ this.props.setExpanded(!!contractAgreement);
+
+ state = mergeOptions(state, {
+ value: {
+ // If `email` is defined in this component, `getContractAgreementsOrCreatePublic`
+ // is either:
+ //
+ // - fetching a already existing contract agreement; or
+ // - trying to create a contract agreement
+ //
+ // If both attempts result in `contractAgreement` being not defined,
+ // it means that the receiver hasn't defined a contract, which means
+ // a contract agreement cannot be created, which means we don't have to
+ // specify `contract_agreement_id` when sending a request to the server.
+ contract_agreement_id: contractAgreement ? contractAgreement.id : null,
+ // If the receiver hasn't set a contract or the contract was
+ // previously accepted, we set the terms to `true`
+ // as we always need to at least give a boolean value for `terms`
+ // to the API endpoint
+ terms: !contractAgreement || !!contractAgreement.datetime_accepted
+ }
+ });
+
+ this.setState(state);
+ },
+
+ onChange(event) {
+ this.setState({
+ value: React.addons.update(this.state.value, {
+ terms: { $set: event.target.value }
+ })
+ });
+ this.props.onChange(event);
+ },
+
+ getContractAgreement(contractAgreementList = this.state.contractAgreementList) {
+ if (contractAgreementList && contractAgreementList.length > 0) {
+ return contractAgreementList[0];
+ }
+ },
+
+ getContractAgreementsOrCreatePublic(email) {
+ ContractAgreementListActions.flushContractAgreementList.defer();
+
+ if (email) {
+ // fetch the available contractagreements (pending/accepted)
+ ContractAgreementListActions.fetchAvailableContractAgreementList(email, this.props.createPublicContractAgreement);
+ }
+ },
+
+ getAppendix() {
+ const contractAgreement = this.getContractAgreement();
+
+ if (contractAgreement &&
+ contractAgreement.appendix &&
+ contractAgreement.appendix.default) {
+ return (
+
+
{getLangText('Appendix')}
+
{contractAgreement.appendix.default}
+
+ );
+ }
+ },
+
+ getContractCheckbox() {
+ const contractAgreement = this.getContractAgreement();
+
+ if(contractAgreement) {
+ const {
+ datetime_accepted: datetimeAccepted,
+ contract: {
+ issuer: contractIssuer,
+ blob: { url_safe: contractUrl }
+ }
+ } = contractAgreement;
+
+ if(datetimeAccepted) {
+ return (
+
+ );
+ } else {
+ const {
+ name,
+ disabled,
+ style } = this.props;
+
+ return (
+
+
+ {getLangText('I agree to the')}
+
+ {getLangText('terms of ')} {contractIssuer}
+
+
+
+ );
+ }
+ }
+ },
+
+ render() {
+ return (
+
+ {this.getContractCheckbox()}
+ {this.getAppendix()}
+
+ );
+ }
+});
+
+export default InputContractAgreementCheckbox;
diff --git a/js/components/ascribe_forms/property.js b/js/components/ascribe_forms/property.js
index 8039e636..e57c8b3c 100644
--- a/js/components/ascribe_forms/property.js
+++ b/js/components/ascribe_forms/property.js
@@ -3,62 +3,69 @@
import React from 'react';
import ReactAddons from 'react/addons';
-import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
-import Tooltip from 'react-bootstrap/lib/Tooltip';
+import Panel from 'react-bootstrap/lib/Panel';
import AppConstants from '../../constants/application_constants';
import { mergeOptions } from '../../utils/general_utils';
-let Property = React.createClass({
- propTypes: {
- hidden: React.PropTypes.bool,
+const { bool, element, string, oneOfType, func, object, arrayOf } = React.PropTypes;
- autoFocus: React.PropTypes.bool,
- editable: React.PropTypes.bool,
+const Property = React.createClass({
+ propTypes: {
+ editable: bool,
// If we want Form to have a different value for disabled as Property has one for
// editable, we need to set overrideForm to true, as it will then override Form's
// disabled value for individual Properties
- overrideForm: React.PropTypes.bool,
+ overrideForm: bool,
- tooltip: React.PropTypes.element,
- label: React.PropTypes.string,
- value: React.PropTypes.oneOfType([
- React.PropTypes.string,
- React.PropTypes.element
+ label: string,
+ value: oneOfType([
+ string,
+ element
]),
- footer: React.PropTypes.element,
- handleChange: React.PropTypes.func,
- ignoreFocus: React.PropTypes.bool,
- name: React.PropTypes.oneOfType([
- React.PropTypes.string,
- React.PropTypes.number
- ]).isRequired,
- className: React.PropTypes.string,
+ footer: element,
+ handleChange: func,
+ ignoreFocus: bool,
+ name: string.isRequired,
+ className: string,
- onClick: React.PropTypes.func,
- onChange: React.PropTypes.func,
- onBlur: React.PropTypes.func,
+ onClick: func,
+ onChange: func,
+ onBlur: func,
- children: React.PropTypes.oneOfType([
- React.PropTypes.arrayOf(React.PropTypes.element),
- React.PropTypes.element
+ children: oneOfType([
+ arrayOf(element),
+ element
]),
- style: React.PropTypes.object
+ style: object,
+ expanded: bool,
+ checkboxLabel: string,
+ autoFocus: bool
},
getDefaultProps() {
return {
editable: true,
- hidden: false,
+ expanded: true,
className: ''
};
},
getInitialState() {
+ const { expanded, ignoreFocus, checkboxLabel } = this.props;
+
return {
+ // We're mirroring expanded here as a state
+ // React's docs do NOT consider this an antipattern as long as it's
+ // not a "source of truth"-duplication
+ expanded,
+
+ // When a checkboxLabel is defined in the props, we want to set
+ // `ignoreFocus` to true
+ ignoreFocus: ignoreFocus || checkboxLabel,
// Please don't confuse initialValue with react's defaultValue.
// initialValue is set by us to ensure that a user can reset a specific
// property (after editing) to its initial value
@@ -70,14 +77,26 @@ let Property = React.createClass({
},
componentDidMount() {
- if (this.props.autoFocus) {
+ if(this.props.autoFocus) {
this.handleFocus();
}
},
- componentWillReceiveProps() {
+ componentWillReceiveProps(nextProps) {
let childInput = this.refs.input;
+ // For expanded there are actually three use cases:
+ //
+ // 1. Control its value from the outside completely (do not define `checkboxLabel`)
+ // 2. Let it be controlled from the inside (default value can be set though via `expanded`)
+ // 3. Let it be controlled from a child by using `setExpanded` (`expanded` must not be
+ // set from the outside as a prop then(!!!))
+ //
+ // This handles case 1. and 3.
+ if(nextProps.expanded !== this.props.expanded && nextProps.expanded !== this.state.expanded && !this.props.checkboxLabel) {
+ this.setState({ expanded: nextProps.expanded });
+ }
+
// In order to set this.state.value from another component
// the state of value should only be set if its not undefined and
// actually references something
@@ -90,13 +109,13 @@ let Property = React.createClass({
// from native HTML elements.
// To enable developers to create input elements, they can expose a property called value
// in their state that will be picked up by property.js
- } else if(childInput.state && typeof childInput.state.value !== 'undefined') {
+ } else if(childInput && childInput.state && typeof childInput.state.value !== 'undefined') {
this.setState({
value: childInput.state.value
});
}
- if(!this.state.initialValue && childInput.props.defaultValue) {
+ if(!this.state.initialValue && childInput && childInput.props.defaultValue) {
this.setState({
initialValue: childInput.props.defaultValue
});
@@ -148,7 +167,7 @@ let Property = React.createClass({
handleFocus() {
// if ignoreFocus (bool) is defined, then just ignore focusing on
// the property and input
- if(this.props.ignoreFocus) {
+ if(this.state.ignoreFocus) {
return;
}
@@ -200,7 +219,7 @@ let Property = React.createClass({
},
getClassName() {
- if(this.props.hidden){
+ if(!this.state.expanded && !this.props.checkboxLabel){
return 'is-hidden';
}
if(!this.props.editable){
@@ -216,40 +235,92 @@ let Property = React.createClass({
}
},
+ setExpanded(expanded) {
+ this.setState({ expanded });
+ },
+
renderChildren(style) {
- return ReactAddons.Children.map(this.props.children, (child) => {
- return ReactAddons.addons.cloneWithProps(child, {
- style,
- onChange: this.handleChange,
- onFocus: this.handleFocus,
- onBlur: this.handleBlur,
- disabled: !this.props.editable,
- ref: 'input',
- name: this.props.name
+ // Input's props should only be cloned and propagated down the tree,
+ // if the component is actually being shown (!== 'expanded === false')
+ if((this.state.expanded && this.props.checkboxLabel) || !this.props.checkboxLabel) {
+ return ReactAddons.Children.map(this.props.children, (child) => {
+
+ // Since refs will be overriden by this functions return statement,
+ // we still want to be able to define refs for nested `Form` or `Property`
+ // children, which is why we're upfront simply invoking the callback-ref-
+ // function before overriding it.
+ if(typeof child.ref === 'function' && this.refs.input) {
+ child.ref(this.refs.input);
+ }
+
+ return React.cloneElement(child, {
+ style,
+ onChange: this.handleChange,
+ onFocus: this.handleFocus,
+ onBlur: this.handleBlur,
+ disabled: !this.props.editable,
+ ref: 'input',
+ name: this.props.name,
+ setExpanded: this.setExpanded
+ });
});
- });
+ }
+ },
+
+ getLabelAndErrors() {
+ if(this.props.label || this.state.errors) {
+ return (
+
+ {this.props.label}
+ {this.state.errors}
+
+ );
+ } else {
+ return null;
+ }
+ },
+
+ handleCheckboxToggle() {
+ this.setState({expanded: !this.state.expanded});
+ },
+
+ getCheckbox() {
+ const { checkboxLabel } = this.props;
+
+ if(checkboxLabel) {
+ return (
+
+
+ {' ' + checkboxLabel}
+
+ );
+ } else {
+ return null;
+ }
},
render() {
let footer = null;
- let tooltip = ;
- let style = this.props.style ? mergeOptions({}, this.props.style) : {};
+ let style = Object.assign({}, this.props.style);
- if(this.props.tooltip){
- tooltip = (
-
- {this.props.tooltip}
- );
- }
-
if(this.props.footer){
footer = (
{this.props.footer}
-
);
+
+ );
}
- if(!this.props.editable) {
+ if (!this.state.expanded) {
+ style.paddingBottom = 0;
+ }
+ if (!this.props.editable) {
style.cursor = 'not-allowed';
}
@@ -258,19 +329,17 @@ let Property = React.createClass({
className={'ascribe-property-wrapper ' + this.getClassName()}
onClick={this.handleFocus}
style={style}>
-
+ {this.getCheckbox()}
+
-
- {this.props.label}
- {this.state.errors}
-
+ {this.getLabelAndErrors()}
{this.renderChildren(style)}
{footer}
-
+
);
}
diff --git a/js/components/ascribe_forms/property_collapsible.js b/js/components/ascribe_forms/property_collapsible.js
index 92970583..db74868b 100644
--- a/js/components/ascribe_forms/property_collapsible.js
+++ b/js/components/ascribe_forms/property_collapsible.js
@@ -8,7 +8,7 @@ import Tooltip from 'react-bootstrap/lib/Tooltip';
import Panel from 'react-bootstrap/lib/Panel';
-let PropertyCollapsile = React.createClass({
+let PropertyCollapsible = React.createClass({
propTypes: {
children: React.PropTypes.arrayOf(React.PropTypes.element),
checkboxLabel: React.PropTypes.string,
@@ -93,4 +93,4 @@ let PropertyCollapsile = React.createClass({
}
});
-export default PropertyCollapsile;
\ No newline at end of file
+export default PropertyCollapsible;
diff --git a/js/components/whitelabel/prize/simple_prize/components/ascribe_detail/prize_piece_container.js b/js/components/whitelabel/prize/simple_prize/components/ascribe_detail/prize_piece_container.js
index 93ca50f3..7becb847 100644
--- a/js/components/whitelabel/prize/simple_prize/components/ascribe_detail/prize_piece_container.js
+++ b/js/components/whitelabel/prize/simple_prize/components/ascribe_detail/prize_piece_container.js
@@ -292,8 +292,8 @@ let PrizePieceRatings = React.createClass({
url={ApiUrls.ownership_loans_pieces_request}
email={this.props.currentUser.email}
gallery={this.props.piece.prize.name}
- startdate={today}
- enddate={endDate}
+ startDate={today}
+ endDate={endDate}
showPersonalMessage={true}
showPassword={false}
handleSuccess={this.handleLoanSuccess} />
diff --git a/js/components/whitelabel/wallet/components/cyland/cyland_forms/cyland_additional_data_form.js b/js/components/whitelabel/wallet/components/cyland/cyland_forms/cyland_additional_data_form.js
index 1e4339f2..54ac501b 100644
--- a/js/components/whitelabel/wallet/components/cyland/cyland_forms/cyland_additional_data_form.js
+++ b/js/components/whitelabel/wallet/components/cyland/cyland_forms/cyland_additional_data_form.js
@@ -122,7 +122,7 @@ let CylandAdditionalDataForm = React.createClass({
+ expanded={!disabled || !!piece.extra_data.artist_bio}>
+ expanded={!disabled || !!piece.extra_data.artist_contact_information}>
+ expanded={!disabled || !!piece.extra_data.conceptual_overview}>
+ expanded={!disabled || !!piece.extra_data.medium}>
+ expanded={!disabled || !!piece.extra_data.size_duration}>
+ expanded={!disabled || !!piece.extra_data.display_instructions}>
+ expanded={!disabled || !!piece.extra_data.additional_details}>
+ expanded={!this.props.disabled || !!this.props.piece.extra_data.artist_website}>
+ expanded={!this.props.disabled || !!this.props.piece.extra_data.gallery_website}>
+ expanded={!this.props.disabled || !!this.props.piece.extra_data.additional_websites}>
+ expanded={!this.props.disabled || !!this.props.piece.extra_data.conceptual_overview}>
+ expanded={!this.props.disabled || !!this.props.piece.extra_data.medium}>
+ expanded={!this.props.disabled || !!this.props.piece.extra_data.size_duration}>
+ expanded={!this.props.disabled || !!this.props.piece.extra_data.copyright}>
+ expanded={!this.props.disabled || !!this.props.piece.extra_data.courtesy_of}>
+ expanded={!this.props.disabled || !!this.props.piece.extra_data.copyright_of_photography}>
+ expanded={!this.props.disabled || !!this.props.piece.extra_data.additional_details}>
@@ -212,8 +213,8 @@ let IkonotvRegisterPiece = React.createClass({
id={{piece_id: piece.id}}
url={ApiUrls.ownership_loans_pieces}
email={whitelabel.user}
- startdate={today}
- enddate={enddate}
+ startDate={today}
+ endDate={endDate}
showStartDate={false}
showEndDate={false}
gallery="IkonoTV archive"
diff --git a/js/components/whitelabel/wallet/components/market/market_buttons/market_submit_button.js b/js/components/whitelabel/wallet/components/market/market_buttons/market_submit_button.js
index a4b1b7c3..8e7775a2 100644
--- a/js/components/whitelabel/wallet/components/market/market_buttons/market_submit_button.js
+++ b/js/components/whitelabel/wallet/components/market/market_buttons/market_submit_button.js
@@ -129,7 +129,8 @@ let MarketSubmitButton = React.createClass({
handleSuccess={this.handleAdditionalDataSuccess.bind(this, solePieceId)}
title={getLangText('Add additional information')}>
+ pieceId={solePieceId}
+ submitLabel={getLangText('Continue to consignment')} />
- {getLangText('Register work')}
+ {submitLabel}
);
diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js
index 92b53dc6..f65e20fb 100644
--- a/js/components/whitelabel/wallet/wallet_routes.js
+++ b/js/components/whitelabel/wallet/wallet_routes.js
@@ -25,7 +25,7 @@ import CylandPieceList from './components/cyland/cyland_piece_list';
import IkonotvLanding from './components/ikonotv/ikonotv_landing';
import IkonotvPieceList from './components/ikonotv/ikonotv_piece_list';
-import ContractAgreementForm from '../../../components/ascribe_forms/form_contract_agreement';
+import SendContractAgreementForm from '../../../components/ascribe_forms/form_send_contract_agreement';
import IkonotvRegisterPiece from './components/ikonotv/ikonotv_register_piece';
import IkonotvPieceContainer from './components/ikonotv/ikonotv_detail/ikonotv_piece_container';
import IkonotvContractNotifications from './components/ikonotv/ikonotv_contract_notifications';
@@ -135,7 +135,7 @@ let ROUTES = {
component={AuthProxyHandler({to: '/login', when: 'loggedOut'})(ContractSettings)}/>