mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 09:23:13 +01:00
loan contract form
This commit is contained in:
parent
e862fa39a9
commit
e933b334c2
27
js/actions/loan_contract_list_actions.js
Normal file
27
js/actions/loan_contract_list_actions.js
Normal file
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import OwnershipFetcher from '../fetchers/ownership_fetcher';
|
||||
|
||||
|
||||
class LoanContractListActions {
|
||||
constructor() {
|
||||
this.generateActions(
|
||||
'updateLoanContractList',
|
||||
'flushLoanContractList'
|
||||
);
|
||||
}
|
||||
|
||||
fetchLoanContractList() {
|
||||
OwnershipFetcher.fetchLoanContractList()
|
||||
.then((contracts) => {
|
||||
this.actions.updateLoanContractList(contracts);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.logGlobal(err);
|
||||
this.actions.updateLoanContractList([]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createActions(LoanContractListActions);
|
@ -74,6 +74,7 @@ let PasswordRequestResetForm = React.createClass({
|
||||
return (
|
||||
<Form
|
||||
ref="form"
|
||||
className='ascribe-form-wrapper'
|
||||
url={ApiUrls.users_password_reset_request}
|
||||
handleSuccess={this.handleSuccess}
|
||||
buttons={
|
||||
@ -130,6 +131,7 @@ let PasswordResetForm = React.createClass({
|
||||
return (
|
||||
<Form
|
||||
ref="form"
|
||||
className='ascribe-form-wrapper'
|
||||
url={ApiUrls.users_password_reset}
|
||||
handleSuccess={this.handleSuccess}
|
||||
getFormData={this.getFormData}
|
||||
|
@ -0,0 +1,135 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Property from '../../../../../ascribe_forms/property';
|
||||
|
||||
import LoanContractListActions from '../../../../../../actions/loan_contract_list_actions';
|
||||
import LoanContractListStore from '../../../../../../stores/loan_contract_list_store';
|
||||
|
||||
import GlobalNotificationModel from '../../../../../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
|
||||
|
||||
import Form from '../../../../../ascribe_forms/form';
|
||||
|
||||
import ApiUrls from '../../../../../../constants/api_urls';
|
||||
|
||||
import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
import { mergeOptions } from '../../../../../../utils/general_utils';
|
||||
|
||||
|
||||
let ContractForm = React.createClass({
|
||||
getInitialState() {
|
||||
return mergeOptions(
|
||||
LoanContractListStore.getState(),
|
||||
{
|
||||
selectedContract: 0
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
LoanContractListStore.listen(this.onChange);
|
||||
LoanContractListActions.fetchLoanContractList();
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
LoanContractListStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
onContractChange(event){
|
||||
this.setState({selectedContract: event.target.selectedIndex});
|
||||
},
|
||||
|
||||
handleSubmitSuccess(response) {
|
||||
let notification = new GlobalNotificationModel(response.notification, 'success', 10000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
getContracts() {
|
||||
if (this.state.contractList && this.state.contractList.length > 0) {
|
||||
return (
|
||||
<Property
|
||||
name='contract'
|
||||
label={getLangText('Contract Type')}
|
||||
onChange={this.onContractChange}
|
||||
footer={
|
||||
<a
|
||||
className="pull-right"
|
||||
href={this.state.contractList[this.state.selectedContract].s3UrlSafe}
|
||||
target="_blank">
|
||||
{getLangText('Learn more')}
|
||||
</a>
|
||||
}>
|
||||
<select name="contract">
|
||||
{this.state.contractList.map((contract, i) => {
|
||||
return (
|
||||
<option
|
||||
name={i}
|
||||
key={i}
|
||||
value={ contract.name }>
|
||||
{ contract.name }
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
</Property>);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Form
|
||||
className="ascribe-form-bordered ascribe-form-wrapper"
|
||||
ref='form'
|
||||
url={ApiUrls.ownership_loans_contract}
|
||||
handleSuccess={this.props.handleSuccess}
|
||||
buttons={<button
|
||||
type="submit"
|
||||
className="btn ascribe-btn ascribe-btn-login">
|
||||
SEND LOAN REQUEST
|
||||
</button>}
|
||||
spinner={
|
||||
<span className="btn ascribe-btn ascribe-btn-login ascribe-btn-login-spinner">
|
||||
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_medium.gif" />
|
||||
</span>
|
||||
}>
|
||||
<div className="ascribe-form-header">
|
||||
<h3>CONTRACT FORM</h3>
|
||||
</div>
|
||||
<Property
|
||||
name='artist_name'
|
||||
label={getLangText('Artist Name')}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="(e.g. Andy Warhol)"
|
||||
required/>
|
||||
</Property>
|
||||
<Property
|
||||
name='artist_email'
|
||||
label={getLangText('Artist Email')}>
|
||||
<input
|
||||
type="email"
|
||||
placeholder="(e.g. andy@warhol.co.uk)"
|
||||
required/>
|
||||
</Property>
|
||||
{this.getContracts()}
|
||||
<Property
|
||||
name='appendix'
|
||||
label={getLangText('Appendix')}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Add an appendix to the contract"
|
||||
required/>
|
||||
</Property>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default ContractForm;
|
@ -0,0 +1,120 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import WhitelabelActions from '../../../../../actions/whitelabel_actions';
|
||||
import WhitelabelStore from '../../../../../stores/whitelabel_store';
|
||||
|
||||
import PieceListStore from '../../../../../stores/piece_list_store';
|
||||
import PieceListActions from '../../../../../actions/piece_list_actions';
|
||||
|
||||
import UserStore from '../../../../../stores/user_store';
|
||||
import UserActions from '../../../../../actions/user_actions';
|
||||
|
||||
import PieceStore from '../../../../../stores/piece_store';
|
||||
import PieceActions from '../../../../../actions/piece_actions';
|
||||
|
||||
import ContractForm from './ascribe_forms/ikonotv_contract_form';
|
||||
|
||||
import GlobalNotificationModel from '../../../../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../../../../actions/global_notification_actions';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import { mergeOptions } from '../../../../../utils/general_utils';
|
||||
|
||||
|
||||
let IkonotvRegisterPiece = React.createClass({
|
||||
|
||||
mixins: [Router.Navigation],
|
||||
|
||||
getInitialState(){
|
||||
return mergeOptions(
|
||||
UserStore.getState(),
|
||||
PieceListStore.getState(),
|
||||
PieceStore.getState(),
|
||||
WhitelabelStore.getState());
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
PieceListStore.listen(this.onChange);
|
||||
UserStore.listen(this.onChange);
|
||||
PieceStore.listen(this.onChange);
|
||||
WhitelabelStore.listen(this.onChange);
|
||||
UserActions.fetchCurrentUser();
|
||||
WhitelabelActions.fetchWhitelabel();
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
PieceListStore.unlisten(this.onChange);
|
||||
UserStore.unlisten(this.onChange);
|
||||
PieceStore.unlisten(this.onChange);
|
||||
WhitelabelStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
|
||||
if(this.state.currentUser && this.state.currentUser.email) {
|
||||
// we should also make the fineuploader component editable again
|
||||
this.setState({
|
||||
isFineUploaderActive: true
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
handleRegisterSuccess(response){
|
||||
|
||||
// once the user was able to register a piece successfully, we need to make sure to keep
|
||||
// the piece list up to date
|
||||
PieceListActions.fetchPieceList(
|
||||
this.state.page,
|
||||
this.state.pageSize,
|
||||
this.state.searchTerm,
|
||||
this.state.orderBy,
|
||||
this.state.orderAsc,
|
||||
this.state.filterBy
|
||||
);
|
||||
|
||||
// also start loading the piece for the next step
|
||||
if(response && response.piece) {
|
||||
PieceActions.updatePiece(response.piece);
|
||||
}
|
||||
|
||||
this.refs.slidesContainer.setSlideNum(1);
|
||||
},
|
||||
|
||||
handleAdditionalDataSuccess() {
|
||||
this.refs.slidesContainer.setSlideNum(2);
|
||||
},
|
||||
|
||||
handleLoanSuccess(response) {
|
||||
let notification = new GlobalNotificationModel(response.notification, 'success', 10000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
PieceActions.fetchOne(this.state.piece.id);
|
||||
this.transitionTo('piece', {pieceId: this.state.piece.id});
|
||||
},
|
||||
|
||||
changeSlide() {
|
||||
// only transition to the login store, if user is not logged in
|
||||
// ergo the currentUser object is not properly defined
|
||||
if(this.state.currentUser && !this.state.currentUser.email) {
|
||||
this.onLoggedOut();
|
||||
}
|
||||
},
|
||||
|
||||
// basically redirects to the second slide (index: 1), when the user is not logged in
|
||||
onLoggedOut() {
|
||||
this.transitionTo('login');
|
||||
},
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<ContractForm />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default IkonotvRegisterPiece;
|
@ -19,6 +19,7 @@ import CylandRegisterPiece from './components/cyland/cyland_register_piece';
|
||||
import CylandPieceList from './components/cyland/cyland_piece_list';
|
||||
|
||||
import IkonotvPieceList from './components/ikonotv/ikonotv_piece_list';
|
||||
import IkonotvRegisterPiece from './components/ikonotv/ikonotv_register_piece';
|
||||
|
||||
import CCRegisterPiece from './components/cc/cc_register_piece';
|
||||
|
||||
@ -62,12 +63,12 @@ let ROUTES = {
|
||||
),
|
||||
'ikonotv': (
|
||||
<Route name="app" path={baseUrl} handler={WalletApp}>
|
||||
<Route name="landing" path={baseUrl} handler={CylandRegisterPiece} />
|
||||
<Route name="landing" path={baseUrl} handler={IkonotvRegisterPiece} />
|
||||
<Route name="login" path="login" handler={LoginContainer} />
|
||||
<Route name="logout" path="logout" handler={LogoutContainer} />
|
||||
<Route name="signup" path="signup" handler={SignupContainer} />
|
||||
<Route name="password_reset" path="password_reset" handler={PasswordResetContainer} />
|
||||
<Route name="register_piece" path="register_piece" handler={CylandRegisterPiece} />
|
||||
<Route name="register_piece" path="register_piece" handler={IkonotvRegisterPiece} />
|
||||
<Route name="pieces" path="collection" handler={IkonotvPieceList} />
|
||||
<Route name="piece" path="pieces/:pieceId" handler={CylandPieceContainer} />
|
||||
<Route name="edition" path="editions/:editionId" handler={EditionContainer} />
|
||||
|
@ -6,12 +6,19 @@ import ApiUrls from '../constants/api_urls';
|
||||
|
||||
let OwnershipFetcher = {
|
||||
/**
|
||||
* Fetch one user from the API.
|
||||
* If no arg is supplied, load the current user
|
||||
* Fetch the default, public loan contract of a user from the API.
|
||||
*/
|
||||
fetchLoanContract(email) {
|
||||
return requests.get(ApiUrls.ownership_loans_contract + '?loanee=' + email);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch the contracts of the logged-in user from the API.
|
||||
*/
|
||||
fetchLoanContractList(){
|
||||
return requests.get(ApiUrls.ownership_loans_contract);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default OwnershipFetcher;
|
||||
|
22
js/stores/loan_contract_list_store.js
Normal file
22
js/stores/loan_contract_list_store.js
Normal file
@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import LoanContractListActions from '../actions/loan_contract_list_actions';
|
||||
|
||||
|
||||
class LoanContractListStore {
|
||||
constructor() {
|
||||
this.contractList = [];
|
||||
this.bindActions(LoanContractListActions);
|
||||
}
|
||||
|
||||
onUpdateLoanContractList(contractList) {
|
||||
this.contractList = contractList;
|
||||
}
|
||||
|
||||
onFlushLoanContractList() {
|
||||
this.contractList = [];
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createStore(LoanContractListStore, 'LoanContractListStore');
|
@ -13,4 +13,13 @@
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
.ascribe-form-wrapper {
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
@media (max-width: 550px) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user