diff --git a/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js b/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js
index 6e8a77c3..84713bd9 100644
--- a/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js
+++ b/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js
@@ -10,9 +10,6 @@ import Row from 'react-bootstrap/lib/Row';
import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece';
-import Property from '../../../../ascribe_forms/property';
-import InputCheckbox from '../../../../ascribe_forms/input_checkbox';
-
import WhitelabelActions from '../../../../../actions/whitelabel_actions';
import WhitelabelStore from '../../../../../stores/whitelabel_store';
@@ -136,7 +133,7 @@ let CylandRegisterPiece = React.createClass({
this.transitionTo('piece', {pieceId: this.state.piece.id});
},
- // We need to increase the step to lock the forms that are already filed out
+ // We need to increase the step to lock the forms that are already filled out
incrementStep() {
// also increase step
let newStep = this.state.step + 1;
diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js
index 4b7f3dbc..be3bda77 100644
--- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js
+++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js
@@ -1,17 +1,8 @@
'use strict';
import React from 'react';
-import Moment from 'moment';
import classNames from 'classnames';
-
-import ModalWrapper from '../../../../../ascribe_modal/modal_wrapper';
-
-import LoanForm from '../../../../../ascribe_forms/form_loan';
-
-import Property from '../../../../../ascribe_forms/property';
-import InputCheckbox from '../../../../../ascribe_forms/input_checkbox';
-
-import ApiUrls from '../../../../../../constants/api_urls';
+import ButtonLink from 'react-router-bootstrap/lib/ButtonLink';
import { getLangText } from '../../../../../../utils/lang_utils';
@@ -22,37 +13,30 @@ let IkonotvSubmitButton = React.createClass({
piece: React.PropTypes.object.isRequired
},
- getSubmitButton() {
- return (
-
- );
- },
-
render() {
+ let piece = this.props.piece;
+ let startFrom = 1;
- let today = new Moment();
- let enddate = new Moment();
- enddate.add(1, 'years');
+ // In the Ikonotv loan page a user has to complete two steps.
+ // Since every one of those steps is atomic a user should always be able to continue
+ // where he left of.
+ // This is why we start the process form slide 1/2 if the user has already finished
+ // it in another session.
+ if(piece && piece.extra_data && Object.keys(piece.extra_data).length > 0) {
+ startFrom = 1;
+ }
return (
-
-
-
-
+
+ {getLangText('Loan to IkonoTV')}
+
);
}
});
diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js
new file mode 100644
index 00000000..6a2f8cc5
--- /dev/null
+++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js
@@ -0,0 +1,134 @@
+'use strict';
+
+import React from 'react';
+
+import Form from '../../../../../ascribe_forms/form';
+import Property from '../../../../../ascribe_forms/property';
+
+import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_toggable';
+
+import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader';
+
+import ApiUrls from '../../../../../../constants/api_urls';
+import AppConstants from '../../../../../../constants/application_constants';
+
+import requests from '../../../../../../utils/requests';
+
+import { getLangText } from '../../../../../../utils/lang_utils';
+import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_s3_fine_uploader_utils';
+
+
+let IkonotvAdditionalDataForm = React.createClass({
+ propTypes: {
+ handleSuccess: React.PropTypes.func.isRequired,
+ piece: React.PropTypes.object.isRequired,
+
+ disabled: React.PropTypes.bool
+ },
+
+ getInitialState() {
+ return {
+ isUploadReady: true
+ };
+ },
+
+ getFormData() {
+ let extradata = {};
+ let formRefs = this.refs.form.refs;
+
+ // Put additional fields in extra data object
+ Object
+ .keys(formRefs)
+ .forEach((fieldName) => {
+ extradata[fieldName] = formRefs[fieldName].state.value;
+ });
+
+ return {
+ extradata: extradata,
+ piece_id: this.props.piece.id
+ };
+
+ },
+
+ uploadStarted() {
+ this.setState({
+ isUploadReady: false
+ });
+ },
+
+ setIsUploadReady(isReady) {
+ this.setState({
+ isUploadReady: isReady
+ });
+ },
+
+ render() {
+ if(this.props.piece && this.props.piece.id) {
+ return (
+
+ );
+ } else {
+ return (
+
+
+
+ );
+ }
+ }
+});
+
+export default IkonotvAdditionalDataForm;
\ No newline at end of file
diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js
new file mode 100644
index 00000000..6a2acbb8
--- /dev/null
+++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js
@@ -0,0 +1,220 @@
+'use strict';
+
+import React from 'react';
+import Moment from 'moment';
+import Router from 'react-router';
+
+import Col from 'react-bootstrap/lib/Col';
+import Row from 'react-bootstrap/lib/Row';
+
+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 GlobalNotificationModel from '../../../../../models/global_notification_model';
+import GlobalNotificationActions from '../../../../../actions/global_notification_actions';
+
+import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece';
+import LoanForm from '../../../../ascribe_forms/form_loan';
+import IkonotvAdditionalDataForm from './ascribe_forms/ikonotv_additional_data_form';
+
+import SlidesContainer from '../../../../ascribe_slides_container/slides_container';
+
+import ApiUrls from '../../../../../constants/api_urls';
+
+import { mergeOptions } from '../../../../../utils/general_utils';
+import { getLangText } from '../../../../../utils/lang_utils';
+
+let IkonotvRegisterPiece = React.createClass({
+
+ propTypes: {
+ handleSuccess: React.PropTypes.func,
+ piece: React.PropTypes.object.isRequired
+ },
+
+ mixins: [Router.Navigation, Router.State],
+
+ getInitialState(){
+ return mergeOptions(
+ UserStore.getState(),
+ PieceListStore.getState(),
+ PieceStore.getState(),
+ {
+ step: 0
+ });
+ },
+
+ componentDidMount() {
+ PieceListStore.listen(this.onChange);
+ UserStore.listen(this.onChange);
+ PieceStore.listen(this.onChange);
+ UserActions.fetchCurrentUser();
+
+ let queryParams = this.getQuery();
+
+ // Since every step of this register process is atomic,
+ // we may need to enter the process at step 1 or 2.
+ // If this is the case, we'll need the piece number to complete submission.
+ // It is encoded in the URL as a queryParam and we're checking for it here.
+ //
+ // We're using 'in' here as we want to know if 'piece_id' is present in the url,
+ // we don't care about the value.
+ if (queryParams && 'piece_id' in queryParams) {
+ PieceActions.fetchOne(queryParams.piece_id);
+ }
+ },
+
+ componentWillUnmount() {
+ PieceListStore.unlisten(this.onChange);
+ UserStore.unlisten(this.onChange);
+ PieceStore.unlisten(this.onChange);
+ },
+
+ onChange(state) {
+ this.setState(state);
+
+ if(this.state.currentUser && this.state.currentUser.email) {
+ // we should also make the fineuploader component editable again
+ this.setState({
+ isFineUploaderActive: true
+ });
+ }
+ },
+
+
+ handleRegisterSuccess(response){
+
+ this.refreshPieceList();
+
+ // also start loading the piece for the next step
+ if(response && response.piece) {
+ PieceActions.updatePiece(response.piece);
+ }
+
+ this.incrementStep();
+
+ this.refs.slidesContainer.nextSlide();
+ },
+
+ handleAdditionalDataSuccess() {
+
+ // We need to refetch the piece again after submitting the additional data
+ // since we want it's otherData to be displayed when the user choses to click
+ // on the browsers back button.
+ PieceActions.fetchOne(this.state.piece.id);
+
+ this.refreshPieceList();
+
+ this.incrementStep();
+
+ this.refs.slidesContainer.nextSlide();
+ },
+
+ handleLoanSuccess(response) {
+ let notification = new GlobalNotificationModel(response.notification, 'success', 10000);
+ GlobalNotificationActions.appendGlobalNotification(notification);
+
+ this.refreshPieceList();
+
+ PieceActions.fetchOne(this.state.piece.id);
+ this.transitionTo('piece', {pieceId: this.state.piece.id});
+ },
+
+ // We need to increase the step to lock the forms that are already filled out
+ incrementStep() {
+ // also increase step
+ let newStep = this.state.step + 1;
+ this.setState({
+ step: newStep
+ });
+ },
+
+ refreshPieceList() {
+ PieceListActions.fetchPieceList(
+ this.state.page,
+ this.state.pageSize,
+ this.state.searchTerm,
+ this.state.orderBy,
+ this.state.orderAsc,
+ this.state.filterBy
+ );
+ },
+
+ 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() {
+
+ let today = new Moment();
+ let enddate = new Moment();
+ enddate.add(1, 'years');
+
+ return (
+
+