summaryrefslogtreecommitdiff
path: root/frontend/delta/js/Clipperz/PM/UI/Components/RegistrationWizard.js
Side-by-side diff
Diffstat (limited to 'frontend/delta/js/Clipperz/PM/UI/Components/RegistrationWizard.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/RegistrationWizard.js240
1 files changed, 240 insertions, 0 deletions
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/RegistrationWizard.js b/frontend/delta/js/Clipperz/PM/UI/Components/RegistrationWizard.js
new file mode 100644
index 0000000..051dcc5
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/RegistrationWizard.js
@@ -0,0 +1,240 @@
+/*
+
+Copyright 2008-2013 Clipperz Srl
+
+This file is part of Clipperz, the online password manager.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com.
+
+* Clipperz is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+* Clipperz is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU Affero General Public License for more details.
+
+* You should have received a copy of the GNU Affero General Public
+ License along with Clipperz. If not, see http://www.gnu.org/licenses/.
+
+*/
+
+Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
+
+ getDefaultProps: function () {
+ return {
+ steps: [
+ {name:'CREDENTIALS', label:'registration', _label:'credentials', description:"Choose your credentails"},
+ {name:'PASSWORD_VERIFICATION', label:'registration', _label:'verify', description:"Verify your passphrase"},
+ {name:'TERMS_OF_SERVICE', label:'registration', _label:'terms', description:"Check our terms of service"}
+ ],
+ disabled: false,
+ template: Clipperz.PM.UI.Components.PageTemplate
+ }
+ },
+
+ getInitialState: function () {
+ return {
+ currentStep: this.props['steps'][0]['name'],
+ username: '',
+ passphrase: '',
+ verify_passphrase: '',
+ no_password_recovery: false,
+ agree_terms_of_service: false
+ };
+ },
+
+ 'propTypes': {
+// steps: React.PropTypes.array,
+ disabled: React.PropTypes.bool,
+ template: React.PropTypes.func
+ },
+
+ //=========================================================================
+
+ currentStepIndex: function () {
+ return this.indexOfStepNamed(this.state['currentStep']);
+ },
+
+ indexOfStepNamed: function (aStepName) {
+ var stepConfiguration;
+ var result;
+
+ stepConfiguration = this.props['steps'].filter(function (aConfig) { return aConfig['name'] == aStepName})[0];
+ result = this.props['steps'].indexOf(stepConfiguration);
+ return result;
+ },
+
+ //=========================================================================
+
+ statusClassForStep: function (aStep) {
+ var currentStepIndex = this.currentStepIndex();
+ var stepIndex = this.indexOfStepNamed(aStep['name']);
+ var result;
+
+ if (stepIndex < currentStepIndex) {
+ result = 'left';
+ } else if (stepIndex == currentStepIndex) {
+ result = 'center';
+ } else {
+ result = 'right';
+ }
+
+ return result;
+ },
+
+ //=========================================================================
+
+ handleBackClick: function (anEvent) {
+ var nextStep;
+ anEvent.preventDefault();
+
+ if (this.currentStepIndex() > 0) {
+ nextStep = this.props['steps'][this.currentStepIndex() - 1];
+ this.setState({currentStep: nextStep['name']});
+ } else {
+ MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack');
+ }
+ },
+
+ handleForwardClick: function (anEvent) {
+ var nextStep;
+ anEvent.preventDefault();
+
+ if (this.canMoveForward()) {
+
+ if (this.currentStepIndex() < this.props['steps'].length - 1) {
+ nextStep = this.props['steps'][this.currentStepIndex() + 1];
+ this.setState({currentStep: nextStep['name']});
+ } else {
+ MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'registerNewUser', {
+ username: this.state['username'],
+ passphrase: this.state['passphrase']
+ })
+ }
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ canMoveForward: function () {
+ var result;
+ var currentStep;
+
+ result = false;
+ currentStep = this.state['currentStep'];
+ if (currentStep == 'CREDENTIALS') {
+ result = ((this.state['username'] != '') && (this.state['passphrase'] != ''));
+ } else if (currentStep == 'PASSWORD_VERIFICATION') {
+ result = (this.state['passphrase'] == this.state['verify_passphrase']);
+ } else if (currentStep == 'TERMS_OF_SERVICE') {
+ result = (this.state['no_password_recovery'] && this.state['agree_terms_of_service']);
+ }
+
+ return result && !this.props['disabled'];
+ },
+
+ //=========================================================================
+
+ handleChange: function (anEvent) {
+ var refs = this.refs;
+ var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
+ var newState = {};
+
+ if ((event.target.type == 'checkbox') || (event.target.type == 'radio')) {
+ newState[refName] = event.target.checked;
+ } else {
+ newState[refName] = event.target.value;
+ }
+ this.setState(newState);
+ },
+
+ //=========================================================================
+
+ renderIndexStep: function (aStep) {
+ return React.DOM.div({'className':'stepIndexItem ' + this.statusClassForStep(aStep)}, '.');
+ },
+
+ renderButtons: function () {
+ return [
+ React.DOM.a({className:'back button step_' + (this.currentStepIndex() - 1), onClick:this.handleBackClick}, '<<'),
+ React.DOM.a({className:'forward button step_' + (this.currentStepIndex() + 1) + ' ' + (this.canMoveForward() ? 'enabled' : 'disabled'), onClick:this.handleForwardClick}, '>>')
+ ];
+ },
+
+ render_CREDENTIALS: function () {
+ return React.DOM.div(null,[
+ React.DOM.label({'for':'name'}, "username"),
+ React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'/*, value:this.state.username*/}),
+ React.DOM.label({'for':'passphrase'}, "passphrase"),
+ React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'/*, value:this.state.passphrase*/})
+ ]);
+ },
+
+ render_PASSWORD_VERIFICATION: function () {
+ return React.DOM.div(null,[
+ React.DOM.label({'for':'verify_passphrase'}, "passphrase"),
+ React.DOM.input({'type':'password', 'name':'verify_passphrase', 'ref':'verify_passphrase', 'placeholder':"verify passphrase", 'key':'verify_passphrase'})
+ ]);
+ },
+
+ render_TERMS_OF_SERVICE: function () {
+ return React.DOM.div(null, [
+ React.DOM.div({className:'checkboxBlock'}, [
+ React.DOM.label({'for':'no_password_recovery'}, "I understand that Clipperz will not be able to recover a lost passphrase."),
+ React.DOM.input({'type':'checkbox', 'name':'no_password_recovery', 'ref':'no_password_recovery', 'key':'no_password_recovery'}),
+ React.DOM.p(null, "I understand that Clipperz will not be able to recover a lost passphrase.")
+ ]),
+ React.DOM.div({className:'checkboxBlock'}, [
+ React.DOM.label({'for':'agree_terms_of_service'}, "I have read and agreed to the Terms of Service."),
+ React.DOM.input({'type':'checkbox', 'name':'agree_terms_of_service', 'ref':'agree_terms_of_service', 'key':'agree_terms_of_service'}),
+ React.DOM.p(null, [
+ "I have read and agreed to the ",
+ React.DOM.a({href:'https://clipperz.com/terms_service/', target:'_blank'}, "Terms of Service.")
+ ])
+ ])
+ ]);
+ },
+
+ renderStep: function (aStep) {
+ return React.DOM.div({'className':'step' + ' ' + aStep['name'] + ' ' + this.statusClassForStep(aStep) + ' step_' + this.currentStepIndex()}, [
+ React.DOM.h1(null, aStep['label']),
+ React.DOM.p(null, aStep['description']),
+ this['render_' + aStep['name']].apply(),
+ React.DOM.div({'className':'stepIndex'}, MochiKit.Base.map(this.renderIndexStep, this.props['steps'])),
+ React.DOM.div({'className':'buttons'}, this.renderButtons())
+ ]);
+ },
+
+ _render: function () {
+ return React.DOM.div({'className':'registrationForm'},[
+ React.DOM.form({onChange: this.handleChange}, [
+ React.DOM.div({'className':'steps'}, MochiKit.Base.map(this.renderStep, this.props['steps']))
+ ])
+ ]);
+ },
+
+ render: function () {
+ return new this.props.template({'innerComponent': this._render()});
+ },
+
+ //=========================================================================
+
+ setInitialFocus: function () {
+ this.refs['username'].getDOMNode().focus();
+ },
+
+ componentDidUpdate: function (prevProps, prevState, rootNode) {
+ if (prevState['currentStep'] != this.state['currentStep']) {
+ if (this.state['currentStep'] == 'CREDENTIALS') {
+ this.refs['passphrase'].getDOMNode().select();
+ } else if (this.state['currentStep'] == 'PASSWORD_VERIFICATION') {
+ this.refs['verify_passphrase'].getDOMNode().select();
+ }
+ }
+ }
+
+ //=========================================================================
+});