mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 17:33:14 +01:00
Refactor contract agreement to be a self contained component that can be used in forms
This commit is contained in:
parent
e442e6bcec
commit
3c516c1598
@ -22,8 +22,7 @@ class ContractAgreementListActions {
|
||||
if (contractAgreementList.count > 0) {
|
||||
this.actions.updateContractAgreementList(contractAgreementList.results);
|
||||
resolve(contractAgreementList.results);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
})
|
||||
@ -35,7 +34,7 @@ class ContractAgreementListActions {
|
||||
);
|
||||
}
|
||||
|
||||
fetchAvailableContractAgreementList(issuer, createContractAgreement) {
|
||||
fetchAvailableContractAgreementList(issuer, createPublicContractAgreement) {
|
||||
return Q.Promise((resolve, reject) => {
|
||||
OwnershipFetcher.fetchContractAgreementList(issuer, true, null)
|
||||
.then((acceptedContractAgreementList) => {
|
||||
@ -52,14 +51,12 @@ class ContractAgreementListActions {
|
||||
.then((pendingContractAgreementList) => {
|
||||
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) {
|
||||
// found and createPublicContractAgreement is set to true, we create a
|
||||
// new public contract agreement
|
||||
this.actions.createContractAgreementFromPublicContract(issuer);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.logGlobal(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,18 +87,14 @@ 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) => {
|
||||
OwnershipFetcher
|
||||
.createContractAgreement(issuer, contract).then(resolve)
|
||||
.catch((err) => {
|
||||
console.logGlobal(err);
|
||||
reject(err);
|
||||
});
|
||||
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
|
||||
import ContractAgreementProperty from './property_contract_agreement';
|
||||
import InputTextAreaToggable from './input_textarea_toggable';
|
||||
import Form from './form';
|
||||
import Property from './property';
|
||||
@ -22,6 +23,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
|
||||
},
|
||||
|
||||
@ -52,6 +54,7 @@ let ConsignForm = React.createClass({
|
||||
const { email } = this.state;
|
||||
const {
|
||||
autoFocusProperty,
|
||||
createPublicContractAgreement,
|
||||
email: defaultEmail,
|
||||
handleSuccess,
|
||||
id,
|
||||
@ -107,6 +110,12 @@ let ConsignForm = React.createClass({
|
||||
placeholder={getLangText('Enter a message...')}
|
||||
required />
|
||||
</Property>
|
||||
<ContractAgreementProperty
|
||||
ref='contractAgreement'
|
||||
createPublicContractAgreement={createPublicContractAgreement}
|
||||
email={email}
|
||||
embedClassName={'consign-form'}
|
||||
label={getLangText('Consign Contract')} />
|
||||
<Property
|
||||
name='password'
|
||||
label={getLangText('Password')}>
|
||||
|
@ -6,20 +6,18 @@ import classnames from 'classnames';
|
||||
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
|
||||
import ContractAgreementProperty from './property_contract_agreement';
|
||||
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 Property from './property';
|
||||
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
|
||||
import AclInformation from '../ascribe_buttons/acl_information';
|
||||
|
||||
import { mergeOptions } from '../../utils/general_utils';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import AclInformation from '../ascribe_buttons/acl_information';
|
||||
|
||||
let LoanForm = React.createClass({
|
||||
propTypes: {
|
||||
@ -49,46 +47,11 @@ 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);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
getContractAgreementsOrCreatePublic(email){
|
||||
ContractAgreementListActions.flushContractAgreementList.defer();
|
||||
if (email) {
|
||||
// fetch the available contractagreements (pending/accepted)
|
||||
ContractAgreementListActions.fetchAvailableContractAgreementList(email, true);
|
||||
}
|
||||
return {
|
||||
email: this.props.email || ''
|
||||
};
|
||||
@ -97,7 +60,7 @@ let LoanForm = React.createClass({
|
||||
getFormData() {
|
||||
return mergeOptions(
|
||||
this.props.id,
|
||||
this.getContractAgreementId()
|
||||
this.refs.contractAgreement.getFormDataForProperty()
|
||||
);
|
||||
},
|
||||
|
||||
@ -108,90 +71,8 @@ let LoanForm = React.createClass({
|
||||
});
|
||||
},
|
||||
|
||||
getContractAgreementId() {
|
||||
if (this.state.contractAgreementList && this.state.contractAgreementList.length > 0) {
|
||||
return {'contract_agreement_id': this.state.contractAgreementList[0].id};
|
||||
}
|
||||
return {};
|
||||
},
|
||||
|
||||
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 (
|
||||
<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;
|
||||
handleReset(event) {
|
||||
this.handleEmailOnChange();
|
||||
},
|
||||
|
||||
getButtons() {
|
||||
@ -222,7 +103,7 @@ let LoanForm = React.createClass({
|
||||
const { email } = this.state;
|
||||
const {
|
||||
children,
|
||||
email,
|
||||
createPublicContractAgreement,
|
||||
email: defaultEmail,
|
||||
handleSuccess,
|
||||
gallery,
|
||||
@ -242,7 +123,7 @@ let LoanForm = React.createClass({
|
||||
ref='form'
|
||||
url={url}
|
||||
getFormData={this.getFormData}
|
||||
onReset={this.handleOnChange}
|
||||
onReset={this.handleReset}
|
||||
handleSuccess={handleSuccess}
|
||||
buttons={this.getButtons()}
|
||||
spinner={
|
||||
@ -309,8 +190,12 @@ let LoanForm = React.createClass({
|
||||
placeholder={getLangText('Enter a message...')}
|
||||
required={showPersonalMessage}/>
|
||||
</Property>
|
||||
{this.getContractCheckbox()}
|
||||
{this.getAppendix()}
|
||||
<ContractAgreementProperty
|
||||
ref='contractAgreement'
|
||||
createPublicContractAgreement={createPublicContractAgreement}
|
||||
email={email}
|
||||
embedClassName={'loan-form'}
|
||||
label={getLangText('Loan Contract')} />
|
||||
<Property
|
||||
name='password'
|
||||
label={getLangText('Password')}
|
||||
|
168
js/components/ascribe_forms/property_contract_agreement.js
Normal file
168
js/components/ascribe_forms/property_contract_agreement.js
Normal file
@ -0,0 +1,168 @@
|
||||
'use strict'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import InputCheckbox from './input_checkbox';
|
||||
import Property from './property';
|
||||
|
||||
import ContractAgreementListStore from '../../stores/contract_agreement_list_store';
|
||||
import ContractAgreementListActions from '../../actions/contract_agreement_list_actions';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import { isEmail } from '../../utils/regex_utils';
|
||||
|
||||
let ContractAgreementProperty = React.createClass({
|
||||
propTypes: {
|
||||
createPublicContractAgreement: React.PropTypes.string,
|
||||
email: React.PropTypes.string,
|
||||
embedClassName: React.PropTypes.string,
|
||||
label: React.PropTypes.string
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
createPublicContractAgreement: true
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return ContractAgreementListStore.getState();
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
ContractAgreementListStore.listen(this.onChange);
|
||||
this.getContractAgreementsOrCreatePublic(this.props.email);
|
||||
},
|
||||
|
||||
componentWillReceiveProps({ email: nextEmail }) {
|
||||
const { contractAgreementList } = this.state;
|
||||
|
||||
if (nextEmail && this.props.email !== nextEmail && isEmail(nextEmail)) {
|
||||
this.getContractAgreementsOrCreatePublic(nextEmail);
|
||||
} else if (contractAgreementList && contractAgreementList.length > 0) {
|
||||
ContractAgreementListActions.flushContractAgreementList();
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
ContractAgreementListStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
getFormDataForProperty() {
|
||||
return this.getContractAgreementId();
|
||||
},
|
||||
|
||||
getContractAgreementId() {
|
||||
if (this.state.contractAgreementList && this.state.contractAgreementList.length > 0) {
|
||||
return { 'contract_agreement_id': this.state.contractAgreementList[0].id };
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
|
||||
getContractAgreementsOrCreatePublic(email) {
|
||||
ContractAgreementListActions.flushContractAgreementList.defer();
|
||||
|
||||
if (email) {
|
||||
// fetch the available contractagreements (pending/accepted)
|
||||
ContractAgreementListActions.fetchAvailableContractAgreementList(email, this.props.createPublicContractAgreement);
|
||||
}
|
||||
},
|
||||
|
||||
getAppendix() {
|
||||
const { contractAgreementList } = this.state;
|
||||
|
||||
if (contractAgreementList && contractAgreementList.length > 0) {
|
||||
const appendix = contractAgreementList[0].appendix;
|
||||
if (appendix && appendix.default) {
|
||||
return (
|
||||
<Property
|
||||
name='appendix'
|
||||
label={getLangText('Appendix')}>
|
||||
<pre className="ascribe-pre">{appendix.default}</pre>
|
||||
</Property>
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getContractCheckbox() {
|
||||
const { contractAgreementList } = this.state;
|
||||
|
||||
if (contractAgreementList && 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)
|
||||
const contractAgreement = contractAgreementList[0];
|
||||
const { issuer: contractIssuer, blob: { url_safe: contractUrl } } = contractAgreement.contract;
|
||||
|
||||
if (contractAgreement.datetime_accepted) {
|
||||
return (
|
||||
<Property
|
||||
name="terms"
|
||||
label={this.props.label}
|
||||
hidden={false}
|
||||
className="notification-contract-pdf">
|
||||
<embed
|
||||
className={this.props.embedClassName}
|
||||
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>
|
||||
{/* 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={contractUrl} target="_blank">
|
||||
{getLangText('terms of ')} {contractIssuer}
|
||||
</a>
|
||||
</span>
|
||||
</InputCheckbox>
|
||||
</Property>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Property
|
||||
name="terms"
|
||||
style={{paddingBottom: 0}}
|
||||
hidden={true}>
|
||||
<InputCheckbox
|
||||
key="terms_implicitly"
|
||||
defaultChecked={true} />
|
||||
</Property>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this.getContractCheckbox()}
|
||||
{this.getAppendix()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default ContractAgreementProperty;
|
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(/.*@.*\..*/);
|
||||
}
|
Loading…
Reference in New Issue
Block a user