diff --git a/client/package.json b/client/package.json index 2cf86903..97e5359d 100644 --- a/client/package.json +++ b/client/package.json @@ -65,7 +65,7 @@ "react": "^15.0.1", "react-document-title": "^1.0.2", "react-dom": "^15.0.1", - "react-google-recaptcha": "^0.5.2", + "react-google-recaptcha": "^0.5.4", "react-motion": "^0.3.0", "react-redux": "^4.4.5", "react-router": "^2.4.0", diff --git a/client/src/actions/__tests__/config-actions-test.js b/client/src/actions/__tests__/config-actions-test.js index 0a0b7e05..b50acda7 100644 --- a/client/src/actions/__tests__/config-actions-test.js +++ b/client/src/actions/__tests__/config-actions-test.js @@ -11,8 +11,8 @@ const ConfigActions = requireUnit('actions/config-actions', { describe('Config Actions,', function () { describe('init action', function () { - it('should return INIT_CONFIGS_FULFILLED with configs if it is already retrieved', function () { - sessionStoreMock.areConfigsStored.returns(true); + it('should return INIT_CONFIGS_FULFILLED with configs if it user is logged in', function () { + sessionStoreMock.isLoggedIn.returns(true); sessionStoreMock.getConfigs.returns({ config1: 'CONFIG_1', config2: 'CONFIG_2' @@ -31,7 +31,7 @@ describe('Config Actions,', function () { it('should return INIT_CONFIGS with API_RESULT if it is not retrieved', function () { APICallMock.call.reset(); - sessionStoreMock.areConfigsStored.returns(false); + sessionStoreMock.isLoggedIn.returns(false); sessionStoreMock.getConfigs.returns({ config1: 'CONFIG_1', config2: 'CONFIG_2' diff --git a/client/src/actions/config-actions.js b/client/src/actions/config-actions.js index 70c41c46..3da9ceea 100644 --- a/client/src/actions/config-actions.js +++ b/client/src/actions/config-actions.js @@ -3,7 +3,7 @@ import sessionStore from 'lib-app/session-store'; export default { init() { - if (sessionStore.areConfigsStored()) { + if (sessionStore.isLoggedIn()) { return { type: 'INIT_CONFIGS_FULFILLED', payload: { diff --git a/client/src/actions/session-actions.js b/client/src/actions/session-actions.js index ed9490b4..3509d6a0 100644 --- a/client/src/actions/session-actions.js +++ b/client/src/actions/session-actions.js @@ -2,6 +2,8 @@ import API from 'lib-app/api-call'; import sessionStore from 'lib-app/session-store'; import store from 'app/store'; +import ConfigActions from 'actions/config-actions'; + export default { login(loginData) { return { diff --git a/client/src/app/main/captcha.js b/client/src/app/main/captcha.js new file mode 100644 index 00000000..41a4b3c3 --- /dev/null +++ b/client/src/app/main/captcha.js @@ -0,0 +1,35 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import ReCAPTCHA from 'react-google-recaptcha'; +import {connect} from 'react-redux'; + + +class Captcha extends React.Component { + constructor(props) { + super(props); + + this.state = { + value: '' + }; + } + + render() { + return ( + {this.setState({value})}} tabIndex="0" /> + ); + } + + getValue() { + return this.state.value; + } + + focus() { + ReactDOM.findDOMNode(this).focus(); + } +} + +export default connect((store) => { + return { + sitekey: store.config.reCaptchaKey + }; +}, null, null, { withRef: true })(Captcha); \ No newline at end of file diff --git a/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js b/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js index f23e7fbe..ae981c6a 100644 --- a/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js +++ b/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js @@ -4,6 +4,7 @@ import { browserHistory } from 'react-router'; import i18n from 'lib-app/i18n'; import API from 'lib-app/api-call'; +import SessionStore from 'lib-app/session-store'; import store from 'app/store'; import SessionActions from 'actions/session-actions'; @@ -41,11 +42,7 @@ class CreateTicketForm extends React.Component {
{return {content: department}}), size: 'medium' }} />
@@ -70,7 +67,7 @@ class CreateTicketForm extends React.Component { renderCaptcha() { return (
- +
); } diff --git a/client/src/app/main/main-signup/main-signup-page.js b/client/src/app/main/main-signup/main-signup-page.js index 86d0fc00..b45afbba 100644 --- a/client/src/app/main/main-signup/main-signup-page.js +++ b/client/src/app/main/main-signup/main-signup-page.js @@ -1,9 +1,11 @@ import React from 'react'; -import ReCAPTCHA from 'react-google-recaptcha'; +import ReactDOM from 'react-dom'; +import _ from 'lodash'; import i18n from 'lib-app/i18n'; import API from 'lib-app/api-call'; +import Captcha from 'app/main/captcha'; import SubmitButton from 'core-components/submit-button'; import Message from 'core-components/message'; import Form from 'core-components/form'; @@ -34,7 +36,7 @@ class MainSignUpPageWidget extends React.Component {
- +
SIGN UP @@ -75,14 +77,20 @@ class MainSignUpPageWidget extends React.Component { } onLoginFormSubmit(formState) { - this.setState({ - loading: true - }); + const captcha = this.refs.captcha.getWrappedInstance(); - API.call({ - path: '/user/signup', - data: formState - }).then(this.onSignupSuccess.bind(this)).catch(this.onSignupFail.bind(this)); + if (!captcha.getValue()) { + captcha.focus(); + } else { + this.setState({ + loading: true + }); + + API.call({ + path: '/user/signup', + data: _.extend({captcha: captcha.getValue()}, formState) + }).then(this.onSignupSuccess.bind(this)).catch(this.onSignupFail.bind(this)); + } } onSignupSuccess() { diff --git a/client/src/data/fixtures/system-fixtures.js b/client/src/data/fixtures/system-fixtures.js index c74613f9..04fc76b8 100644 --- a/client/src/data/fixtures/system-fixtures.js +++ b/client/src/data/fixtures/system-fixtures.js @@ -7,7 +7,12 @@ module.exports = [ status: 'success', data: { 'language': 'us', - 'reCaptchaKey': '6LfM5CYTAAAAAGLz6ctpf-hchX2_l0Ge-Bn-n8wS' + 'reCaptchaKey': '6LfM5CYTAAAAAGLz6ctpf-hchX2_l0Ge-Bn-n8wS', + 'departments': [ + 'Sales Support', + 'Technical Issues', + 'System and Administration' + ] } }; } diff --git a/client/src/lib-app/session-store.js b/client/src/lib-app/session-store.js index fa635f4e..94eac77f 100644 --- a/client/src/lib-app/session-store.js +++ b/client/src/lib-app/session-store.js @@ -42,6 +42,10 @@ class SessionStore { return JSON.parse(this.getItem('userData')); } + getDepartments() { + return JSON.parse(this.getItem('departments')); + } + storeRememberData({token, userId, expiration}) { this.setItem('rememberData-token', token); this.setItem('rememberData-userId', userId); @@ -51,19 +55,17 @@ class SessionStore { storeConfigs(configs) { this.setItem('language', configs.language); this.setItem('reCaptchaKey', configs.reCaptchaKey); + this.setItem('departments', JSON.stringify(configs.departments)); } getConfigs() { return { language: this.getItem('language'), - reCaptchaKey: this.getItem('reCaptchaKey') + reCaptchaKey: this.getItem('reCaptchaKey'), + departments: this.getDepartments() }; } - areConfigsStored() { - return !!this.getItem('reCaptchaKey'); - } - isRememberDataExpired() { let rememberData = this.getRememberData();