From 862cd7986c208ccf488e3771f6bf770c3fd9b897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 19 Aug 2015 17:06:14 +0200 Subject: [PATCH 1/6] add lock/disabled functionality to form --- js/components/ascribe_forms/form.js | 6 +++- .../ascribe_forms/form_register_piece.js | 18 ++++++++++-- js/components/ascribe_forms/input_checkbox.js | 28 +++++++++++++++++-- js/components/ascribe_forms/property.js | 20 +++++++++---- sass/ascribe_settings.scss | 2 -- 5 files changed, 62 insertions(+), 12 deletions(-) diff --git a/js/components/ascribe_forms/form.js b/js/components/ascribe_forms/form.js index 2b956a7e..eac91d42 100644 --- a/js/components/ascribe_forms/form.js +++ b/js/components/ascribe_forms/form.js @@ -33,6 +33,9 @@ let Form = React.createClass({ React.PropTypes.arrayOf(React.PropTypes.element) ]), + // Can be used to freeze the whole form + disabled: React.PropTypes.bool, + // You can use the form for inline requests, like the submit click on a button. // For the form to then not display the error on top, you need to enable this option. // It will make use of the GlobalNotification @@ -203,7 +206,8 @@ let Form = React.createClass({ if (child) { return ReactAddons.addons.cloneWithProps(child, { handleChange: this.handleChangeChild, - ref: child.props.name + ref: child.props.name, + editable: !this.props.disabled }); } }); diff --git a/js/components/ascribe_forms/form_register_piece.js b/js/components/ascribe_forms/form_register_piece.js index 6545007c..a47ab00e 100644 --- a/js/components/ascribe_forms/form_register_piece.js +++ b/js/components/ascribe_forms/form_register_piece.js @@ -86,6 +86,7 @@ let RegisterPieceForm = React.createClass({ enableLocalHashing = enableLocalHashing && this.props.enableLocalHashing; return (
@@ -83,7 +105,9 @@ let InputCheckbox = React.createClass({ onChange={this.onChange} checked={this.state.value} defaultChecked={this.props.defaultChecked}/> - + {this.props.children} diff --git a/js/components/ascribe_forms/property.js b/js/components/ascribe_forms/property.js index 5a72270c..acb38234 100644 --- a/js/components/ascribe_forms/property.js +++ b/js/components/ascribe_forms/property.js @@ -6,6 +6,8 @@ import ReactAddons from 'react/addons'; import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger'; import Tooltip from 'react-bootstrap/lib/Tooltip'; +import { mergeOptions } from '../../utils/general_utils'; + let Property = React.createClass({ propTypes: { hidden: React.PropTypes.bool, @@ -167,9 +169,10 @@ let Property = React.createClass({ } }, - renderChildren() { + renderChildren(style) { return ReactAddons.Children.map(this.props.children, (child) => { return ReactAddons.addons.cloneWithProps(child, { + style, onChange: this.handleChange, onFocus: this.handleFocus, onBlur: this.handleBlur, @@ -181,25 +184,32 @@ let Property = React.createClass({ render() { let tooltip = ; - if (this.props.tooltip){ + let style = this.props.style ? mergeOptions({}, this.props.style) : {}; + + if(this.props.tooltip){ tooltip = ( {this.props.tooltip} ); } let footer = null; - if (this.props.footer){ + if(this.props.footer){ footer = (
{this.props.footer}
); } + + if(!this.props.editable) { + style.cursor = 'not-allowed'; + } + return (
+ style={style}> {this.state.errors} { this.props.label} - {this.renderChildren()} + {this.renderChildren(style)} {footer}
diff --git a/sass/ascribe_settings.scss b/sass/ascribe_settings.scss index e8a57832..ad498646 100644 --- a/sass/ascribe_settings.scss +++ b/sass/ascribe_settings.scss @@ -153,12 +153,10 @@ /* Taken from: http://www.htmllion.com/css3-checkbox.html */ .checkbox { display: inline-block; - cursor: pointer; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: normal; font-size: .9em; - color: rgba(0, 0, 0, .5); vertical-align:middle; > span { From 495f5600af8fab9ce6c01ae91deda1e75a6e48e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 19 Aug 2015 17:39:25 +0200 Subject: [PATCH 2/6] implement form locking for cyland --- .../ascribe_forms/form_register_piece.js | 10 +++++++--- .../cyland_additional_data_form.js | 7 +++++-- .../cyland/cyland_register_piece.js | 19 ++++++++++++++++++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/js/components/ascribe_forms/form_register_piece.js b/js/components/ascribe_forms/form_register_piece.js index a47ab00e..3519c976 100644 --- a/js/components/ascribe_forms/form_register_piece.js +++ b/js/components/ascribe_forms/form_register_piece.js @@ -28,7 +28,10 @@ let RegisterPieceForm = React.createClass({ isFineUploaderEditable: React.PropTypes.bool, enableLocalHashing: React.PropTypes.bool, children: React.PropTypes.element, - onLoggedOut: React.PropTypes.func + onLoggedOut: React.PropTypes.func, + + // For this form to work with SlideContainer, we sometimes have to disable it + disabled: React.PropTypes.bool }, getDefaultProps() { @@ -84,9 +87,10 @@ let RegisterPieceForm = React.createClass({ let currentUser = this.state.currentUser; let enableLocalHashing = currentUser && currentUser.profile ? currentUser.profile.hash_locally : false; enableLocalHashing = enableLocalHashing && this.props.enableLocalHashing; + return ( + disabled={!this.state.isUploadReady || this.props.disabled}> {this.props.submitMessage} } spinner={ diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js b/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js index 38eeee7f..397e5d6d 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js @@ -19,7 +19,9 @@ import { getLangText } from '../../../../../../utils/lang_utils'; let CylandAdditionalDataForm = React.createClass({ propTypes: { handleSuccess: React.PropTypes.func.isRequired, - piece: React.PropTypes.object.isRequired + piece: React.PropTypes.object.isRequired, + + disabled: React.PropTypes.bool }, getInitialState() { @@ -67,6 +69,7 @@ let CylandAdditionalDataForm = React.createClass({ if(this.props.piece && this.props.piece.id) { return ( + disabled={!this.state.isUploadReady || this.props.disabled}> {getLangText('Proceed to loan')} } 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 1c07bbd1..6e4abead 100644 --- a/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js +++ b/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js @@ -53,7 +53,8 @@ let CylandRegisterPiece = React.createClass({ WhitelabelStore.getState(), { selectedLicense: 0, - isFineUploaderActive: false + isFineUploaderActive: false, + step: 0 }); }, @@ -99,11 +100,16 @@ let CylandRegisterPiece = React.createClass({ PieceActions.updatePiece(response.piece); } + this.incrementStep(); + this.refs.slidesContainer.nextSlide(); }, handleAdditionalDataSuccess() { this.refreshPieceList(); + + this.incrementStep(); + this.refs.slidesContainer.nextSlide(); }, @@ -117,6 +123,15 @@ 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 + incrementStep() { + // also increase step + let newStep = this.state.step + 1; + this.setState({ + step: newStep + }); + }, + refreshPieceList() { PieceListActions.fetchPieceList( this.state.page, @@ -155,6 +170,7 @@ let CylandRegisterPiece = React.createClass({ 0} enableLocalHashing={false} headerMessage={getLangText('Submit to Cyland Archive')} submitMessage={getLangText('Submit')} @@ -182,6 +198,7 @@ let CylandRegisterPiece = React.createClass({ 1} handleSuccess={this.handleAdditionalDataSuccess} piece={this.state.piece}/> From 215f251845a6207a798b66c9d2cee014bfa2ca97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 19 Aug 2015 18:09:37 +0200 Subject: [PATCH 3/6] enable overriding of editable prop for property --- js/components/ascribe_forms/form.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/js/components/ascribe_forms/form.js b/js/components/ascribe_forms/form.js index eac91d42..8522825c 100644 --- a/js/components/ascribe_forms/form.js +++ b/js/components/ascribe_forms/form.js @@ -207,7 +207,10 @@ let Form = React.createClass({ return ReactAddons.addons.cloneWithProps(child, { handleChange: this.handleChangeChild, ref: child.props.name, - editable: !this.props.disabled + + // We need this in order to make editable be overridable when setting it directly + // on Property + editable: typeof child.props.editable !== 'undefined' ? child.props.editable : !this.props.disabled }); } }); From 689796b115579e29294c8555f66214f3462d3065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 19 Aug 2015 18:23:04 +0200 Subject: [PATCH 4/6] slidecontainer: display lock on progress --- .../slides_container.js | 27 +++++++++++++++++-- .../cyland/cyland_register_piece.js | 6 ++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/js/components/ascribe_slides_container/slides_container.js b/js/components/ascribe_slides_container/slides_container.js index 50b6eb82..3b0c493e 100644 --- a/js/components/ascribe_slides_container/slides_container.js +++ b/js/components/ascribe_slides_container/slides_container.js @@ -12,11 +12,25 @@ let Navigation = Router.Navigation; let SlidesContainer = React.createClass({ propTypes: { children: React.PropTypes.arrayOf(React.PropTypes.element), - forwardProcess: React.PropTypes.bool.isRequired + forwardProcess: React.PropTypes.bool.isRequired, + + glyphiconClassNames: React.PropTypes.shape({ + pending: React.PropTypes.string, + complete: React.PropTypes.string + }) }, mixins: [State, Navigation], + getDefaultProps() { + return { + glyphiconClassNames: { + pending: 'glyphicon glyphicon-chevron-right', + complete: 'glyphicon glyphicon-lock' + } + }; + }, + getInitialState() { // handle queryParameters let queryParams = this.getQuery(); @@ -200,6 +214,15 @@ let SlidesContainer = React.createClass({
{breadcrumbs.map((breadcrumb, i) => { + + let glyphiconClassName; + + if(i >= this.state.slideNum) { + glyphiconClassName = this.props.glyphiconClassNames.pending; + } else { + glyphiconClassName = this.props.glyphiconClassNames.completed; + } + return ( {breadcrumb} - +
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 6e4abead..88a5c305 100644 --- a/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js +++ b/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js @@ -165,7 +165,11 @@ let CylandRegisterPiece = React.createClass({ return ( + forwardProcess={true} + glyphiconClassNames={{ + pending: 'glyphicon glyphicon-chevron-right', + completed: 'glyphicon glyphicon-lock' + }}>
From 12de8139c23ef3e3abc3c115b29654e293bc6b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 19 Aug 2015 18:36:23 +0200 Subject: [PATCH 5/6] separate breadcrumb functionality into own component --- .../slides_container.js | 54 +++---------- .../slides_container_breadcrumbs.js | 78 +++++++++++++++++++ 2 files changed, 88 insertions(+), 44 deletions(-) create mode 100644 js/components/ascribe_slides_container/slides_container_breadcrumbs.js diff --git a/js/components/ascribe_slides_container/slides_container.js b/js/components/ascribe_slides_container/slides_container.js index 3b0c493e..ea329ca2 100644 --- a/js/components/ascribe_slides_container/slides_container.js +++ b/js/components/ascribe_slides_container/slides_container.js @@ -6,6 +6,8 @@ import ReactAddons from 'react/addons'; import Col from 'react-bootstrap/lib/Col'; +import SlidesContainerBreadcrumbs from './slides_container_breadcrumbs'; + let State = Router.State; let Navigation = Router.Navigation; @@ -22,15 +24,6 @@ let SlidesContainer = React.createClass({ mixins: [State, Navigation], - getDefaultProps() { - return { - glyphiconClassNames: { - pending: 'glyphicon glyphicon-chevron-right', - complete: 'glyphicon glyphicon-lock' - } - }; - }, - getInitialState() { // handle queryParameters let queryParams = this.getQuery(); @@ -206,41 +199,13 @@ let SlidesContainer = React.createClass({ // otherwise do not display the breadcrumbs at all // Also, if there is only one child, do not display the breadcrumbs if(breadcrumbs.length === numOfChildren && breadcrumbs.length > 1 && numOfChildren > 1) { - let numSlides = breadcrumbs.length; - let columnWidth = Math.floor(12 / numSlides); - return ( -
-
-
- {breadcrumbs.map((breadcrumb, i) => { - - let glyphiconClassName; - - if(i >= this.state.slideNum) { - glyphiconClassName = this.props.glyphiconClassNames.pending; - } else { - glyphiconClassName = this.props.glyphiconClassNames.completed; - } - - return ( - - - - ); - })} -
-
-
+ ); } else { return null; @@ -251,9 +216,9 @@ let SlidesContainer = React.createClass({ // Also, a key is nice to have! renderChildren() { return ReactAddons.Children.map(this.props.children, (child, i) => { + // since the default parameter of startFrom is -1, we do not need to check // if its actually present in the url bar, as it will just not match - if(i >= this.state.startFrom) { return ReactAddons.addons.cloneWithProps(child, { className: 'ascribe-slide', @@ -266,6 +231,7 @@ let SlidesContainer = React.createClass({ // Abortions are bad mkay return null; } + }); }, diff --git a/js/components/ascribe_slides_container/slides_container_breadcrumbs.js b/js/components/ascribe_slides_container/slides_container_breadcrumbs.js new file mode 100644 index 00000000..eb3e95f1 --- /dev/null +++ b/js/components/ascribe_slides_container/slides_container_breadcrumbs.js @@ -0,0 +1,78 @@ +'use strict'; + +import React from 'react'; + +import Col from 'react-bootstrap/lib/Col'; + + +// Note: +// +// If we ever need generic breadcrumbs component, we should refactor this +let SlidesContainerBreadcrumbs = React.createClass({ + propTypes: { + breadcrumbs: React.PropTypes.arrayOf(React.PropTypes.string).isRequired, + + slideNum: React.PropTypes.number.isRequired, + numOfSlides: React.PropTypes.number.isRequired, + + containerWidth: React.PropTypes.number.isRequired, + + glyphiconClassNames: React.PropTypes.shape({ + pending: React.PropTypes.string, + complete: React.PropTypes.string + }) + }, + + getDefaultProps() { + return { + glyphiconClassNames: { + pending: 'glyphicon glyphicon-chevron-right', + complete: 'glyphicon glyphicon-lock' + } + }; + }, + + render() { + let breadcrumbs = this.props.breadcrumbs; + let numSlides = breadcrumbs.length; + let columnWidth = Math.floor(12 / numSlides); + + return ( +
+
+
+ {breadcrumbs.map((breadcrumb, i) => { + + // Depending on the progress the user has already made, we display different + // glyphicons that can also be specified from the outside + let glyphiconClassName; + + if(i >= this.props.slideNum) { + glyphiconClassName = this.props.glyphiconClassNames.pending; + } else { + glyphiconClassName = this.props.glyphiconClassNames.completed; + } + + return ( + + + + ); + })} +
+
+
+ ); + } +}); + +export default SlidesContainerBreadcrumbs; \ No newline at end of file From 5d4762f9426d74970d481614e64f9e6e5f6fb835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Thu, 20 Aug 2015 11:03:00 +0200 Subject: [PATCH 6/6] fix lock functionality bug --- js/components/ascribe_forms/form.js | 2 +- js/components/ascribe_forms/form_loan.js | 6 ++++-- js/components/ascribe_forms/property.js | 7 +++++++ js/components/ascribe_slides_container/slides_container.js | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/js/components/ascribe_forms/form.js b/js/components/ascribe_forms/form.js index 8522825c..12e4ebae 100644 --- a/js/components/ascribe_forms/form.js +++ b/js/components/ascribe_forms/form.js @@ -210,7 +210,7 @@ let Form = React.createClass({ // We need this in order to make editable be overridable when setting it directly // on Property - editable: typeof child.props.editable !== 'undefined' ? child.props.editable : !this.props.disabled + editable: child.props.overrideForm ? child.props.editable : !this.props.disabled }); } }); diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 3fc6bd6e..201ba174 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -147,7 +147,8 @@ let LoanForm = React.createClass({ name='loanee' label={getLangText('Loanee Email')} onBlur={this.handleOnBlur} - editable={!this.props.email}> + editable={!this.props.email} + overrideForm={!this.props.email}> + editable={!this.props.gallery} + overrideForm={!this.props.gallery}> { - if(i >= this.state.startFrom) { + if(i >= this.state.startFrom && child.props['data-slide-title']) { breadcrumbs.push(child.props['data-slide-title']); } });