mirror of
https://github.com/ascribe/onion.git
synced 2025-01-03 10:25:08 +01:00
Merge pull request #47 from ascribe/AD-1149-additional-details
AD-1149 Contract agreement in consign forms
This commit is contained in:
commit
c9949f0cc0
@ -22,8 +22,7 @@ class ContractAgreementListActions {
|
|||||||
if (contractAgreementList.count > 0) {
|
if (contractAgreementList.count > 0) {
|
||||||
this.actions.updateContractAgreementList(contractAgreementList.results);
|
this.actions.updateContractAgreementList(contractAgreementList.results);
|
||||||
resolve(contractAgreementList.results);
|
resolve(contractAgreementList.results);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
resolve(null);
|
resolve(null);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -35,13 +34,13 @@ class ContractAgreementListActions {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAvailableContractAgreementList(issuer, createContractAgreement) {
|
fetchAvailableContractAgreementList(issuer, createPublicContractAgreement) {
|
||||||
return Q.Promise((resolve, reject) => {
|
return Q.Promise((resolve, reject) => {
|
||||||
OwnershipFetcher.fetchContractAgreementList(issuer, true, null)
|
OwnershipFetcher.fetchContractAgreementList(issuer, true, null)
|
||||||
.then((acceptedContractAgreementList) => {
|
.then((acceptedContractAgreementList) => {
|
||||||
// if there is at least an accepted contract agreement, we're going to
|
// if there is at least an accepted contract agreement, we're going to
|
||||||
// use it
|
// use it
|
||||||
if(acceptedContractAgreementList.count > 0) {
|
if (acceptedContractAgreementList.count > 0) {
|
||||||
this.actions.updateContractAgreementList(acceptedContractAgreementList.results);
|
this.actions.updateContractAgreementList(acceptedContractAgreementList.results);
|
||||||
} else {
|
} else {
|
||||||
// otherwise, we're looking for contract agreements that are still pending
|
// otherwise, we're looking for contract agreements that are still pending
|
||||||
@ -50,15 +49,13 @@ class ContractAgreementListActions {
|
|||||||
// overcomplicate the method
|
// overcomplicate the method
|
||||||
OwnershipFetcher.fetchContractAgreementList(issuer, null, true)
|
OwnershipFetcher.fetchContractAgreementList(issuer, null, true)
|
||||||
.then((pendingContractAgreementList) => {
|
.then((pendingContractAgreementList) => {
|
||||||
if(pendingContractAgreementList.count > 0) {
|
if (pendingContractAgreementList.count > 0) {
|
||||||
this.actions.updateContractAgreementList(pendingContractAgreementList.results);
|
this.actions.updateContractAgreementList(pendingContractAgreementList.results);
|
||||||
} else {
|
} else if (createPublicContractAgreement) {
|
||||||
// if there was neither a pending nor an active contractAgreement
|
// if there was neither a pending nor an active contractAgreement
|
||||||
// found and createContractAgreement is set to true, we create a
|
// found and createPublicContractAgreement is set to true, we create a
|
||||||
// new contract agreement
|
// new public contract agreement
|
||||||
if(createContractAgreement) {
|
this.actions.createContractAgreementFromPublicContract(issuer);
|
||||||
this.actions.createContractAgreementFromPublicContract(issuer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@ -81,8 +78,7 @@ class ContractAgreementListActions {
|
|||||||
// create an agreement with the public contract if there is one
|
// create an agreement with the public contract if there is one
|
||||||
if (publicContract && publicContract.length > 0) {
|
if (publicContract && publicContract.length > 0) {
|
||||||
return this.actions.createContractAgreement(null, publicContract[0]);
|
return this.actions.createContractAgreement(null, publicContract[0]);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
/*
|
/*
|
||||||
contractAgreementList in the store is already set to null;
|
contractAgreementList in the store is already set to null;
|
||||||
*/
|
*/
|
||||||
@ -91,21 +87,17 @@ class ContractAgreementListActions {
|
|||||||
if (publicContracAgreement) {
|
if (publicContracAgreement) {
|
||||||
this.actions.updateContractAgreementList([publicContracAgreement]);
|
this.actions.updateContractAgreementList([publicContracAgreement]);
|
||||||
}
|
}
|
||||||
}).catch((err) => {
|
}).catch(console.logGlobal);
|
||||||
console.logGlobal(err);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createContractAgreement(issuer, contract){
|
createContractAgreement(issuer, contract){
|
||||||
return Q.Promise((resolve, reject) => {
|
return Q.Promise((resolve, reject) => {
|
||||||
OwnershipFetcher.createContractAgreement(issuer, contract).then(
|
OwnershipFetcher
|
||||||
(contractAgreement) => {
|
.createContractAgreement(issuer, contract).then(resolve)
|
||||||
resolve(contractAgreement);
|
.catch((err) => {
|
||||||
}
|
console.logGlobal(err);
|
||||||
).catch((err) => {
|
reject(err);
|
||||||
console.logGlobal(err);
|
});
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ let EditionActionPanel = React.createClass({
|
|||||||
isInline={true}>
|
isInline={true}>
|
||||||
<Property
|
<Property
|
||||||
name="bitcoin_id"
|
name="bitcoin_id"
|
||||||
hidden={true}>
|
expanded={false}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={edition.bitcoin_id}
|
value={edition.bitcoin_id}
|
||||||
@ -148,7 +148,7 @@ let EditionActionPanel = React.createClass({
|
|||||||
isInline={true}>
|
isInline={true}>
|
||||||
<Property
|
<Property
|
||||||
name="bitcoin_id"
|
name="bitcoin_id"
|
||||||
hidden={true}>
|
expanded={false}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={edition.bitcoin_id}
|
value={edition.bitcoin_id}
|
||||||
|
@ -124,8 +124,18 @@ let Form = React.createClass({
|
|||||||
getFormData() {
|
getFormData() {
|
||||||
let data = {};
|
let data = {};
|
||||||
|
|
||||||
for (let ref in this.refs) {
|
for (let refName in this.refs) {
|
||||||
data[this.refs[ref].props.name] = this.refs[ref].state.value;
|
const ref = this.refs[refName];
|
||||||
|
|
||||||
|
if (ref.state && 'value' in ref.state) {
|
||||||
|
// An input can also provide an `Object` as a value
|
||||||
|
// which we're going to merge with `data` (overwrites)
|
||||||
|
if(ref.state.value.constructor === Object) {
|
||||||
|
Object.assign(data, ref.state.value);
|
||||||
|
} else {
|
||||||
|
data[ref.props.name] = ref.state.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof this.props.getFormData === 'function') {
|
if (typeof this.props.getFormData === 'function') {
|
||||||
@ -238,7 +248,15 @@ let Form = React.createClass({
|
|||||||
renderChildren() {
|
renderChildren() {
|
||||||
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
||||||
if (child) {
|
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,
|
handleChange: this.handleChangeChild,
|
||||||
ref: child.props.name,
|
ref: child.props.name,
|
||||||
key: i,
|
key: i,
|
||||||
|
@ -6,9 +6,13 @@ import Button from 'react-bootstrap/lib/Button';
|
|||||||
|
|
||||||
import Form from './form';
|
import Form from './form';
|
||||||
import Property from './property';
|
import Property from './property';
|
||||||
|
|
||||||
|
import InputContractAgreementCheckbox from './input_contract_agreement_checkbox';
|
||||||
import InputTextAreaToggable from './input_textarea_toggable';
|
import InputTextAreaToggable from './input_textarea_toggable';
|
||||||
|
|
||||||
|
|
||||||
import AscribeSpinner from '../ascribe_spinner';
|
import AscribeSpinner from '../ascribe_spinner';
|
||||||
|
|
||||||
import AclInformation from '../ascribe_buttons/acl_information';
|
import AclInformation from '../ascribe_buttons/acl_information';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils.js';
|
import { getLangText } from '../../utils/lang_utils.js';
|
||||||
@ -21,6 +25,7 @@ let ConsignForm = React.createClass({
|
|||||||
email: React.PropTypes.string,
|
email: React.PropTypes.string,
|
||||||
message: React.PropTypes.string,
|
message: React.PropTypes.string,
|
||||||
labels: React.PropTypes.object,
|
labels: React.PropTypes.object,
|
||||||
|
createPublicContractAgreement: React.PropTypes.bool,
|
||||||
handleSuccess: React.PropTypes.func
|
handleSuccess: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -30,12 +35,34 @@ let ConsignForm = React.createClass({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
email: this.props.email
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
getFormData() {
|
getFormData() {
|
||||||
return this.props.id;
|
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() {
|
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 (
|
return (
|
||||||
<Form
|
<Form
|
||||||
@ -64,12 +91,13 @@ let ConsignForm = React.createClass({
|
|||||||
autoFocus={autoFocusProperty === 'email'}
|
autoFocus={autoFocusProperty === 'email'}
|
||||||
name='consignee'
|
name='consignee'
|
||||||
label={labels.email || getLangText('Email')}
|
label={labels.email || getLangText('Email')}
|
||||||
editable={!email}
|
editable={!defaultEmail}
|
||||||
overrideForm={!!email}>
|
onChange={this.handleEmailOnChange}
|
||||||
|
overrideForm={!!defaultEmail}>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
|
value={email}
|
||||||
placeholder={getLangText('Email of the consignee')}
|
placeholder={getLangText('Email of the consignee')}
|
||||||
defaultValue={email}
|
|
||||||
required/>
|
required/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
@ -84,6 +112,15 @@ let ConsignForm = React.createClass({
|
|||||||
placeholder={getLangText('Enter a message...')}
|
placeholder={getLangText('Enter a message...')}
|
||||||
required />
|
required />
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property
|
||||||
|
name='contract_agreement'
|
||||||
|
label={getLangText('Consign Contract')}
|
||||||
|
className="ascribe-property-collapsible-toggle"
|
||||||
|
style={{paddingBottom: 0}}>
|
||||||
|
<InputContractAgreementCheckbox
|
||||||
|
createPublicContractAgreement={createPublicContractAgreement}
|
||||||
|
email={email} />
|
||||||
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='password'
|
name='password'
|
||||||
label={getLangText('Password')}>
|
label={getLangText('Password')}>
|
||||||
|
@ -91,14 +91,14 @@ let CreateContractForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='name'
|
name='name'
|
||||||
label={getLangText('Contract name')}
|
label={getLangText('Contract name')}
|
||||||
hidden={true}>
|
expanded={false}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={this.state.contractName}/>
|
value={this.state.contractName}/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name="is_public"
|
name="is_public"
|
||||||
hidden={true}>
|
expanded={false}>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
value={this.props.isPublic} />
|
value={this.props.isPublic} />
|
||||||
|
@ -1,33 +1,34 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
import Button from 'react-bootstrap/lib/Button';
|
import Button from 'react-bootstrap/lib/Button';
|
||||||
|
|
||||||
|
import ContractAgreementListStore from '../../stores/contract_agreement_list_store';
|
||||||
|
|
||||||
import Form from './form';
|
import Form from './form';
|
||||||
import Property from './property';
|
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 InputDate from './input_date';
|
||||||
import ContractAgreementListActions from '../../actions/contract_agreement_list_actions';
|
import InputTextAreaToggable from './input_textarea_toggable';
|
||||||
|
import InputContractAgreementCheckbox from './input_contract_agreement_checkbox';
|
||||||
|
|
||||||
import AscribeSpinner from '../ascribe_spinner';
|
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 AclInformation from '../ascribe_buttons/acl_information';
|
||||||
|
|
||||||
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
|
import { mergeOptions } from '../../utils/general_utils';
|
||||||
|
|
||||||
|
|
||||||
let LoanForm = React.createClass({
|
let LoanForm = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
loanHeading: React.PropTypes.string,
|
loanHeading: React.PropTypes.string,
|
||||||
email: React.PropTypes.string,
|
email: React.PropTypes.string,
|
||||||
gallery: React.PropTypes.string,
|
gallery: React.PropTypes.string,
|
||||||
startdate: React.PropTypes.object,
|
startDate: React.PropTypes.object,
|
||||||
enddate: React.PropTypes.object,
|
endDate: React.PropTypes.object,
|
||||||
showPersonalMessage: React.PropTypes.bool,
|
showPersonalMessage: React.PropTypes.bool,
|
||||||
showEndDate: React.PropTypes.bool,
|
showEndDate: React.PropTypes.bool,
|
||||||
showStartDate: React.PropTypes.bool,
|
showStartDate: React.PropTypes.bool,
|
||||||
@ -36,7 +37,11 @@ let LoanForm = React.createClass({
|
|||||||
id: React.PropTypes.object,
|
id: React.PropTypes.object,
|
||||||
message: React.PropTypes.string,
|
message: React.PropTypes.string,
|
||||||
createPublicContractAgreement: React.PropTypes.bool,
|
createPublicContractAgreement: React.PropTypes.bool,
|
||||||
handleSuccess: React.PropTypes.func
|
handleSuccess: React.PropTypes.func,
|
||||||
|
children: React.PropTypes.oneOfType([
|
||||||
|
React.PropTypes.object,
|
||||||
|
React.PropTypes.array
|
||||||
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
@ -45,148 +50,33 @@ let LoanForm = React.createClass({
|
|||||||
showPersonalMessage: true,
|
showPersonalMessage: true,
|
||||||
showEndDate: true,
|
showEndDate: true,
|
||||||
showStartDate: true,
|
showStartDate: true,
|
||||||
showPassword: true,
|
showPassword: true
|
||||||
createPublicContractAgreement: true
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return ContractAgreementListStore.getState();
|
return {
|
||||||
},
|
email: this.props.email || ''
|
||||||
|
};
|
||||||
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);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onChange(state) {
|
onChange(state) {
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
},
|
},
|
||||||
|
|
||||||
getContractAgreementsOrCreatePublic(email){
|
handleEmailOnChange(event) {
|
||||||
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) {
|
|
||||||
// event.target.value is the submitted email of the loanee
|
// event.target.value is the submitted email of the loanee
|
||||||
if(event && event.target && event.target.value && event.target.value.match(/.*@.*\..*/)) {
|
this.setState({
|
||||||
this.getContractAgreementsOrCreatePublic(event.target.value);
|
email: event && event.target && event.target.value || ''
|
||||||
} else {
|
});
|
||||||
ContractAgreementListActions.flushContractAgreementList();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getContractAgreementId() {
|
handleReset() {
|
||||||
if (this.state.contractAgreementList && this.state.contractAgreementList.length > 0) {
|
this.handleEmailOnChange();
|
||||||
return {'contract_agreement_id': this.state.contractAgreementList[0].id};
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getContractCheckbox() {
|
getFormData() {
|
||||||
if(this.state.contractAgreementList && this.state.contractAgreementList.length > 0) {
|
return this.props.id;
|
||||||
// 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 (
|
|
||||||
<Property
|
|
||||||
name="terms"
|
|
||||||
label={getLangText('Loan Contract')}
|
|
||||||
hidden={false}
|
|
||||||
className="notification-contract-pdf">
|
|
||||||
<embed
|
|
||||||
className="loan-form"
|
|
||||||
src={contract.blob.url_safe}
|
|
||||||
alt="pdf"
|
|
||||||
pluginspage="http://www.adobe.com/products/acrobat/readstep2.html"/>
|
|
||||||
<a href={contract.blob.url_safe} target="_blank">
|
|
||||||
<span className="glyphicon glyphicon-download" aria-hidden="true"></span> {getLangText('Download contract')}
|
|
||||||
</a>
|
|
||||||
{/* We still need to send the server information that we're accepting */}
|
|
||||||
<InputCheckbox
|
|
||||||
style={{'display': 'none'}}
|
|
||||||
key="terms_implicitly"
|
|
||||||
defaultChecked={true} />
|
|
||||||
</Property>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<Property
|
|
||||||
name="terms"
|
|
||||||
className="ascribe-property-collapsible-toggle"
|
|
||||||
style={{paddingBottom: 0}}>
|
|
||||||
<InputCheckbox
|
|
||||||
key="terms_explicitly"
|
|
||||||
defaultChecked={false}>
|
|
||||||
<span>
|
|
||||||
{getLangText('I agree to the')}
|
|
||||||
<a href={contract.blob.url_safe} target="_blank">
|
|
||||||
{getLangText('terms of ')} {contract.issuer}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</InputCheckbox>
|
|
||||||
</Property>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<Property
|
|
||||||
name="terms"
|
|
||||||
style={{paddingBottom: 0}}
|
|
||||||
hidden={true}>
|
|
||||||
<InputCheckbox
|
|
||||||
key="terms_implicitly"
|
|
||||||
defaultChecked={true} />
|
|
||||||
</Property>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getAppendix() {
|
|
||||||
if(this.state.contractAgreementList && this.state.contractAgreementList.length > 0) {
|
|
||||||
let appendix = this.state.contractAgreementList[0].appendix;
|
|
||||||
if (appendix && appendix.default) {
|
|
||||||
return (
|
|
||||||
<Property
|
|
||||||
name='appendix'
|
|
||||||
label={getLangText('Appendix')}>
|
|
||||||
<pre className="ascribe-pre">{appendix.default}</pre>
|
|
||||||
</Property>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getButtons() {
|
getButtons() {
|
||||||
@ -214,14 +104,31 @@ let LoanForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { email } = this.state;
|
||||||
|
const {
|
||||||
|
children,
|
||||||
|
createPublicContractAgreement,
|
||||||
|
email: defaultEmail,
|
||||||
|
handleSuccess,
|
||||||
|
gallery,
|
||||||
|
loanHeading,
|
||||||
|
message,
|
||||||
|
showPersonalMessage,
|
||||||
|
endDate,
|
||||||
|
startDate,
|
||||||
|
showEndDate,
|
||||||
|
showStartDate,
|
||||||
|
showPassword,
|
||||||
|
url } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
className={classnames({'ascribe-form-bordered': this.props.loanHeading})}
|
className={classnames({'ascribe-form-bordered': loanHeading})}
|
||||||
ref='form'
|
ref='form'
|
||||||
url={this.props.url}
|
url={url}
|
||||||
getFormData={this.getFormData}
|
getFormData={this.getFormData}
|
||||||
onReset={this.handleOnChange}
|
onReset={this.handleReset}
|
||||||
handleSuccess={this.props.handleSuccess}
|
handleSuccess={handleSuccess}
|
||||||
buttons={this.getButtons()}
|
buttons={this.getButtons()}
|
||||||
spinner={
|
spinner={
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
@ -229,18 +136,18 @@ let LoanForm = React.createClass({
|
|||||||
<AscribeSpinner color='dark-blue' size='md'/>
|
<AscribeSpinner color='dark-blue' size='md'/>
|
||||||
</p>
|
</p>
|
||||||
</div>}>
|
</div>}>
|
||||||
<div className={classnames({'ascribe-form-header': true, 'hidden': !this.props.loanHeading})}>
|
<div className={classnames({'ascribe-form-header': true, 'hidden': !loanHeading})}>
|
||||||
<h3>{this.props.loanHeading}</h3>
|
<h3>{loanHeading}</h3>
|
||||||
</div>
|
</div>
|
||||||
<AclInformation aim={'form'} verbs={['acl_loan']}/>
|
<AclInformation aim={'form'} verbs={['acl_loan']}/>
|
||||||
<Property
|
<Property
|
||||||
name='loanee'
|
name='loanee'
|
||||||
label={getLangText('Loanee Email')}
|
label={getLangText('Loanee Email')}
|
||||||
editable={!this.props.email}
|
editable={!defaultEmail}
|
||||||
onChange={this.handleOnChange}
|
onChange={this.handleEmailOnChange}
|
||||||
overrideForm={!!this.props.email}>
|
overrideForm={!!defaultEmail}>
|
||||||
<input
|
<input
|
||||||
value={this.props.email}
|
value={email}
|
||||||
type="email"
|
type="email"
|
||||||
placeholder={getLangText('Email of the loanee')}
|
placeholder={getLangText('Email of the loanee')}
|
||||||
required/>
|
required/>
|
||||||
@ -248,31 +155,31 @@ let LoanForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='gallery'
|
name='gallery'
|
||||||
label={getLangText('Gallery/exhibition (optional)')}
|
label={getLangText('Gallery/exhibition (optional)')}
|
||||||
editable={!this.props.gallery}
|
editable={!gallery}
|
||||||
overrideForm={!!this.props.gallery}>
|
overrideForm={!!gallery}>
|
||||||
<input
|
<input
|
||||||
value={this.props.gallery}
|
value={gallery}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={getLangText('Gallery/exhibition (optional)')}/>
|
placeholder={getLangText('Gallery/exhibition (optional)')}/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='startdate'
|
name='startdate'
|
||||||
label={getLangText('Start date')}
|
label={getLangText('Start date')}
|
||||||
editable={!this.props.startdate}
|
editable={!startDate}
|
||||||
overrideForm={!!this.props.startdate}
|
overrideForm={!!startDate}
|
||||||
hidden={!this.props.showStartDate}>
|
expanded={showStartDate}>
|
||||||
<InputDate
|
<InputDate
|
||||||
defaultValue={this.props.startdate}
|
defaultValue={startDate}
|
||||||
placeholderText={getLangText('Loan start date')} />
|
placeholderText={getLangText('Loan start date')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='enddate'
|
name='enddate'
|
||||||
editable={!this.props.enddate}
|
editable={!endDate}
|
||||||
overrideForm={!!this.props.enddate}
|
overrideForm={!!endDate}
|
||||||
label={getLangText('End date')}
|
label={getLangText('End date')}
|
||||||
hidden={!this.props.showEndDate}>
|
expanded={showEndDate}>
|
||||||
<InputDate
|
<InputDate
|
||||||
defaultValue={this.props.enddate}
|
defaultValue={endDate}
|
||||||
placeholderText={getLangText('Loan end date')} />
|
placeholderText={getLangText('Loan end date')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
@ -280,25 +187,32 @@ let LoanForm = React.createClass({
|
|||||||
label={getLangText('Personal Message')}
|
label={getLangText('Personal Message')}
|
||||||
editable={true}
|
editable={true}
|
||||||
overrideForm={true}
|
overrideForm={true}
|
||||||
hidden={!this.props.showPersonalMessage}>
|
expanded={showPersonalMessage}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.message}
|
defaultValue={message}
|
||||||
placeholder={getLangText('Enter a message...')}
|
placeholder={getLangText('Enter a message...')}
|
||||||
required={this.props.showPersonalMessage}/>
|
required={showPersonalMessage}/>
|
||||||
|
</Property>
|
||||||
|
<Property
|
||||||
|
name='contract_agreement'
|
||||||
|
label={getLangText('Loan Contract')}
|
||||||
|
className="ascribe-property-collapsible-toggle"
|
||||||
|
style={{paddingBottom: 0}}>
|
||||||
|
<InputContractAgreementCheckbox
|
||||||
|
createPublicContractAgreement={createPublicContractAgreement}
|
||||||
|
email={email} />
|
||||||
</Property>
|
</Property>
|
||||||
{this.getContractCheckbox()}
|
|
||||||
{this.getAppendix()}
|
|
||||||
<Property
|
<Property
|
||||||
name='password'
|
name='password'
|
||||||
label={getLangText('Password')}
|
label={getLangText('Password')}
|
||||||
hidden={!this.props.showPassword}>
|
expanded={showPassword}>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
placeholder={getLangText('Enter your password')}
|
placeholder={getLangText('Enter your password')}
|
||||||
required={this.props.showPassword ? 'required' : ''}/>
|
required={showPassword ? 'required' : ''}/>
|
||||||
</Property>
|
</Property>
|
||||||
{this.props.children}
|
{children}
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,8 @@ let LoanRequestAnswerForm = React.createClass({
|
|||||||
url={this.props.url}
|
url={this.props.url}
|
||||||
email={this.state.loanRequest ? this.state.loanRequest.new_owner : null}
|
email={this.state.loanRequest ? this.state.loanRequest.new_owner : null}
|
||||||
gallery={this.state.loanRequest ? this.state.loanRequest.gallery : null}
|
gallery={this.state.loanRequest ? this.state.loanRequest.gallery : null}
|
||||||
startdate={startDate}
|
startDate={startDate}
|
||||||
enddate={endDate}
|
endDate={endDate}
|
||||||
showPassword={true}
|
showPassword={true}
|
||||||
showPersonalMessage={false}
|
showPersonalMessage={false}
|
||||||
handleSuccess={this.props.handleSuccess}/>
|
handleSuccess={this.props.handleSuccess}/>
|
||||||
|
@ -21,7 +21,7 @@ import { getLangText } from '../../utils/lang_utils';
|
|||||||
import { mergeOptions } from '../../utils/general_utils';
|
import { mergeOptions } from '../../utils/general_utils';
|
||||||
|
|
||||||
|
|
||||||
let ContractAgreementForm = React.createClass({
|
let SendContractAgreementForm = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
handleSuccess: React.PropTypes.func
|
handleSuccess: React.PropTypes.func
|
||||||
},
|
},
|
||||||
@ -55,7 +55,7 @@ let ContractAgreementForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleSubmitSuccess() {
|
handleSubmitSuccess() {
|
||||||
let notification = 'Contract agreement send';
|
let notification = 'Contract agreement sent';
|
||||||
notification = new GlobalNotificationModel(notification, 'success', 10000);
|
notification = new GlobalNotificationModel(notification, 'success', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
@ -148,4 +148,4 @@ let ContractAgreementForm = React.createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default ContractAgreementForm;
|
export default SendContractAgreementForm;
|
201
js/components/ascribe_forms/input_contract_agreement_checkbox.js
Normal file
201
js/components/ascribe_forms/input_contract_agreement_checkbox.js
Normal file
@ -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 (
|
||||||
|
<div className="ascribe-property contract-appendix-form">
|
||||||
|
<p><span>{getLangText('Appendix')}</span></p>
|
||||||
|
<pre className="ascribe-pre">{contractAgreement.appendix.default}</pre>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getContractCheckbox() {
|
||||||
|
const contractAgreement = this.getContractAgreement();
|
||||||
|
|
||||||
|
if(contractAgreement) {
|
||||||
|
const {
|
||||||
|
datetime_accepted: datetimeAccepted,
|
||||||
|
contract: {
|
||||||
|
issuer: contractIssuer,
|
||||||
|
blob: { url_safe: contractUrl }
|
||||||
|
}
|
||||||
|
} = contractAgreement;
|
||||||
|
|
||||||
|
if(datetimeAccepted) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="notification-contract-pdf"
|
||||||
|
style={{paddingBottom: '1em'}}>
|
||||||
|
<embed
|
||||||
|
className="embed-form"
|
||||||
|
src={contractUrl}
|
||||||
|
alt="pdf"
|
||||||
|
pluginspage="http://www.adobe.com/products/acrobat/readstep2.html"/>
|
||||||
|
<a href={contractUrl} target="_blank">
|
||||||
|
<span className="glyphicon glyphicon-download" aria-hidden="true" /> {getLangText('Download contract')}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
disabled,
|
||||||
|
style } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InputCheckbox
|
||||||
|
name={name}
|
||||||
|
disabled={disabled}
|
||||||
|
style={style}
|
||||||
|
onChange={this.onChange}
|
||||||
|
key="terms_explicitly"
|
||||||
|
defaultChecked={false}>
|
||||||
|
<span>
|
||||||
|
{getLangText('I agree to the')}
|
||||||
|
<a href={contractUrl} target="_blank">
|
||||||
|
{getLangText('terms of ')} {contractIssuer}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</InputCheckbox>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{this.getContractCheckbox()}
|
||||||
|
{this.getAppendix()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default InputContractAgreementCheckbox;
|
@ -3,62 +3,69 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactAddons from 'react/addons';
|
import ReactAddons from 'react/addons';
|
||||||
|
|
||||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
import Panel from 'react-bootstrap/lib/Panel';
|
||||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
|
||||||
|
|
||||||
import AppConstants from '../../constants/application_constants';
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
|
||||||
import { mergeOptions } from '../../utils/general_utils';
|
import { mergeOptions } from '../../utils/general_utils';
|
||||||
|
|
||||||
|
|
||||||
let Property = React.createClass({
|
const { bool, element, string, oneOfType, func, object, arrayOf } = React.PropTypes;
|
||||||
propTypes: {
|
|
||||||
hidden: React.PropTypes.bool,
|
|
||||||
|
|
||||||
autoFocus: React.PropTypes.bool,
|
const Property = React.createClass({
|
||||||
editable: React.PropTypes.bool,
|
propTypes: {
|
||||||
|
editable: bool,
|
||||||
|
|
||||||
// If we want Form to have a different value for disabled as Property has one for
|
// 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
|
// editable, we need to set overrideForm to true, as it will then override Form's
|
||||||
// disabled value for individual Properties
|
// disabled value for individual Properties
|
||||||
overrideForm: React.PropTypes.bool,
|
overrideForm: bool,
|
||||||
|
|
||||||
tooltip: React.PropTypes.element,
|
label: string,
|
||||||
label: React.PropTypes.string,
|
value: oneOfType([
|
||||||
value: React.PropTypes.oneOfType([
|
string,
|
||||||
React.PropTypes.string,
|
element
|
||||||
React.PropTypes.element
|
|
||||||
]),
|
]),
|
||||||
footer: React.PropTypes.element,
|
footer: element,
|
||||||
handleChange: React.PropTypes.func,
|
handleChange: func,
|
||||||
ignoreFocus: React.PropTypes.bool,
|
ignoreFocus: bool,
|
||||||
name: React.PropTypes.oneOfType([
|
name: string.isRequired,
|
||||||
React.PropTypes.string,
|
className: string,
|
||||||
React.PropTypes.number
|
|
||||||
]).isRequired,
|
|
||||||
className: React.PropTypes.string,
|
|
||||||
|
|
||||||
onClick: React.PropTypes.func,
|
onClick: func,
|
||||||
onChange: React.PropTypes.func,
|
onChange: func,
|
||||||
onBlur: React.PropTypes.func,
|
onBlur: func,
|
||||||
|
|
||||||
children: React.PropTypes.oneOfType([
|
children: oneOfType([
|
||||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
arrayOf(element),
|
||||||
React.PropTypes.element
|
element
|
||||||
]),
|
]),
|
||||||
style: React.PropTypes.object
|
style: object,
|
||||||
|
expanded: bool,
|
||||||
|
checkboxLabel: string,
|
||||||
|
autoFocus: bool
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
return {
|
return {
|
||||||
editable: true,
|
editable: true,
|
||||||
hidden: false,
|
expanded: true,
|
||||||
className: ''
|
className: ''
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
|
const { expanded, ignoreFocus, checkboxLabel } = this.props;
|
||||||
|
|
||||||
return {
|
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.
|
// Please don't confuse initialValue with react's defaultValue.
|
||||||
// initialValue is set by us to ensure that a user can reset a specific
|
// initialValue is set by us to ensure that a user can reset a specific
|
||||||
// property (after editing) to its initial value
|
// property (after editing) to its initial value
|
||||||
@ -70,14 +77,26 @@ let Property = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (this.props.autoFocus) {
|
if(this.props.autoFocus) {
|
||||||
this.handleFocus();
|
this.handleFocus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillReceiveProps() {
|
componentWillReceiveProps(nextProps) {
|
||||||
let childInput = this.refs.input;
|
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
|
// In order to set this.state.value from another component
|
||||||
// the state of value should only be set if its not undefined and
|
// the state of value should only be set if its not undefined and
|
||||||
// actually references something
|
// actually references something
|
||||||
@ -90,13 +109,13 @@ let Property = React.createClass({
|
|||||||
// from native HTML elements.
|
// from native HTML elements.
|
||||||
// To enable developers to create input elements, they can expose a property called value
|
// 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
|
// 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({
|
this.setState({
|
||||||
value: childInput.state.value
|
value: childInput.state.value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.state.initialValue && childInput.props.defaultValue) {
|
if(!this.state.initialValue && childInput && childInput.props.defaultValue) {
|
||||||
this.setState({
|
this.setState({
|
||||||
initialValue: childInput.props.defaultValue
|
initialValue: childInput.props.defaultValue
|
||||||
});
|
});
|
||||||
@ -148,7 +167,7 @@ let Property = React.createClass({
|
|||||||
handleFocus() {
|
handleFocus() {
|
||||||
// if ignoreFocus (bool) is defined, then just ignore focusing on
|
// if ignoreFocus (bool) is defined, then just ignore focusing on
|
||||||
// the property and input
|
// the property and input
|
||||||
if(this.props.ignoreFocus) {
|
if(this.state.ignoreFocus) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +219,7 @@ let Property = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getClassName() {
|
getClassName() {
|
||||||
if(this.props.hidden){
|
if(!this.state.expanded && !this.props.checkboxLabel){
|
||||||
return 'is-hidden';
|
return 'is-hidden';
|
||||||
}
|
}
|
||||||
if(!this.props.editable){
|
if(!this.props.editable){
|
||||||
@ -216,40 +235,92 @@ let Property = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setExpanded(expanded) {
|
||||||
|
this.setState({ expanded });
|
||||||
|
},
|
||||||
|
|
||||||
renderChildren(style) {
|
renderChildren(style) {
|
||||||
return ReactAddons.Children.map(this.props.children, (child) => {
|
// Input's props should only be cloned and propagated down the tree,
|
||||||
return ReactAddons.addons.cloneWithProps(child, {
|
// if the component is actually being shown (!== 'expanded === false')
|
||||||
style,
|
if((this.state.expanded && this.props.checkboxLabel) || !this.props.checkboxLabel) {
|
||||||
onChange: this.handleChange,
|
return ReactAddons.Children.map(this.props.children, (child) => {
|
||||||
onFocus: this.handleFocus,
|
|
||||||
onBlur: this.handleBlur,
|
// Since refs will be overriden by this functions return statement,
|
||||||
disabled: !this.props.editable,
|
// we still want to be able to define refs for nested `Form` or `Property`
|
||||||
ref: 'input',
|
// children, which is why we're upfront simply invoking the callback-ref-
|
||||||
name: this.props.name
|
// 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 (
|
||||||
|
<p>
|
||||||
|
<span className="pull-left">{this.props.label}</span>
|
||||||
|
<span className="pull-right">{this.state.errors}</span>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleCheckboxToggle() {
|
||||||
|
this.setState({expanded: !this.state.expanded});
|
||||||
|
},
|
||||||
|
|
||||||
|
getCheckbox() {
|
||||||
|
const { checkboxLabel } = this.props;
|
||||||
|
|
||||||
|
if(checkboxLabel) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="ascribe-property-collapsible-toggle"
|
||||||
|
onClick={this.handleCheckboxToggle}>
|
||||||
|
<input
|
||||||
|
onChange={this.handleCheckboxToggle}
|
||||||
|
type="checkbox"
|
||||||
|
checked={this.state.expanded}
|
||||||
|
ref="checkboxCollapsible"/>
|
||||||
|
<span className="checkbox">{' ' + checkboxLabel}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let footer = null;
|
let footer = null;
|
||||||
let tooltip = <span/>;
|
let style = Object.assign({}, this.props.style);
|
||||||
let style = this.props.style ? mergeOptions({}, this.props.style) : {};
|
|
||||||
|
|
||||||
if(this.props.tooltip){
|
|
||||||
tooltip = (
|
|
||||||
<Tooltip>
|
|
||||||
{this.props.tooltip}
|
|
||||||
</Tooltip>);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.props.footer){
|
if(this.props.footer){
|
||||||
footer = (
|
footer = (
|
||||||
<div className="ascribe-property-footer">
|
<div className="ascribe-property-footer">
|
||||||
{this.props.footer}
|
{this.props.footer}
|
||||||
</div>);
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.props.editable) {
|
if (!this.state.expanded) {
|
||||||
|
style.paddingBottom = 0;
|
||||||
|
}
|
||||||
|
if (!this.props.editable) {
|
||||||
style.cursor = 'not-allowed';
|
style.cursor = 'not-allowed';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,19 +329,17 @@ let Property = React.createClass({
|
|||||||
className={'ascribe-property-wrapper ' + this.getClassName()}
|
className={'ascribe-property-wrapper ' + this.getClassName()}
|
||||||
onClick={this.handleFocus}
|
onClick={this.handleFocus}
|
||||||
style={style}>
|
style={style}>
|
||||||
<OverlayTrigger
|
{this.getCheckbox()}
|
||||||
delay={500}
|
<Panel
|
||||||
placement="top"
|
collapsible
|
||||||
overlay={tooltip}>
|
expanded={this.state.expanded}
|
||||||
|
className="bs-custom-panel">
|
||||||
<div className={'ascribe-property ' + this.props.className}>
|
<div className={'ascribe-property ' + this.props.className}>
|
||||||
<p>
|
{this.getLabelAndErrors()}
|
||||||
<span className="pull-left">{this.props.label}</span>
|
|
||||||
<span className="pull-right">{this.state.errors}</span>
|
|
||||||
</p>
|
|
||||||
{this.renderChildren(style)}
|
{this.renderChildren(style)}
|
||||||
{footer}
|
{footer}
|
||||||
</div>
|
</div>
|
||||||
</OverlayTrigger>
|
</Panel>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import Tooltip from 'react-bootstrap/lib/Tooltip';
|
|||||||
import Panel from 'react-bootstrap/lib/Panel';
|
import Panel from 'react-bootstrap/lib/Panel';
|
||||||
|
|
||||||
|
|
||||||
let PropertyCollapsile = React.createClass({
|
let PropertyCollapsible = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
children: React.PropTypes.arrayOf(React.PropTypes.element),
|
children: React.PropTypes.arrayOf(React.PropTypes.element),
|
||||||
checkboxLabel: React.PropTypes.string,
|
checkboxLabel: React.PropTypes.string,
|
||||||
@ -93,4 +93,4 @@ let PropertyCollapsile = React.createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default PropertyCollapsile;
|
export default PropertyCollapsible;
|
||||||
|
@ -292,8 +292,8 @@ let PrizePieceRatings = React.createClass({
|
|||||||
url={ApiUrls.ownership_loans_pieces_request}
|
url={ApiUrls.ownership_loans_pieces_request}
|
||||||
email={this.props.currentUser.email}
|
email={this.props.currentUser.email}
|
||||||
gallery={this.props.piece.prize.name}
|
gallery={this.props.piece.prize.name}
|
||||||
startdate={today}
|
startDate={today}
|
||||||
enddate={endDate}
|
endDate={endDate}
|
||||||
showPersonalMessage={true}
|
showPersonalMessage={true}
|
||||||
showPassword={false}
|
showPassword={false}
|
||||||
handleSuccess={this.handleLoanSuccess} />
|
handleSuccess={this.handleLoanSuccess} />
|
||||||
|
@ -122,7 +122,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='artist_bio'
|
name='artist_bio'
|
||||||
label={getLangText('Artist Biography')}
|
label={getLangText('Artist Biography')}
|
||||||
hidden={disabled && !piece.extra_data.artist_bio}>
|
expanded={!disabled || !!piece.extra_data.artist_bio}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.artist_bio}
|
defaultValue={piece.extra_data.artist_bio}
|
||||||
@ -131,7 +131,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='artist_contact_information'
|
name='artist_contact_information'
|
||||||
label={getLangText('Artist Contact Information')}
|
label={getLangText('Artist Contact Information')}
|
||||||
hidden={disabled && !piece.extra_data.artist_contact_information}>
|
expanded={!disabled || !!piece.extra_data.artist_contact_information}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.artist_contact_information}
|
defaultValue={piece.extra_data.artist_contact_information}
|
||||||
@ -140,7 +140,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='conceptual_overview'
|
name='conceptual_overview'
|
||||||
label={getLangText('Conceptual Overview')}
|
label={getLangText('Conceptual Overview')}
|
||||||
hidden={disabled && !piece.extra_data.conceptual_overview}>
|
expanded={!disabled || !!piece.extra_data.conceptual_overview}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.conceptual_overview}
|
defaultValue={piece.extra_data.conceptual_overview}
|
||||||
@ -149,7 +149,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='medium'
|
name='medium'
|
||||||
label={getLangText('Medium (technical specifications)')}
|
label={getLangText('Medium (technical specifications)')}
|
||||||
hidden={disabled && !piece.extra_data.medium}>
|
expanded={!disabled || !!piece.extra_data.medium}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.medium}
|
defaultValue={piece.extra_data.medium}
|
||||||
@ -158,7 +158,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='size_duration'
|
name='size_duration'
|
||||||
label={getLangText('Size / Duration')}
|
label={getLangText('Size / Duration')}
|
||||||
hidden={disabled && !piece.extra_data.size_duration}>
|
expanded={!disabled || !!piece.extra_data.size_duration}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.size_duration}
|
defaultValue={piece.extra_data.size_duration}
|
||||||
@ -167,7 +167,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='display_instructions'
|
name='display_instructions'
|
||||||
label={getLangText('Display instructions')}
|
label={getLangText('Display instructions')}
|
||||||
hidden={disabled && !piece.extra_data.display_instructions}>
|
expanded={!disabled || !!piece.extra_data.display_instructions}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.display_instructions}
|
defaultValue={piece.extra_data.display_instructions}
|
||||||
@ -176,7 +176,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='additional_details'
|
name='additional_details'
|
||||||
label={getLangText('Additional details')}
|
label={getLangText('Additional details')}
|
||||||
hidden={disabled && !piece.extra_data.additional_details}>
|
expanded={!disabled || !!piece.extra_data.additional_details}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.additional_details}
|
defaultValue={piece.extra_data.additional_details}
|
||||||
|
@ -214,8 +214,8 @@ let CylandRegisterPiece = React.createClass({
|
|||||||
url={ApiUrls.ownership_loans_pieces}
|
url={ApiUrls.ownership_loans_pieces}
|
||||||
email={this.state.whitelabel.user}
|
email={this.state.whitelabel.user}
|
||||||
gallery="Cyland Archive"
|
gallery="Cyland Archive"
|
||||||
startdate={today}
|
startDate={today}
|
||||||
enddate={datetimeWhenWeAllWillBeFlyingCoolHoverboardsAndDinosaursWillLiveAgain}
|
endDate={datetimeWhenWeAllWillBeFlyingCoolHoverboardsAndDinosaursWillLiveAgain}
|
||||||
showStartDate={false}
|
showStartDate={false}
|
||||||
showEndDate={false}
|
showEndDate={false}
|
||||||
showPersonalMessage={false}
|
showPersonalMessage={false}
|
||||||
|
@ -104,7 +104,7 @@ let IkonotvArtistDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='artist_website'
|
name='artist_website'
|
||||||
label={getLangText('Artist Website')}
|
label={getLangText('Artist Website')}
|
||||||
hidden={this.props.disabled && !this.props.piece.extra_data.artist_website}>
|
expanded={!this.props.disabled || !!this.props.piece.extra_data.artist_website}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.artist_website}
|
defaultValue={this.props.piece.extra_data.artist_website}
|
||||||
@ -113,7 +113,7 @@ let IkonotvArtistDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='gallery_website'
|
name='gallery_website'
|
||||||
label={getLangText('Website of related Gallery, Museum, etc.')}
|
label={getLangText('Website of related Gallery, Museum, etc.')}
|
||||||
hidden={this.props.disabled && !this.props.piece.extra_data.gallery_website}>
|
expanded={!this.props.disabled || !!this.props.piece.extra_data.gallery_website}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.gallery_website}
|
defaultValue={this.props.piece.extra_data.gallery_website}
|
||||||
@ -122,7 +122,7 @@ let IkonotvArtistDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='additional_websites'
|
name='additional_websites'
|
||||||
label={getLangText('Additional Websites/Publications/Museums/Galleries')}
|
label={getLangText('Additional Websites/Publications/Museums/Galleries')}
|
||||||
hidden={this.props.disabled && !this.props.piece.extra_data.additional_websites}>
|
expanded={!this.props.disabled || !!this.props.piece.extra_data.additional_websites}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.additional_websites}
|
defaultValue={this.props.piece.extra_data.additional_websites}
|
||||||
@ -131,7 +131,7 @@ let IkonotvArtistDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='conceptual_overview'
|
name='conceptual_overview'
|
||||||
label={getLangText('Short text about the Artist')}
|
label={getLangText('Short text about the Artist')}
|
||||||
hidden={this.props.disabled && !this.props.piece.extra_data.conceptual_overview}>
|
expanded={!this.props.disabled || !!this.props.piece.extra_data.conceptual_overview}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.conceptual_overview}
|
defaultValue={this.props.piece.extra_data.conceptual_overview}
|
||||||
|
@ -103,7 +103,7 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='medium'
|
name='medium'
|
||||||
label={getLangText('Medium')}
|
label={getLangText('Medium')}
|
||||||
hidden={this.props.disabled && !this.props.piece.extra_data.medium}>
|
expanded={!this.props.disabled || !!this.props.piece.extra_data.medium}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.medium}
|
defaultValue={this.props.piece.extra_data.medium}
|
||||||
@ -112,7 +112,7 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='size_duration'
|
name='size_duration'
|
||||||
label={getLangText('Size/Duration')}
|
label={getLangText('Size/Duration')}
|
||||||
hidden={this.props.disabled && !this.props.piece.extra_data.size_duration}>
|
expanded={!this.props.disabled || !!this.props.piece.extra_data.size_duration}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.size_duration}
|
defaultValue={this.props.piece.extra_data.size_duration}
|
||||||
@ -121,7 +121,7 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='copyright'
|
name='copyright'
|
||||||
label={getLangText('Copyright')}
|
label={getLangText('Copyright')}
|
||||||
hidden={this.props.disabled && !this.props.piece.extra_data.copyright}>
|
expanded={!this.props.disabled || !!this.props.piece.extra_data.copyright}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.copyright}
|
defaultValue={this.props.piece.extra_data.copyright}
|
||||||
@ -130,7 +130,7 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='courtesy_of'
|
name='courtesy_of'
|
||||||
label={getLangText('Courtesy of')}
|
label={getLangText('Courtesy of')}
|
||||||
hidden={this.props.disabled && !this.props.piece.extra_data.courtesy_of}>
|
expanded={!this.props.disabled || !!this.props.piece.extra_data.courtesy_of}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.courtesy_of}
|
defaultValue={this.props.piece.extra_data.courtesy_of}
|
||||||
@ -139,7 +139,7 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='copyright_of_photography'
|
name='copyright_of_photography'
|
||||||
label={getLangText('Copyright of Photography')}
|
label={getLangText('Copyright of Photography')}
|
||||||
hidden={this.props.disabled && !this.props.piece.extra_data.copyright_of_photography}>
|
expanded={!this.props.disabled || !!this.props.piece.extra_data.copyright_of_photography}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.copyright_of_photography}
|
defaultValue={this.props.piece.extra_data.copyright_of_photography}
|
||||||
@ -148,7 +148,7 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='additional_details'
|
name='additional_details'
|
||||||
label={getLangText('Additional Details about the artwork')}
|
label={getLangText('Additional Details about the artwork')}
|
||||||
hidden={this.props.disabled && !this.props.piece.extra_data.additional_details}>
|
expanded={!this.props.disabled || !!this.props.piece.extra_data.additional_details}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.additional_details}
|
defaultValue={this.props.piece.extra_data.additional_details}
|
||||||
|
@ -199,10 +199,11 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
|
|
||||||
getSlideLoan() {
|
getSlideLoan() {
|
||||||
if (this.canSubmit()) {
|
if (this.canSubmit()) {
|
||||||
let today = new Moment();
|
|
||||||
let enddate = new Moment();
|
|
||||||
enddate.add(2, 'years');
|
|
||||||
const {piece, whitelabel} = this.state;
|
const {piece, whitelabel} = this.state;
|
||||||
|
let today = new Moment();
|
||||||
|
let endDate = new Moment();
|
||||||
|
endDate.add(2, 'years');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-slide-title={getLangText('Loan')}>
|
<div data-slide-title={getLangText('Loan')}>
|
||||||
<Row className="no-margin">
|
<Row className="no-margin">
|
||||||
@ -212,8 +213,8 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
id={{piece_id: piece.id}}
|
id={{piece_id: piece.id}}
|
||||||
url={ApiUrls.ownership_loans_pieces}
|
url={ApiUrls.ownership_loans_pieces}
|
||||||
email={whitelabel.user}
|
email={whitelabel.user}
|
||||||
startdate={today}
|
startDate={today}
|
||||||
enddate={enddate}
|
endDate={endDate}
|
||||||
showStartDate={false}
|
showStartDate={false}
|
||||||
showEndDate={false}
|
showEndDate={false}
|
||||||
gallery="IkonoTV archive"
|
gallery="IkonoTV archive"
|
||||||
|
@ -129,7 +129,8 @@ let MarketSubmitButton = React.createClass({
|
|||||||
handleSuccess={this.handleAdditionalDataSuccess.bind(this, solePieceId)}
|
handleSuccess={this.handleAdditionalDataSuccess.bind(this, solePieceId)}
|
||||||
title={getLangText('Add additional information')}>
|
title={getLangText('Add additional information')}>
|
||||||
<MarketAdditionalDataForm
|
<MarketAdditionalDataForm
|
||||||
pieceId={solePieceId} />
|
pieceId={solePieceId}
|
||||||
|
submitLabel={getLangText('Continue to consignment')} />
|
||||||
</ModalWrapper>
|
</ModalWrapper>
|
||||||
|
|
||||||
<ModalWrapper
|
<ModalWrapper
|
||||||
|
@ -35,9 +35,16 @@ let MarketAdditionalDataForm = React.createClass({
|
|||||||
isInline: React.PropTypes.bool,
|
isInline: React.PropTypes.bool,
|
||||||
showHeading: React.PropTypes.bool,
|
showHeading: React.PropTypes.bool,
|
||||||
showNotification: React.PropTypes.bool,
|
showNotification: React.PropTypes.bool,
|
||||||
|
submitLabel: React.PropTypes.string,
|
||||||
handleSuccess: React.PropTypes.func
|
handleSuccess: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getDefaultProps() {
|
||||||
|
return {
|
||||||
|
submitLabel: getLangText('Register work')
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
const pieceStore = PieceStore.getState();
|
const pieceStore = PieceStore.getState();
|
||||||
|
|
||||||
@ -123,7 +130,7 @@ let MarketAdditionalDataForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isInline, handleSuccess, showHeading, showNotification } = this.props;
|
const { isInline, handleSuccess, showHeading, showNotification, submitLabel } = this.props;
|
||||||
const { piece } = this.state;
|
const { piece } = this.state;
|
||||||
let buttons, spinner, heading;
|
let buttons, spinner, heading;
|
||||||
|
|
||||||
@ -133,7 +140,7 @@ let MarketAdditionalDataForm = React.createClass({
|
|||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-default btn-wide"
|
className="btn btn-default btn-wide"
|
||||||
disabled={!this.state.isUploadReady}>
|
disabled={!this.state.isUploadReady}>
|
||||||
{getLangText('Register work')}
|
{submitLabel}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ import CylandPieceList from './components/cyland/cyland_piece_list';
|
|||||||
|
|
||||||
import IkonotvLanding from './components/ikonotv/ikonotv_landing';
|
import IkonotvLanding from './components/ikonotv/ikonotv_landing';
|
||||||
import IkonotvPieceList from './components/ikonotv/ikonotv_piece_list';
|
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 IkonotvRegisterPiece from './components/ikonotv/ikonotv_register_piece';
|
||||||
import IkonotvPieceContainer from './components/ikonotv/ikonotv_detail/ikonotv_piece_container';
|
import IkonotvPieceContainer from './components/ikonotv/ikonotv_detail/ikonotv_piece_container';
|
||||||
import IkonotvContractNotifications from './components/ikonotv/ikonotv_contract_notifications';
|
import IkonotvContractNotifications from './components/ikonotv/ikonotv_contract_notifications';
|
||||||
@ -135,7 +135,7 @@ let ROUTES = {
|
|||||||
component={AuthProxyHandler({to: '/login', when: 'loggedOut'})(ContractSettings)}/>
|
component={AuthProxyHandler({to: '/login', when: 'loggedOut'})(ContractSettings)}/>
|
||||||
<Route
|
<Route
|
||||||
path='request_loan'
|
path='request_loan'
|
||||||
component={AuthProxyHandler({to: '/login', when: 'loggedOut'})(ContractAgreementForm)}
|
component={AuthProxyHandler({to: '/login', when: 'loggedOut'})(SendContractAgreementForm)}
|
||||||
headerTitle='SEND NEW CONTRACT'
|
headerTitle='SEND NEW CONTRACT'
|
||||||
aclName='acl_create_contractagreement'/>
|
aclName='acl_create_contractagreement'/>
|
||||||
<Route
|
<Route
|
||||||
|
7
js/utils/regex_utils.js
Normal file
7
js/utils/regex_utils.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
export function isEmail(string) {
|
||||||
|
// This is a bit of a weak test for an email, but you really can't win them all
|
||||||
|
// http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address
|
||||||
|
return !!string && string.match(/.*@.*\..*/);
|
||||||
|
}
|
@ -31,16 +31,11 @@
|
|||||||
margin-top: .5em;
|
margin-top: .5em;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
|
||||||
.loan-form {
|
&.embed-form {
|
||||||
margin-top: .5em;
|
|
||||||
height: 45vh;
|
height: 45vh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.loan-form {
|
|
||||||
height: 40vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.notification-contract-pdf-download {
|
.notification-contract-pdf-download {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
@ -70,3 +65,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ascribe-property.contract-appendix-form {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
@ -1,3 +1,8 @@
|
|||||||
|
.panel {
|
||||||
|
/* Here we are overriding bootstrap to show the is-focused background color */
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
.ascribe-panel-wrapper {
|
.ascribe-panel-wrapper {
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
height: 5em;
|
height: 5em;
|
||||||
|
Loading…
Reference in New Issue
Block a user