From 815c8f2799c440d8226d1047f49e773078473f96 Mon Sep 17 00:00:00 2001 From: Anike Arni Date: Tue, 28 Mar 2017 13:11:04 -0300 Subject: [#932] Adds user recovery code form --- web-ui/app/locales/en_US/translation.json | 5 ++++- web-ui/src/account_recovery/forms/user_recovery_code_form.js | 6 ++++++ .../account_recovery/forms/user_recovery_code_form.spec.js | 12 ++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/web-ui/app/locales/en_US/translation.json b/web-ui/app/locales/en_US/translation.json index 26dccfcd..b162ae3a 100644 --- a/web-ui/app/locales/en_US/translation.json +++ b/web-ui/app/locales/en_US/translation.json @@ -92,7 +92,10 @@ "button": "Next" }, "user-form": { - "title": "Remember your backup account?" + "title": "Remember your backup account?", + "description": "When you created your account you received a message - it was sent by team@pixelated-project.org. You'll need the recovery code that is in it.", + "input-label": "type here your backup code", + "button": "Next" } }, "backup-account": { diff --git a/web-ui/src/account_recovery/forms/user_recovery_code_form.js b/web-ui/src/account_recovery/forms/user_recovery_code_form.js index 2eec96ba..9f13b498 100644 --- a/web-ui/src/account_recovery/forms/user_recovery_code_form.js +++ b/web-ui/src/account_recovery/forms/user_recovery_code_form.js @@ -18,9 +18,15 @@ import React from 'react'; import { translate } from 'react-i18next'; +import InputField from 'src/common/input_field/input_field'; +import SubmitButton from 'src/common/submit_button/submit_button'; + export const UserRecoveryCodeForm = ({ t }) => (

{t('account-recovery.user-form.title')}

+

{t('account-recovery.user-form.description')}

+ + ); diff --git a/web-ui/src/account_recovery/forms/user_recovery_code_form.spec.js b/web-ui/src/account_recovery/forms/user_recovery_code_form.spec.js index ade96f9c..c950e305 100644 --- a/web-ui/src/account_recovery/forms/user_recovery_code_form.spec.js +++ b/web-ui/src/account_recovery/forms/user_recovery_code_form.spec.js @@ -16,4 +16,16 @@ describe('UserRecoveryCodeForm', () => { it('renders title for user recovery code', () => { expect(userRecoveryCodeForm.find('h1').text()).toEqual('account-recovery.user-form.title'); }); + + it('renders description', () => { + expect(userRecoveryCodeForm.find('p').text()).toEqual('account-recovery.user-form.description'); + }); + + it('renders input for user code', () => { + expect(userRecoveryCodeForm.find('InputField').props().label).toEqual('account-recovery.user-form.input-label'); + }); + + it('renders submit button', () => { + expect(userRecoveryCodeForm.find('SubmitButton').props().buttonText).toEqual('account-recovery.user-form.button'); + }); }); -- cgit v1.2.3 From a6c848f373e4842c29c602ec7071d9b964587095 Mon Sep 17 00:00:00 2001 From: Anike Arni Date: Tue, 28 Mar 2017 13:29:51 -0300 Subject: [#932] Adds mobile progress bar to account recovery flow --- web-ui/app/images/account-recovery/step_1.svg | 52 +++++++++++++++++++++ web-ui/app/images/account-recovery/step_2.svg | 53 ++++++++++++++++++++++ web-ui/app/images/account-recovery/step_3.svg | 53 ++++++++++++++++++++++ web-ui/app/images/account-recovery/step_4.svg | 52 +++++++++++++++++++++ web-ui/app/locales/en_US/translation.json | 2 + .../forms/admin_recovery_code_form.js | 8 +++- .../forms/admin_recovery_code_form.scss | 0 web-ui/src/account_recovery/forms/forms.scss | 20 ++++++++ .../forms/user_recovery_code_form.js | 5 ++ 9 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 web-ui/app/images/account-recovery/step_1.svg create mode 100644 web-ui/app/images/account-recovery/step_2.svg create mode 100644 web-ui/app/images/account-recovery/step_3.svg create mode 100644 web-ui/app/images/account-recovery/step_4.svg delete mode 100644 web-ui/src/account_recovery/forms/admin_recovery_code_form.scss create mode 100644 web-ui/src/account_recovery/forms/forms.scss diff --git a/web-ui/app/images/account-recovery/step_1.svg b/web-ui/app/images/account-recovery/step_1.svg new file mode 100644 index 00000000..a3e73b94 --- /dev/null +++ b/web-ui/app/images/account-recovery/step_1.svg @@ -0,0 +1,52 @@ + + + + Group 5 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web-ui/app/images/account-recovery/step_2.svg b/web-ui/app/images/account-recovery/step_2.svg new file mode 100644 index 00000000..c977aa66 --- /dev/null +++ b/web-ui/app/images/account-recovery/step_2.svg @@ -0,0 +1,53 @@ + + + + Group 5 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web-ui/app/images/account-recovery/step_3.svg b/web-ui/app/images/account-recovery/step_3.svg new file mode 100644 index 00000000..80bbefdc --- /dev/null +++ b/web-ui/app/images/account-recovery/step_3.svg @@ -0,0 +1,53 @@ + + + + Group 2 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web-ui/app/images/account-recovery/step_4.svg b/web-ui/app/images/account-recovery/step_4.svg new file mode 100644 index 00000000..b94793e8 --- /dev/null +++ b/web-ui/app/images/account-recovery/step_4.svg @@ -0,0 +1,52 @@ + + + + Group 2 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web-ui/app/locales/en_US/translation.json b/web-ui/app/locales/en_US/translation.json index b162ae3a..8b85685c 100644 --- a/web-ui/app/locales/en_US/translation.json +++ b/web-ui/app/locales/en_US/translation.json @@ -84,6 +84,7 @@ "account-recovery": { "page-title": "Pixelated Account Recovery", "admin-form": { + "image-description": "Admin Recovery Code - Step 1 of 4", "title": "Contact your account administrator and ask for their part of the recovery code", "tip1": "The safest way to do this is in person.", "tip2": "You can call or text if you need to.", @@ -92,6 +93,7 @@ "button": "Next" }, "user-form": { + "image-description": "User Recovery Code - Step 2 of 4", "title": "Remember your backup account?", "description": "When you created your account you received a message - it was sent by team@pixelated-project.org. You'll need the recovery code that is in it.", "input-label": "type here your backup code", diff --git a/web-ui/src/account_recovery/forms/admin_recovery_code_form.js b/web-ui/src/account_recovery/forms/admin_recovery_code_form.js index 0a28e8b2..75cf6ea5 100644 --- a/web-ui/src/account_recovery/forms/admin_recovery_code_form.js +++ b/web-ui/src/account_recovery/forms/admin_recovery_code_form.js @@ -21,11 +21,15 @@ import { translate } from 'react-i18next'; import InputField from 'src/common/input_field/input_field'; import SubmitButton from 'src/common/submit_button/submit_button'; -import './admin_recovery_code_form.scss'; - +import './forms.scss'; export const AdminRecoveryCodeForm = ({ t, next }) => (
+ {t('account-recovery.admin-form.image-description')}

{t('account-recovery.admin-form.title')}

  • {t('account-recovery.admin-form.tip1')}
  • diff --git a/web-ui/src/account_recovery/forms/admin_recovery_code_form.scss b/web-ui/src/account_recovery/forms/admin_recovery_code_form.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/web-ui/src/account_recovery/forms/forms.scss b/web-ui/src/account_recovery/forms/forms.scss new file mode 100644 index 00000000..1ef0e8d3 --- /dev/null +++ b/web-ui/src/account_recovery/forms/forms.scss @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017 ThoughtWorks, Inc. + * + * Pixelated 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. + * + * Pixelated 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 Pixelated. If not, see . + */ + +.account-recovery-progress { + width: 100%; +} diff --git a/web-ui/src/account_recovery/forms/user_recovery_code_form.js b/web-ui/src/account_recovery/forms/user_recovery_code_form.js index 9f13b498..5b679f88 100644 --- a/web-ui/src/account_recovery/forms/user_recovery_code_form.js +++ b/web-ui/src/account_recovery/forms/user_recovery_code_form.js @@ -23,6 +23,11 @@ import SubmitButton from 'src/common/submit_button/submit_button'; export const UserRecoveryCodeForm = ({ t }) => ( + {t('account-recovery.user-form.image-description')}

    {t('account-recovery.user-form.title')}

    {t('account-recovery.user-form.description')}

    -- cgit v1.2.3 From d133b2876e49bdb285c8e8f1bdf64502d8bf9a02 Mon Sep 17 00:00:00 2001 From: Anike Arni Date: Tue, 28 Mar 2017 13:51:56 -0300 Subject: [#932] Adds new password form --- web-ui/app/locales/en_US/translation.json | 7 ++++ .../account_recovery/forms/new_password_form.js | 42 ++++++++++++++++++++++ .../forms/new_password_form.spec.js | 31 ++++++++++++++++ .../forms/user_recovery_code_form.js | 9 +++-- .../forms/user_recovery_code_form.spec.js | 9 ++++- web-ui/src/account_recovery/page.js | 4 ++- web-ui/src/account_recovery/page.spec.js | 13 +++++++ web-ui/test/integration/translations.spec.js | 8 +++++ 8 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 web-ui/src/account_recovery/forms/new_password_form.js create mode 100644 web-ui/src/account_recovery/forms/new_password_form.spec.js diff --git a/web-ui/app/locales/en_US/translation.json b/web-ui/app/locales/en_US/translation.json index 8b85685c..22f533c0 100644 --- a/web-ui/app/locales/en_US/translation.json +++ b/web-ui/app/locales/en_US/translation.json @@ -98,6 +98,13 @@ "description": "When you created your account you received a message - it was sent by team@pixelated-project.org. You'll need the recovery code that is in it.", "input-label": "type here your backup code", "button": "Next" + }, + "new-password-form": { + "image-description": "New Password - Step 3 of 4", + "title": "Now, create a new password", + "input-label1": "create new password", + "input-label2": "confirm your new password", + "button": "Next" } }, "backup-account": { diff --git a/web-ui/src/account_recovery/forms/new_password_form.js b/web-ui/src/account_recovery/forms/new_password_form.js new file mode 100644 index 00000000..71239cfa --- /dev/null +++ b/web-ui/src/account_recovery/forms/new_password_form.js @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017 ThoughtWorks, Inc. + * + * Pixelated 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. + * + * Pixelated 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 Pixelated. If not, see . + */ + +import React from 'react'; +import { translate } from 'react-i18next'; + +import InputField from 'src/common/input_field/input_field'; +import SubmitButton from 'src/common/submit_button/submit_button'; + +export const NewPasswordForm = ({ t }) => ( + + {t('account-recovery.new-password.image-description')} +

    {t('account-recovery.new-password-form.title')}

    + + + + +); + +NewPasswordForm.propTypes = { + t: React.PropTypes.func.isRequired +}; + +export default translate('', { wait: true })(NewPasswordForm); diff --git a/web-ui/src/account_recovery/forms/new_password_form.spec.js b/web-ui/src/account_recovery/forms/new_password_form.spec.js new file mode 100644 index 00000000..a2986165 --- /dev/null +++ b/web-ui/src/account_recovery/forms/new_password_form.spec.js @@ -0,0 +1,31 @@ +import { shallow } from 'enzyme'; +import expect from 'expect'; +import React from 'react'; +import { NewPasswordForm } from 'src/account_recovery/forms/new_password_form'; + +describe('NewPasswordForm', () => { + let newPasswordForm; + + beforeEach(() => { + const mockTranslations = key => key; + newPasswordForm = shallow( + + ); + }); + + it('renders title for new password form', () => { + expect(newPasswordForm.find('h1').text()).toEqual('account-recovery.new-password-form.title'); + }); + + it('renders input for new password', () => { + expect(newPasswordForm.find('InputField').at(0).props().label).toEqual('account-recovery.new-password-form.input-label1'); + }); + + it('renders input to confirm new password', () => { + expect(newPasswordForm.find('InputField').at(1).props().label).toEqual('account-recovery.new-password-form.input-label2'); + }); + + it('renders submit button', () => { + expect(newPasswordForm.find('SubmitButton').props().buttonText).toEqual('account-recovery.new-password-form.button'); + }); +}); diff --git a/web-ui/src/account_recovery/forms/user_recovery_code_form.js b/web-ui/src/account_recovery/forms/user_recovery_code_form.js index 5b679f88..aaefd75d 100644 --- a/web-ui/src/account_recovery/forms/user_recovery_code_form.js +++ b/web-ui/src/account_recovery/forms/user_recovery_code_form.js @@ -21,8 +21,10 @@ import { translate } from 'react-i18next'; import InputField from 'src/common/input_field/input_field'; import SubmitButton from 'src/common/submit_button/submit_button'; -export const UserRecoveryCodeForm = ({ t }) => ( -
    +import './forms.scss'; + +export const UserRecoveryCodeForm = ({ t, next }) => ( + ( ); UserRecoveryCodeForm.propTypes = { - t: React.PropTypes.func.isRequired + t: React.PropTypes.func.isRequired, + next: React.PropTypes.func.isRequired }; export default translate('', { wait: true })(UserRecoveryCodeForm); diff --git a/web-ui/src/account_recovery/forms/user_recovery_code_form.spec.js b/web-ui/src/account_recovery/forms/user_recovery_code_form.spec.js index c950e305..a20d3b7b 100644 --- a/web-ui/src/account_recovery/forms/user_recovery_code_form.spec.js +++ b/web-ui/src/account_recovery/forms/user_recovery_code_form.spec.js @@ -5,11 +5,13 @@ import { UserRecoveryCodeForm } from 'src/account_recovery/forms/user_recovery_c describe('UserRecoveryCodeForm', () => { let userRecoveryCodeForm; + let mockNext; beforeEach(() => { const mockTranslations = key => key; + mockNext = expect.createSpy(); userRecoveryCodeForm = shallow( - + ); }); @@ -28,4 +30,9 @@ describe('UserRecoveryCodeForm', () => { it('renders submit button', () => { expect(userRecoveryCodeForm.find('SubmitButton').props().buttonText).toEqual('account-recovery.user-form.button'); }); + + it('submits form to next step', () => { + userRecoveryCodeForm.find('form').simulate('submit'); + expect(mockNext).toHaveBeenCalled(); + }); }); diff --git a/web-ui/src/account_recovery/page.js b/web-ui/src/account_recovery/page.js index 93781729..f867fcd5 100644 --- a/web-ui/src/account_recovery/page.js +++ b/web-ui/src/account_recovery/page.js @@ -21,6 +21,7 @@ import DocumentTitle from 'react-document-title'; import Header from 'src/common/header/header'; import AdminRecoveryCodeForm from 'src/account_recovery/forms/admin_recovery_code_form'; import UserRecoveryCodeForm from 'src/account_recovery/forms/user_recovery_code_form'; +import NewPasswordForm from 'src/account_recovery/forms/new_password_form'; import Footer from 'src/common/footer/footer'; import 'font-awesome/scss/font-awesome.scss'; @@ -41,7 +42,8 @@ export class Page extends React.Component { steps = { 0: , - 1: + 1: , + 2: } mainContent = () => this.steps[this.state.step]; diff --git a/web-ui/src/account_recovery/page.spec.js b/web-ui/src/account_recovery/page.spec.js index 37c7be6f..f5e52c85 100644 --- a/web-ui/src/account_recovery/page.spec.js +++ b/web-ui/src/account_recovery/page.spec.js @@ -6,6 +6,7 @@ import { Page } from 'src/account_recovery/page'; import Header from 'src/common/header/header'; import AdminRecoveryCodeForm from 'src/account_recovery/forms/admin_recovery_code_form'; import UserRecoveryCodeForm from 'src/account_recovery/forms/user_recovery_code_form'; +import NewPasswordForm from 'src/account_recovery/forms/new_password_form'; import Footer from 'src/common/footer/footer'; describe('Account Recovery Page', () => { @@ -37,6 +38,8 @@ describe('Account Recovery Page', () => { it('renders admin recovery code form as default form', () => { expect(page.find(AdminRecoveryCodeForm).length).toEqual(1); + expect(page.find(UserRecoveryCodeForm).length).toEqual(0); + expect(page.find(NewPasswordForm).length).toEqual(0); }); it('renders user recovery code form when admin code submitted', () => { @@ -44,6 +47,16 @@ describe('Account Recovery Page', () => { expect(page.find(AdminRecoveryCodeForm).length).toEqual(0); expect(page.find(UserRecoveryCodeForm).length).toEqual(1); + expect(page.find(NewPasswordForm).length).toEqual(0); + }); + + it('renders new password form when user code submitted', () => { + pageInstance.nextStep({ preventDefault: () => {} }); + pageInstance.nextStep({ preventDefault: () => {} }); + + expect(page.find(AdminRecoveryCodeForm).length).toEqual(0); + expect(page.find(UserRecoveryCodeForm).length).toEqual(0); + expect(page.find(NewPasswordForm).length).toEqual(1); }); }); }); diff --git a/web-ui/test/integration/translations.spec.js b/web-ui/test/integration/translations.spec.js index 7821ac55..4b4c7b2d 100644 --- a/web-ui/test/integration/translations.spec.js +++ b/web-ui/test/integration/translations.spec.js @@ -20,6 +20,14 @@ describe('Translations', () => { expect(app.text()).toNotContain('untranslated', 'Unstranslated message found in the text: ' + app.text()); }); + + it('translates all keys on third step', () => { + const app = mount(} />); + app.find('form.admin-code-form').simulate('submit'); + app.find('form.user-code-form').simulate('submit'); + + expect(app.text()).toNotContain('untranslated', 'Unstranslated message found in the text: ' + app.text()); + }); }); context('Backup Account Page', () => { -- cgit v1.2.3