IGNITE-7650 Extracted signin/signup form to separate page, improved landing page.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/19256745 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/19256745 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/19256745 Branch: refs/heads/ignite-3345 Commit: 19256745bdf239db73a5cbd13f9eb92e064ff500 Parents: 071e27e Author: alexdel <verba...@yandex.ru> Authored: Mon Feb 19 11:25:24 2018 +0700 Committer: Andrey Novikov <anovi...@gridgain.com> Committed: Mon Feb 19 11:25:24 2018 +0700 ---------------------------------------------------------------------- modules/web-console/e2e/testcafe/Dockerfile | 2 + modules/web-console/e2e/testcafe/envtools.js | 1 + .../web-console/e2e/testcafe/fixtures/auth.js | 73 ++++--- .../e2e/testcafe/fixtures/user-profile.js | 113 ----------- .../fixtures/user-profile/credentials.js | 63 ++++++ .../testcafe/fixtures/user-profile/profile.js | 84 ++++++++ modules/web-console/e2e/testcafe/roles.js | 23 +-- modules/web-console/e2e/testcafe/testcafe.js | 4 +- modules/web-console/e2e/testenv/Dockerfile | 2 + modules/web-console/frontend/app/app.js | 14 +- .../app/components/page-configure/index.js | 3 + .../app/components/page-landing/index.js | 65 ++++++ .../app/components/page-landing/style.scss | 104 ++++++++++ .../app/components/page-landing/template.pug | 66 ++++++ .../page-password-changed/controller.js | 18 ++ .../components/page-password-changed/index.js | 33 +++ .../components/page-password-changed/style.scss | 34 ++++ .../page-password-changed/template.pug | 14 ++ .../page-password-reset/controller.js | 53 +++++ .../app/components/page-password-reset/index.js | 57 ++++++ .../components/page-password-reset/style.scss | 31 +++ .../components/page-password-reset/template.pug | 80 ++++++++ .../app/components/page-profile/controller.js | 8 +- .../app/components/page-profile/index.js | 13 +- .../app/components/page-profile/style.scss | 31 +++ .../app/components/page-profile/template.pug | 203 +++++++++++++------ .../app/components/page-signin/controller.js | 30 +++ .../app/components/page-signin/index.js | 56 +++++ .../app/components/page-signin/style.scss | 38 ++++ .../app/components/page-signin/template.pug | 161 +++++++++++++++ .../components/web-console-header/style.scss | 1 + .../components/web-console-header/template.pug | 2 +- .../frontend/app/controllers/auth.controller.js | 29 --- .../frontend/app/data/countries.json | 72 ++++--- .../frontend/app/helpers/jade/mixins.pug | 1 + .../app/modules/states/configuration.state.js | 1 + .../app/modules/states/password.state.js | 50 ----- .../frontend/app/modules/states/signin.state.js | 53 ----- .../frontend/app/modules/user/Auth.service.js | 6 +- .../app/primitives/form-field/checkbox.pug | 30 +++ .../app/primitives/form-field/dropdown.pug | 51 +++++ .../app/primitives/form-field/email.pug | 37 ++++ .../app/primitives/form-field/error.pug | 29 +++ .../app/primitives/form-field/index.pug | 27 +++ .../app/primitives/form-field/index.scss | 149 +++++++++++++- .../app/primitives/form-field/input.pug | 28 +++ .../app/primitives/form-field/label.pug | 30 +++ .../app/primitives/form-field/number.pug | 46 +++++ .../app/primitives/form-field/password.pug | 37 ++++ .../app/primitives/form-field/phone.pug | 35 ++++ .../frontend/app/primitives/form-field/text.pug | 35 ++++ .../app/primitives/form-field/tooltip.pug | 18 ++ .../frontend/app/primitives/panel/index.scss | 96 +++++++-- .../frontend/app/primitives/tooltip/index.scss | 17 ++ .../frontend/app/primitives/ui-grid/index.scss | 32 +-- .../frontend/app/services/DefaultState.js | 36 ++++ .../web-console/frontend/app/services/index.js | 2 + modules/web-console/frontend/app/vendor.js | 5 +- modules/web-console/frontend/package.json | 3 +- .../frontend/public/images/icons/collapse.svg | 3 + .../public/images/icons/exclamation.svg | 3 + .../frontend/public/images/icons/expand.svg | 3 + .../frontend/public/images/icons/index.js | 4 + .../frontend/public/images/main-screenshot.png | Bin 0 -> 86830 bytes .../public/images/page-landing-carousel-1.png | Bin 0 -> 84434 bytes .../public/images/page-landing-carousel-2.png | Bin 0 -> 106670 bytes .../public/images/page-landing-carousel-3.png | Bin 0 -> 70876 bytes .../public/stylesheets/_bootstrap-custom.scss | 1 - .../web-console/frontend/views/reset.tpl.pug | 44 ---- .../web-console/frontend/views/signin.tpl.pug | 165 --------------- 70 files changed, 2006 insertions(+), 652 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/e2e/testcafe/Dockerfile ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/Dockerfile b/modules/web-console/e2e/testcafe/Dockerfile index e58cbef..d890d10 100644 --- a/modules/web-console/e2e/testcafe/Dockerfile +++ b/modules/web-console/e2e/testcafe/Dockerfile @@ -25,6 +25,8 @@ WORKDIR /opt/testcafe/tests COPY . /opt/testcafe/tests +ENV NPM_CONFIG_LOGLEVEL warn + RUN npm install --production && \ npm cache verify --force && \ rm -rf /tmp/* http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/e2e/testcafe/envtools.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/envtools.js b/modules/web-console/e2e/testcafe/envtools.js index 846a33a..c251b5f 100644 --- a/modules/web-console/e2e/testcafe/envtools.js +++ b/modules/web-console/e2e/testcafe/envtools.js @@ -46,6 +46,7 @@ const insertTestUser = ({userId = '000000000000000000000001', token = 'ppw4tPI3J lastName: 'Doe', company: 'TestCompany', country: 'Canada', + industry: 'Banking', admin: true, token, attempts: 0, http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/e2e/testcafe/fixtures/auth.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/fixtures/auth.js b/modules/web-console/e2e/testcafe/fixtures/auth.js index 8f72b83..c845560 100644 --- a/modules/web-console/e2e/testcafe/fixtures/auth.js +++ b/modules/web-console/e2e/testcafe/fixtures/auth.js @@ -21,7 +21,7 @@ const { AngularJSSelector } = require('testcafe-angular-selectors'); const { removeData, insertTestUser } = require('../envtools'); fixture('Checking Ignite auth screen') - .page `${process.env.APP_URL || 'http://localhost:9001/'}` + .page `${process.env.APP_URL || 'http://localhost:9001/'}signin` .beforeEach(async(t) => { await removeData(); @@ -34,61 +34,59 @@ fixture('Checking Ignite auth screen') test('Testing Ignite signup validation and signup success', async(t) => { async function checkBtnDisabled() { - const btnDisabled = await t.expect(Selector('#signup').getAttribute('disabled')).ok(); + const btnDisabled = await t.expect(Selector('#signup_submit').getAttribute('disabled')).ok(); const btnNotWorks = await t - .click('#signup') + .click('#signup_submit') .expect(Selector('title').innerText).eql('Apache Ignite - Management Tool and Configuration Wizard â Apache Ignite Web Console'); return btnDisabled && btnNotWorks; } - await t.click(Selector('a').withText('Sign Up')); - await t - .click(Selector('#signup_email')) - .typeText(Selector('#signup_email'), 't...@test.com'); + .typeText(AngularJSSelector.byModel('ui_signup.email'), 't...@test.com'); await checkBtnDisabled(); await t - .typeText(AngularJSSelector.byModel('ui.password'), 'qwerty') + .typeText(AngularJSSelector.byModel('ui_signup.password'), 'qwerty') .typeText(AngularJSSelector.byModel('ui_exclude.confirm'), 'qwerty'); await checkBtnDisabled(); await t - .typeText(AngularJSSelector.byModel('ui.firstName'), 'John') - .typeText(AngularJSSelector.byModel('ui.lastName'), 'Doe'); + .typeText(AngularJSSelector.byModel('ui_signup.firstName'), 'John') + .typeText(AngularJSSelector.byModel('ui_signup.lastName'), 'Doe'); await checkBtnDisabled(); await t - .typeText(AngularJSSelector.byModel('ui.company'), 'DevNull LTD'); + .typeText(AngularJSSelector.byModel('ui_signup.company'), 'DevNull LTD'); await checkBtnDisabled(); await t - .click('#country') + .click('#countryInput') .click(Selector('span').withText('Brazil')); - // checking passwords confirm dismatch + // Checking passwords confirm dismatch. await t .click(AngularJSSelector.byModel('ui_exclude.confirm')) .pressKey('ctrl+a delete') .typeText(AngularJSSelector.byModel('ui_exclude.confirm'), 'ytrewq'); await checkBtnDisabled(); + await t .click(AngularJSSelector.byModel('ui_exclude.confirm')) .pressKey('ctrl+a delete') .typeText(AngularJSSelector.byModel('ui_exclude.confirm'), 'qwerty'); - await t.click('#signup') + await t.click('#signup_submit') .expect(Selector('title').innerText).eql('Basic Configuration â Apache Ignite Web Console'); }); test('Testing Ignite validation and successful sign in of existing user', async(t) => { async function checkSignInBtnDisabled() { - const btnDisabled = await t.expect(await Selector('#login').getAttribute('disabled')).ok(); + const btnDisabled = await t.expect(await Selector('#signin_submit').getAttribute('disabled')).ok(); const btnNotWorks = await t - .click('#login') + .click('#signin_submit') .expect(Selector('title').innerText).eql('Apache Ignite - Management Tool and Configuration Wizard â Apache Ignite Web Console'); return btnDisabled && btnNotWorks; @@ -96,14 +94,14 @@ test('Testing Ignite validation and successful sign in of existing user', async( await insertTestUser(); - // checking signin validation + // Checking signin validation. await t .typeText(AngularJSSelector.byModel('ui.email'), 't...@test.com'); await checkSignInBtnDisabled(); await t .typeText(AngularJSSelector.byModel('ui.password'), 'b') - .click('#login'); + .click('#signin_submit'); await t.expect(Selector('#popover-validation-message').withText('Invalid email or password').exists).ok(); await t @@ -112,7 +110,7 @@ test('Testing Ignite validation and successful sign in of existing user', async( .typeText(AngularJSSelector.byModel('ui.email'), 'testtest.com'); await checkSignInBtnDisabled(); - // checking regular sigin in + // Checking regular sigin in await t .click(AngularJSSelector.byModel('ui.email')) .pressKey('ctrl+a delete') @@ -120,7 +118,7 @@ test('Testing Ignite validation and successful sign in of existing user', async( .click(AngularJSSelector.byModel('ui.password')) .pressKey('ctrl+a delete') .typeText(AngularJSSelector.byModel('ui.password'), 'a') - .click('#login') + .click('#signin_submit') .expect(Selector('title').innerText).eql('Basic Configuration â Apache Ignite Web Console'); }); @@ -128,46 +126,43 @@ test('Testing Ignite validation and successful sign in of existing user', async( test('Forbid Ignite signing up of already existing user', async(t) => { await insertTestUser(); - await t.click(Selector('a').withText('Sign Up')); - await t - .click(Selector('#signup_email')) - .typeText(Selector('#signup_email'), 'a@a') - .typeText(AngularJSSelector.byModel('ui.password'), 'a') + .typeText(AngularJSSelector.byModel('ui_signup.email'), 'a@a') + .typeText(AngularJSSelector.byModel('ui_signup.password'), 'a') .typeText(AngularJSSelector.byModel('ui_exclude.confirm'), 'a') - .typeText(AngularJSSelector.byModel('ui.firstName'), 'John') - .typeText(AngularJSSelector.byModel('ui.lastName'), 'Doe') - .typeText(AngularJSSelector.byModel('ui.company'), 'DevNull LTD') - .click('#country') + .typeText(AngularJSSelector.byModel('ui_signup.firstName'), 'John') + .typeText(AngularJSSelector.byModel('ui_signup.lastName'), 'Doe') + .typeText(AngularJSSelector.byModel('ui_signup.company'), 'DevNull LTD') + .click('#countryInput') .click(Selector('span').withText('Brazil')) - .click('#signup'); + .click('#signup_submit'); await t.expect(Selector('#popover-validation-message').withText('A user with the given username is already registered').exists).ok(); }); test('Test Ignite password reset', async(t) => { - await t.click(Selector('#password-forgot-signin')); + await t.click(Selector('#forgot_show')); - // testing incorrect email + // Testing incorrect email. await t - .typeText('#forgot_email', 'testtest') + .typeText('#forgotEmailInput', 'testtest') .expect(await Selector('button').withText('Send it to me').getAttribute('disabled')).ok(); - // testing handling unknown email password reset + // Testing handling unknown email password reset. await t - .click(Selector('#forgot_email')) + .click(Selector('#forgotEmailInput')) .pressKey('ctrl+a delete') - .typeText(Selector('#forgot_email'), 'nonexist...@mail.com') + .typeText(Selector('#forgotEmailInput'), 'nonexist...@mail.com') .click(Selector('button').withText('Send it to me')); await t.expect(Selector('#popover-validation-message').withText('Account with that email address does not exists!').exists).ok(); - // testing regular password reset + // Testing regular password reset. await t - .click(Selector('#forgot_email')) + .click(Selector('#forgotEmailInput')) .pressKey('ctrl+a delete') - .typeText(Selector('#forgot_email'), 'a@a') + .typeText(Selector('#forgotEmailInput'), 'a@a') .click(Selector('button').withText('Send it to me')); await t.expect(Selector('#popover-validation-message').withText('Account with that email address does not exists!').exists).notOk(); http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/e2e/testcafe/fixtures/user-profile.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/fixtures/user-profile.js b/modules/web-console/e2e/testcafe/fixtures/user-profile.js deleted file mode 100644 index 133b37e..0000000 --- a/modules/web-console/e2e/testcafe/fixtures/user-profile.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const { Selector } = require('testcafe'); -const { removeData, insertTestUser } = require('../envtools'); -const { signIn, signUp } = require('../roles'); - -fixture('Checking user profile') - .page `${process.env.APP_URL || 'http://localhost:9001/'}settings/profile` - .beforeEach(async(t) => { - await t.setNativeDialogHandler(() => true); - await removeData(); - await insertTestUser(); - await signIn(t); - - await t.navigateTo(`${process.env.APP_URL || 'http://localhost:9001/'}settings/profile`); - }) - .after(async() => { - await removeData(); - }); - -test('Testing user data change', async(t) => { - - const newUserData = { - firstName: { - selector: '#profile-firstname', - value: 'Richard' - }, - lastName: { - selector: '#profile-lastname', - value: 'Roe' - }, - email: { - selector: '#profile-email', - value: 'r....@mail.com' - }, - company: { - selector: '#profile-company', - value: 'New Company' - }, - country: { - selector: '#profile-country', - value: 'Israel' - } - }; - - ['firstName', 'lastName', 'email', 'company'].forEach(async(item) => { - await t - .click(newUserData[item].selector) - .pressKey('ctrl+a delete') - .typeText(newUserData[item].selector, newUserData[item].value); - }); - - await t - .click(newUserData.country.selector) - .click(Selector('span').withText(newUserData.country.value)) - .click(Selector('a').withText('Save')); - - await t.navigateTo(`${process.env.APP_URL || 'http://localhost:9001/'}settings/profile`); - - ['firstName', 'lastName', 'email', 'company'].forEach(async(item) => { - await t - .expect(await Selector(newUserData[item].selector).getAttribute('value')) - .eql(newUserData[item].value); - }); - - await t - .expect(Selector(newUserData.country.selector).innerText) - .eql(newUserData.country.value); -}); - -test('Testing secure token change', async(t) => { - await t.click(Selector('a').withAttribute('ng-click', 'toggleToken()')); - - const currentToken = await Selector('#current-security-token').innerText; - - await t - .click(Selector('i').withAttribute('ng-click', 'generateToken()')) - .expect(Selector('p').withText('Are you sure you want to change security token?').exists) - .ok() - .click('#confirm-btn-ok', {timeout: 5000}); - - await t - .expect(await Selector('#current-security-token').innerText) - .notEql(currentToken); -}); - -test('Testing password change', async(t) => { - await t.click(Selector('a').withAttribute('ng-click', 'togglePassword()')); - - await t - .typeText('#profile_password', 'newPass') - .typeText('#profile_confirm', 'newPass') - .click(Selector('a').withText('Save')); - - await t - .expect(Selector('span').withText('Profile saved.').exists) - .ok(); -}); http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/e2e/testcafe/fixtures/user-profile/credentials.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/fixtures/user-profile/credentials.js b/modules/web-console/e2e/testcafe/fixtures/user-profile/credentials.js new file mode 100644 index 0000000..491a100 --- /dev/null +++ b/modules/web-console/e2e/testcafe/fixtures/user-profile/credentials.js @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const { Selector } = require('testcafe'); +const { removeData, insertTestUser } = require('../../envtools'); +const { signIn } = require('../../roles'); + +fixture('Checking user credentials change') + .page `${process.env.APP_URL || 'http://localhost:9001/'}settings/profile` + .beforeEach(async(t) => { + await t.setNativeDialogHandler(() => true); + await removeData(); + await insertTestUser(); + await signIn(t); + + await t.navigateTo(`${process.env.APP_URL || 'http://localhost:9001/'}settings/profile`); + }) + .after(async() => { + await removeData(); + }); + +test('Testing secure token change', async(t) => { + await t.click(Selector('header').withAttribute('ng-click', '$ctrl.toggleToken()')); + + const currentToken = await Selector('#current-security-token').innerText; + + await t + .click(Selector('i').withAttribute('ng-click', '$ctrl.generateToken()')) + .expect(Selector('p').withText('Are you sure you want to change security token?').exists) + .ok() + .click('#confirm-btn-ok', {timeout: 5000}); + + await t + .expect(await Selector('#current-security-token').innerText) + .notEql(currentToken); +}); + +test('Testing password change', async(t) => { + await t.click(Selector('header').withAttribute('ng-click', '$ctrl.togglePassword()')); + + await t + .typeText('#passwordInput', 'newPass') + .typeText('#passwordConfirmInput', 'newPass') + .click(Selector('button').withText('Save Changes')); + + await t + .expect(Selector('span').withText('Profile saved.').exists) + .ok(); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/e2e/testcafe/fixtures/user-profile/profile.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/fixtures/user-profile/profile.js b/modules/web-console/e2e/testcafe/fixtures/user-profile/profile.js new file mode 100644 index 0000000..738d596 --- /dev/null +++ b/modules/web-console/e2e/testcafe/fixtures/user-profile/profile.js @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const { Selector } = require('testcafe'); +const { removeData, insertTestUser } = require('../../envtools'); +const { signIn } = require('../../roles'); + +fixture('Checking user profile') + .page `${process.env.APP_URL || 'http://localhost:9001/'}settings/profile` + .beforeEach(async(t) => { + await t.setNativeDialogHandler(() => true); + await removeData(); + await insertTestUser(); + await signIn(t); + + await t.navigateTo(`${process.env.APP_URL || 'http://localhost:9001/'}settings/profile`); + }) + .after(async() => { + await removeData(); + }); + +test('Testing user data change', async(t) => { + + const newUserData = { + firstName: { + selector: '#firstNameInput', + value: 'Richard' + }, + lastName: { + selector: '#lastNameInput', + value: 'Roe' + }, + email: { + selector: '#emailInput', + value: 'r....@mail.com' + }, + company: { + selector: '#companyInput', + value: 'New Company' + }, + country: { + selector: '#countryInput', + value: 'Israel' + } + }; + + ['firstName', 'lastName', 'email', 'company'].forEach(async(item) => { + await t + .click(newUserData[item].selector) + .pressKey('ctrl+a delete') + .typeText(newUserData[item].selector, newUserData[item].value); + }); + + await t + .click(newUserData.country.selector) + .click(Selector('span').withText(newUserData.country.value)) + .click(Selector('button').withText('Save Changes')); + + await t.navigateTo(`${process.env.APP_URL || 'http://localhost:9001/'}settings/profile`); + + ['firstName', 'lastName', 'email', 'company'].forEach(async(item) => { + await t + .expect(await Selector(newUserData[item].selector).getAttribute('value')) + .eql(newUserData[item].value); + }); + + await t + .expect(Selector(newUserData.country.selector).innerText) + .eql(newUserData.country.value); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/e2e/testcafe/roles.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/roles.js b/modules/web-console/e2e/testcafe/roles.js index bfa9f13..568a520 100644 --- a/modules/web-console/e2e/testcafe/roles.js +++ b/modules/web-console/e2e/testcafe/roles.js @@ -20,21 +20,18 @@ const { Selector } = require('testcafe'); const { AngularJSSelector } = require('testcafe-angular-selectors'); const igniteSignUp = async(t) => { - await t.navigateTo(`${process.env.APP_URL || 'http://localhost:9001/'}`); - - await t.click(Selector('a').withText('Sign Up')); + await t.navigateTo(`${process.env.APP_URL || 'http://localhost:9001/'}signin`); await t - .click(Selector('#signup_email')) - .typeText(Selector('#signup_email'), 'a@a') - .typeText(AngularJSSelector.byModel('ui.password'), 'a') + .typeText(AngularJSSelector.byModel('ui_signup.email'), 'a@a') + .typeText(AngularJSSelector.byModel('ui_signup.password'), 'a') .typeText(AngularJSSelector.byModel('ui_exclude.confirm'), 'a') - .typeText(AngularJSSelector.byModel('ui.firstName'), 'John') - .typeText(AngularJSSelector.byModel('ui.lastName'), 'Doe') - .typeText(AngularJSSelector.byModel('ui.company'), 'DevNull LTD') - .click('#country') + .typeText(AngularJSSelector.byModel('ui_signup.firstName'), 'John') + .typeText(AngularJSSelector.byModel('ui_signup.lastName'), 'Doe') + .typeText(AngularJSSelector.byModel('ui_signup.company'), 'DevNull LTD') + .click('#countryInput') .click(Selector('span').withText('Brazil')) - .click('#signup'); + .click('#signup_submit'); // close modal window await t.click('.modal-header button.close'); @@ -42,12 +39,12 @@ const igniteSignUp = async(t) => { const igniteSignIn = async(t) => { - await t.navigateTo(`${process.env.APP_URL || 'http://localhost:9001/'}`); + await t.navigateTo(`${process.env.APP_URL || 'http://localhost:9001/'}signin`); await t .typeText(AngularJSSelector.byModel('ui.email'), 'a@a') .typeText(AngularJSSelector.byModel('ui.password'), 'a') - .click('#login'); + .click('#signin_submit'); // close modal window await t.click('.modal-header button.close'); http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/e2e/testcafe/testcafe.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/testcafe.js b/modules/web-console/e2e/testcafe/testcafe.js index 597d29a..66610e8 100644 --- a/modules/web-console/e2e/testcafe/testcafe.js +++ b/modules/web-console/e2e/testcafe/testcafe.js @@ -33,11 +33,11 @@ const BROWSERS = ['chromium:headless --no-sandbox']; // For example: ['chrome', let testcafe = null; const resolveFixturesPaths = () => { - let fixturesPaths = glob.sync('./fixtures/*.js'); + let fixturesPaths = glob.sync(' ./fixtures/**/*.js'); if (process.env.IGNITE_MODULES) { const igniteModulesTestcafe = path.join(process.env.IGNITE_MODULES, 'e2e/testcafe'); - const additionalFixturesPaths = glob.sync(path.join(igniteModulesTestcafe, 'fixtures', '*.js')); + const additionalFixturesPaths = glob.sync(path.join(igniteModulesTestcafe, 'fixtures', '**/*.js')); const relativePaths = new Set(additionalFixturesPaths.map((fixturePath) => path.relative(igniteModulesTestcafe, fixturePath))); fixturesPaths = fixturesPaths.filter((fixturePath) => !relativePaths.has(path.relative(process.cwd(), fixturePath))).concat(additionalFixturesPaths); http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/e2e/testenv/Dockerfile ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testenv/Dockerfile b/modules/web-console/e2e/testenv/Dockerfile index 5a8f24b..0db2f29 100644 --- a/modules/web-console/e2e/testenv/Dockerfile +++ b/modules/web-console/e2e/testenv/Dockerfile @@ -49,6 +49,8 @@ RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux- tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 && \ rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt +ENV NPM_CONFIG_LOGLEVEL warn + # Install global node packages. RUN npm install -g pm2 http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/app.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/app.js b/modules/web-console/frontend/app/app.js index c19018c..6524450 100644 --- a/modules/web-console/frontend/app/app.js +++ b/modules/web-console/frontend/app/app.js @@ -25,9 +25,7 @@ import './modules/agent/agent.module'; import './modules/nodes/nodes.module'; import './modules/demo/Demo.module'; -import './modules/states/signin.state'; import './modules/states/logout.state'; -import './modules/states/password.state'; import './modules/states/configuration.state'; import './modules/states/admin.state'; import './modules/states/errors.state'; @@ -133,8 +131,12 @@ import uiGridFilters from './components/ui-grid-filters'; import listEditable from './components/list-editable'; import clusterSelector from './components/cluster-selector'; import connectedClusters from './components/connected-clusters'; +import pageSignIn from './components/page-signin'; +import pageLanding from './components/page-landing'; import pageProfile from './components/page-profile'; +import pagePasswordChanged from './components/page-password-changed'; +import pagePasswordReset from './components/page-password-reset'; import igniteServices from './services'; @@ -148,6 +150,7 @@ angular.module('ignite-console', [ // Optional AngularJS modules. 'ngAnimate', 'ngSanitize', + 'ngMessages', // Third party libs. 'btford.socket-io', 'dndLists', @@ -166,6 +169,7 @@ angular.module('ignite-console', [ 'ui.grid.selection', 'ui.router', 'ui.router.state.events', + 'ui.carousel', // Base modules. 'ignite-console.core', 'ignite-console.ace', @@ -178,9 +182,7 @@ angular.module('ignite-console', [ 'ignite-console.nodes', 'ignite-console.demo', // States. - 'ignite-console.states.login', 'ignite-console.states.logout', - 'ignite-console.states.password', 'ignite-console.states.configuration', 'ignite-console.states.admin', 'ignite-console.states.errors', @@ -218,6 +220,10 @@ angular.module('ignite-console', [ connectedClusters.name, igniteListOfRegisteredUsers.name, pageProfile.name, + pageSignIn.name, + pageLanding.name, + pagePasswordChanged.name, + pagePasswordReset.name, // Ignite modules. IgniteModules.name ]) http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-configure/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-configure/index.js b/modules/web-console/frontend/app/components/page-configure/index.js index 172609f..8c4e3c2 100644 --- a/modules/web-console/frontend/app/components/page-configure/index.js +++ b/modules/web-console/frontend/app/components/page-configure/index.js @@ -23,6 +23,9 @@ import ConfigurationDownload from './services/ConfigurationDownload'; export default angular .module('ignite-console.page-configure', []) + .config(['DefaultStateProvider', (DefaultState) => { + DefaultState.setRedirectTo(() => 'base.configuration.tabs'); + }]) .component('pageConfigure', component) .service('PageConfigure', PageConfigure) .service('ConfigureState', ConfigureState) http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-landing/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-landing/index.js b/modules/web-console/frontend/app/components/page-landing/index.js new file mode 100644 index 0000000..037f3d4 --- /dev/null +++ b/modules/web-console/frontend/app/components/page-landing/index.js @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import angular from 'angular'; + +import template from './template.pug'; +import './style.scss'; + +export default angular + .module('ignite-console.landing', [ + 'ui.router', + 'ignite-console.user' + ]) + .component('pageLanding', { + template, + controller: class LandingController { + static images = [ + '/images/page-landing-carousel-1.png', + '/images/page-landing-carousel-2.png', + '/images/page-landing-carousel-3.png' + ]; + + $onInit() { + this.images = LandingController.images; + } + } + }) + .config(['$stateProvider', function($stateProvider) { + // set up the states + $stateProvider + .state('landing', { + url: '/', + template: '<page-landing></page-landing>', + redirectTo: (trans) => { + return trans.injector().get('User').read() + .then(() => { + try { + const {name, params} = JSON.parse(localStorage.getItem('lastStateChangeSuccess')); + + const restored = trans.router.stateService.target(name, params); + + return restored.valid() ? restored : 'base.configuration.tabs'; + } catch (ignored) { + return 'base.configuration.tabs'; + } + }) + .catch(() => true); + }, + unsaved: true + }); + }]); http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-landing/style.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-landing/style.scss b/modules/web-console/frontend/app/components/page-landing/style.scss new file mode 100644 index 0000000..a92206b --- /dev/null +++ b/modules/web-console/frontend/app/components/page-landing/style.scss @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@mixin custom_btn { + font-weight: 500; + padding: 10px 25px !important; +} + +#signin_show { + @include custom_btn; +} + +page-landing { + font-family: Roboto; + + .btn-custom { + @include custom_btn; + } + + section.intro-container-wrapper { + padding: 40px 0; + + background-color: #f9f9f9; + border-bottom: 1px solid #aaaaaa; + + .intro-content { + padding-right: 70px; + } + + h1 { + margin-top: 45px; + font-size: 48px; + line-height: 55px; + font-weight: 300; + } + + h2 { + margin-bottom: 20px; + font-size: 24px; + font-style: italic; + font-weight: 300; + } + + p { + font-size: 16px; + font-weight: 300; + color: #777777; + } + + .btn-custom { + margin-top: 20px; + padding: 10px 40px !important; + border-color: #f9f9f9 !important; + } + } + + section.features-container-wrapper { + padding: 25px 0 60px; + background-color: #ffffff; + + .section-title { + font-size: 38px; + font-weight: 300; + color: #444444; + margin: 30px 0 60px; + } + + .feature { + margin: 30px 0; + + h3 { + font-size: 24px; + font-weight: normal; + color: #000000; + line-height: 28px; + margin-bottom: 10px; + } + + p { + color: #666666; + font-size: 16px; + } + + i.fa { + font-size: 48px; + color: #bbbbbb; + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-landing/template.pug ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-landing/template.pug b/modules/web-console/frontend/app/components/page-landing/template.pug new file mode 100644 index 0000000..a1ce4f7 --- /dev/null +++ b/modules/web-console/frontend/app/components/page-landing/template.pug @@ -0,0 +1,66 @@ +//- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +web-console-header + web-console-header-left + ignite-header-title + web-console-header-right + a#signin_show.btn-ignite.btn-ignite--primary(ui-sref='signin') Sign In + +section.intro-container-wrapper + .container + .col-lg-6.col-md-6.col-sm-6.col-xs-12.intro-content + h1 Web Console + h2 An Interactive Configuration Wizard and Management Tool for Apache⢠Ignite® + p It provides an interactive configuration wizard which helps you create and download configuration files and code snippets for your Apache Ignite projects. Additionally, the tool allows you to automatically load SQL metadata from any RDBMS, run SQL queries on your in-memory cache as well as view execution plans, in-memory schema, and streaming charts. + a#signup_show.btn.btn-lg.btn-primary.btn-custom(ui-sref='signin') Try Now + .col-lg-6.col-md-6.col-sm-6.col-xs-12 + ui-carousel(slides='$ctrl.images' autoplay='true' slides-to-show='1' arrows='false') + carousel-item + img(ng-src='{{item}}') +section.features-container-wrapper + .container.features-container + .section-title Web Console allows you to: + .row + .col-lg-6.col-md-6.col-sm-6.col-xs-12.feature + .col-lg-2.col-md-2.col-sm-2.col-xs-2 + i.fa.fa-sitemap + .col-lg-9.col-md-9.col-sm-9.col-xs-9 + h3 Configure Apache Ignite Clusters and Caches + p The Web Console configuration wizard takes you through a step-by-step process to define all of your required configuration parameters. The system then generates a ready-to-use project with all of the required config files for you. + .col-lg-6.col-md-6.col-sm-6.col-xs-12.feature + .col-lg-2.col-md-2.col-sm-2.col-xs-2 + i.fa.fa-search + .col-lg-9.col-md-9.col-sm-9.col-xs-9 + h3 Run Free Form SQL Queries on #[br] Apache Ignite Caches + p By connecting The Web Console to your Apache Ignite cluster, you can execute SQL queries on your in-memory cache. You can also view the execution plan, in-memory schema, and streaming charts for your cluster. + .row + .col-lg-6.col-md-6.col-sm-6.col-xs-12.feature + .col-lg-2.col-md-2.col-sm-2.col-xs-2 + i.fa.fa-database + .col-lg-9.col-md-9.col-sm-9.col-xs-9 + h3 Import Database Schemas from #[br] Virtually Any RDBMS + p To speed the creation of your configuration files, The Web Console allows you to automatically import the database schema from any current RDBMS. and Apache Ignite support virtually any RDBMS including Oracle, SAP, MySQL, PostgreSQL and many more. + .col-lg-6.col-md-6.col-sm-6.col-xs-12.feature + .col-lg-2.col-md-2.col-sm-2.col-xs-2 + i.fa.fa-gears + .col-lg-9.col-md-9.col-sm-9.col-xs-9 + h3 Manage The Web Console users + p With The Web Console you can have accounts with different roles. + .align-center.text-center + a.btn.btn-lg.btn-primary.btn-custom(ui-sref='signin') Get Started + +web-console-footer http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-password-changed/controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-password-changed/controller.js b/modules/web-console/frontend/app/components/page-password-changed/controller.js new file mode 100644 index 0000000..5b8301d --- /dev/null +++ b/modules/web-console/frontend/app/components/page-password-changed/controller.js @@ -0,0 +1,18 @@ +/* + * Copyright (C) GridGain Systems. All Rights Reserved. + * _________ _____ __________________ _____ + * __ ____/___________(_)______ /__ ____/______ ____(_)_______ + * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \ + * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / / + * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/ + */ + +export default class { + static $inject = ['$state', '$timeout']; + + constructor($state, $timeout) { + $timeout(() => { + $state.go('signin'); + }, 10000); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-password-changed/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-password-changed/index.js b/modules/web-console/frontend/app/components/page-password-changed/index.js new file mode 100644 index 0000000..4d624a7 --- /dev/null +++ b/modules/web-console/frontend/app/components/page-password-changed/index.js @@ -0,0 +1,33 @@ +/* + * Copyright (C) GridGain Systems. All Rights Reserved. + * _________ _____ __________________ _____ + * __ ____/___________(_)______ /__ ____/______ ____(_)_______ + * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \ + * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / / + * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/ + */ + +import angular from 'angular'; + +import template from './template.pug'; +import controller from './controller'; + +import './style.scss'; + +export default angular + .module('ignite-console.page-password-changed', [ + ]) + .component('pagePasswordChanged', { + template, + controller + }) + .config(['$stateProvider', ($stateProvider) => { + $stateProvider.state('password.send', { + url: '/changed', + component: 'pagePasswordChanged', + tfMetaTags: { + title: 'Password send' + }, + unsaved: true + }); + }]); http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-password-changed/style.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-password-changed/style.scss b/modules/web-console/frontend/app/components/page-password-changed/style.scss new file mode 100644 index 0000000..944fc47 --- /dev/null +++ b/modules/web-console/frontend/app/components/page-password-changed/style.scss @@ -0,0 +1,34 @@ +/* + * Copyright (C) GridGain Systems. All Rights Reserved. + * _________ _____ __________________ _____ + * __ ____/___________(_)______ /__ ____/______ ____(_)_______ + * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \ + * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / / + * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/ + */ + +page-password-changed { + display: flex; + flex: 1 0 auto; + flex-direction: column; + + min-height: 100%; + + font-family: Roboto; + + .body-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + + h2 { + margin-bottom: 30px; + } + + p { + font-size: 16px; + text-align: center; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-password-changed/template.pug ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-password-changed/template.pug b/modules/web-console/frontend/app/components/page-password-changed/template.pug new file mode 100644 index 0000000..33f20d4 --- /dev/null +++ b/modules/web-console/frontend/app/components/page-password-changed/template.pug @@ -0,0 +1,14 @@ +//- + Copyright (C) GridGain Systems. All Rights Reserved. + _________ _____ __________________ _____ + __ ____/___________(_)______ /__ ____/______ ____(_)_______ + _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \ + / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / / + \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/ + +.container.body-container + h2 Ready! + + p + | Further instructions for password reset have been sent to your e-mail address.#[br] + | You'll be redirected back automatically in a few seconds. If not, please #[a(ui-sref='signin') click here]. http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-password-reset/controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-password-reset/controller.js b/modules/web-console/frontend/app/components/page-password-reset/controller.js new file mode 100644 index 0000000..6b40228 --- /dev/null +++ b/modules/web-console/frontend/app/components/page-password-reset/controller.js @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default class { + static $inject = ['$modal', '$http', '$state', 'IgniteMessages']; + + /** + * @param {mgcrea.ngStrap.modal.IModalService} $modal + * @param $http + * @param {StateProvider} $state + * @param Messages + */ + constructor($modal, $http, $state, Messages) { + this.$http = $http; + this.$state = $state; + this.Messages = Messages; + } + + $onInit() { + this.$http.post('/api/v1/password/validate/token', {token: this.$state.params.token}) + .then(({data}) => this.ui = data); + } + + // Try to reset user password for provided token. + resetPassword() { + this.$http.post('/api/v1/password/reset', {token: this.ui.token, password: this.ui.password}) + .then(() => { + this.$state.go('signin'); + + this.Messages.showInfo('Password successfully changed'); + }) + .catch(({data, state}) => { + if (state === 503) + this.$state.go('signin'); + + this.Messages.showError(data); + }); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-password-reset/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-password-reset/index.js b/modules/web-console/frontend/app/components/page-password-reset/index.js new file mode 100644 index 0000000..e1042a6 --- /dev/null +++ b/modules/web-console/frontend/app/components/page-password-reset/index.js @@ -0,0 +1,57 @@ +/* +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import angular from 'angular'; + +import _ from 'lodash'; + +import template from './template.pug'; +import controller from './controller'; + +import './style.scss'; + +export default angular + .module('ignite-console.page-password-reset', [ + ]) + .component('pagePasswordReset', { + template, + controller + }) + .config(['$stateProvider', ($stateProvider) => { + // set up the states + $stateProvider + .state('password', { + url: '/password', + abstract: true, + template: '<ui-view></ui-view>' + }) + .state('password.reset', { + url: '/reset?{token}', + component: 'pagePasswordReset', + redirectTo: (trans) => { + if (_.isEmpty(trans.params('to').token)) + return 'signin'; + + return true; + }, + unsaved: true, + tfMetaTags: { + title: 'Reset password' + } + }); + }]); http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-password-reset/style.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-password-reset/style.scss b/modules/web-console/frontend/app/components/page-password-reset/style.scss new file mode 100644 index 0000000..75f758e --- /dev/null +++ b/modules/web-console/frontend/app/components/page-password-reset/style.scss @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +page-password-reset { + display: flex; + flex: 1 0 auto; + flex-direction: column; + + footer { + display: flex; + justify-content: flex-end; + } + + .btn-ignite + .btn-ignite { + margin-left: 10px; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-password-reset/template.pug ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-password-reset/template.pug b/modules/web-console/frontend/app/components/page-password-reset/template.pug new file mode 100644 index 0000000..1acfab8 --- /dev/null +++ b/modules/web-console/frontend/app/components/page-password-reset/template.pug @@ -0,0 +1,80 @@ +//- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +include /app/helpers/jade/mixins + +web-console-header + web-console-header-left + ignite-header-title + +.container.body-container + .row + .main-content(ng-if='error') + .text-center + p {{::$ctrl.ui.error}} + div(ng-if='$ctrl.ui.token && !$ctrl.ui.error') + header.header-with-selector + div + h1 Reset Password + + -var form = '$ctrl.form' + form.theme--ignite(name='$ctrl.form' ng-init='reset_info.token = token') + .row + .col-50 + +form-field__email({ + label: 'E-mail:', + model: '$ctrl.ui.email', + disabled: true + }) + + .row + .col-50 + +form-field__password({ + label: 'New password:', + model: '$ctrl.ui.password', + name: '"password"', + required: true, + placeholder: 'New password' + })( + ignite-auto-focus + ignite-on-enter-focus-move='passwordConfirmInput' + ) + + .row + .col-50 + +form-field__password({ + label: 'Confirm password:', + model: 'confirm', + name: '"passwordConfirm"', + required: true, + placeholder: 'Confirm new password' + })( + ignite-on-enter-focus-move='resetForm.$valid && resetPassword(user_info)' + ignite-match='$ctrl.ui.password' + ) + + hr + + footer + a.btn-ignite.btn-ignite--link-success(type='button' ui-sref='default-state') Cancel + button.btn-ignite.btn-ignite--success( + ng-disabled='$ctrl.form.$invalid' + ng-click='$ctrl.resetPassword()' + ) + svg.icon-left(ignite-icon='checkmark') + | Save Changes + +web-console-footer http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-profile/controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-profile/controller.js b/modules/web-console/frontend/app/components/page-profile/controller.js index b60340b..3fc7318 100644 --- a/modules/web-console/frontend/app/components/page-profile/controller.js +++ b/modules/web-console/frontend/app/components/page-profile/controller.js @@ -25,14 +25,12 @@ export default class PageProfileController { } $onInit() { - const self = this; - - self.ui = {}; + this.ui = {}; this.User.read() - .then((user) => self.ui.user = angular.copy(user)); + .then((user) => this.ui.user = angular.copy(user)); - self.ui.countries = this.Countries.getAll(); + this.ui.countries = this.Countries.getAll(); } toggleToken() { http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-profile/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-profile/index.js b/modules/web-console/frontend/app/components/page-profile/index.js index d9921b3..faa3c21 100644 --- a/modules/web-console/frontend/app/components/page-profile/index.js +++ b/modules/web-console/frontend/app/components/page-profile/index.js @@ -16,7 +16,11 @@ */ import angular from 'angular'; + import component from './component'; +import template from 'views/base2.pug'; + +import './style.scss'; export default angular .module('ignite-console.page-profile', [ @@ -26,7 +30,14 @@ export default angular // set up the states $stateProvider.state('base.settings.profile', { url: '/profile', - component: 'pageProfile', + views: { + '@': { + template + }, + '@base.settings.profile': { + component: 'pageProfile' + } + }, permission: 'profile', tfMetaTags: { title: 'User profile' http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-profile/style.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-profile/style.scss b/modules/web-console/frontend/app/components/page-profile/style.scss new file mode 100644 index 0000000..a96914e --- /dev/null +++ b/modules/web-console/frontend/app/components/page-profile/style.scss @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +page-profile { + .panel--ignite { + width: 100%; + } + + footer { + display: flex; + justify-content: flex-end; + } + + .btn-ignite + .btn-ignite { + margin-left: 10px; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-profile/template.pug ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-profile/template.pug b/modules/web-console/frontend/app/components/page-profile/template.pug index 5331670..48aa151 100644 --- a/modules/web-console/frontend/app/components/page-profile/template.pug +++ b/modules/web-console/frontend/app/components/page-profile/template.pug @@ -14,70 +14,143 @@ See the License for the specific language governing permissions and limitations under the License. -mixin lbl(txt) - label.col-sm-2.required.labelFormField #{txt} +include /app/helpers/jade/mixins -mixin lbl-not-required(txt) - label.col-sm-2.labelFormField #{txt} - -.row - .docs-content - .docs-header +div + header.header-with-selector + div h1 User profile - hr - .docs-body - form.form-horizontal(name='$ctrl.form' novalidate) - .col-sm-10(style='padding: 0') - .details-row - +lbl('First name:') - .col-xs-5.col-sm-4 - input#profile-firstname.form-control(ignite-on-enter-focus-move='profile-lastname' type='text' ng-model='$ctrl.ui.user.firstName' placeholder='Input first name' required ignite-auto-focus) - .details-row - +lbl('Last name:') - .col-xs-5.col-sm-4 - input#profile-lastname.form-control(ignite-on-enter-focus-move='profile-email' type='text' ng-model='$ctrl.ui.user.lastName' placeholder='Input last name' required) - .details-row - +lbl('Email:') - .col-xs-5.col-sm-4 - input#profile-email.form-control(ignite-on-enter-focus-move='profile-company' type='email' ng-model='$ctrl.ui.user.email' placeholder='Input email' required) - .details-row - +lbl-not-required('Phone:') - .col-xs-5.col-sm-4 - input#profile-phone.form-control(ignite-on-enter-focus-move='profile-company' type='tel' ng-model='$ctrl.ui.user.phone' placeholder='Input phone') - .details-row - +lbl('Company:') - .col-xs-5.col-sm-4 - input#profile-company.form-control(ignite-on-enter-focus-move='profile-country' type='text' ng-model='$ctrl.ui.user.company' placeholder='Input company name' required) - .details-row - +lbl('Country:') - .col-xs-5.col-sm-4 - button#profile-country.select-toggle.form-control(bs-select bs-options='item.name as item.name for item in $ctrl.ui.countries' type='text' ng-model='$ctrl.ui.user.country' placeholder='Choose your country' ng-required='true') - .details-row#security-token-section - .advanced-options - i.fa( - ng-click='$ctrl.toggleToken()' - ng-class='$ctrl.ui.expandedToken ? "fa-chevron-circle-down" : "fa-chevron-circle-right"') - a(ng-click='$ctrl.toggleToken()') {{$ctrl.ui.expandedToken ? 'Cancel security token changing...' : 'Show security token...'}} - div(ng-if='$ctrl.ui.expandedToken') - +lbl('Security token:') - label#current-security-token {{$ctrl.ui.user.token || 'No security token. Regenerate please.'}} - i.tipLabel.fa.fa-refresh(ng-click='$ctrl.generateToken()' bs-tooltip='' data-title='Generate random security token') - i.tipLabel.fa.fa-clipboard(ignite-copy-to-clipboard='{{$ctrl.ui.user.token}}' bs-tooltip='' data-title='Copy security token to clipboard') - i.tipLabel.icon-help(ng-if=lines bs-tooltip='' data-title='The security token is used for authorization of web agent') - .details-row#change-password-section - .advanced-options - i.fa( - ng-click='$ctrl.togglePassword()' - ng-class='$ctrl.ui.expandedPassword ? "fa-chevron-circle-down" : "fa-chevron-circle-right"') - a(ng-click='$ctrl.togglePassword()') {{$ctrl.ui.expandedPassword ? 'Cancel password changing...' : 'Change password...'}} - div(ng-if='$ctrl.ui.expandedPassword') - .details-row - +lbl('New password:') - .col-xs-5.col-sm-4 - input#profile_password.form-control(ignite-on-enter-focus-move='profile_confirm' type='password' ng-model='$ctrl.ui.user.password' placeholder='New password' required) - .details-row - +lbl('Confirm:') - .col-xs-5.col-sm-4 - input#profile_confirm.form-control(type='password' ng-model='user.confirm' ignite-match='$ctrl.ui.user.password' placeholder='Confirm new password' required) - .col-xs-12.col-sm-12.details-row - button.btn.btn-primary(ng-click='$ctrl.saveUser()' ng-disabled='$ctrl.form.$invalid') Save + + -var form = '$ctrl.form' + form.theme--ignite(name='$ctrl.form' novalidate) + .row + .col-25 + +form-field__text({ + label: 'First name:', + model: '$ctrl.ui.user.firstName', + name: '"firstName"', + required: true, + placeholder: 'Input first name' + })( + ignite-auto-focus + ignite-on-enter-focus-move='lastNameInput' + ) + .col-25 + +form-field__text({ + label: 'Last name:', + model: '$ctrl.ui.user.lastName', + name: '"lastName"', + required: true, + placeholder: 'Input last name' + })( + ignite-on-enter-focus-move='emailInput' + ) + .row + .col-50 + +form-field__email({ + label: 'Email:', + model: '$ctrl.ui.user.email', + name: '"email"', + required: true, + placeholder: 'Input email' + })( + ignite-on-enter-focus-move='phoneInput' + ) + .row + .col-25 + +form-field__phone({ + label: 'Phone:', + model: '$ctrl.ui.user.phone', + name: '"phone"', + optional: true, + placeholder: 'Input phone (ex.: +15417543010)' + })( + ignite-on-enter-focus-move='companyInput' + ) + .col-25 + +form-field__dropdown({ + label: 'Country:', + model: '$ctrl.ui.user.country', + name: '"country"', + required: true, + placeholder: 'Choose your country', + options: '$ctrl.ui.countries' + }) + .row + .col-50 + +form-field__text({ + label: 'Company:', + model: '$ctrl.ui.user.company', + name: '"company"', + required: true, + placeholder: 'Input company name' + })( + ignite-on-enter-focus-move='countryInput' + ) + + .row#security-token-section + .col-50 + .panel--ignite.panel--collapse(ng-class='{ in: !$ctrl.ui.expandedToken }') + header(ng-click='$ctrl.toggleToken()') + svg(ignite-icon='expand') + svg(ignite-icon='collapse') + + | {{$ctrl.ui.expandedToken ? 'Cancel security token changing...' : 'Show security token...'}} + hr + section(ng-if='$ctrl.ui.expandedToken') + .row + .col-25 + label.required Security token: + .col-75 + label#current-security-token {{$ctrl.ui.user.token || 'No security token. Regenerate please.'}} + label + i.tipLabel.fa.fa-refresh(ng-click='$ctrl.generateToken()' bs-tooltip='' data-title='Generate random security token') + i.tipLabel.fa.fa-clipboard(ignite-copy-to-clipboard='{{$ctrl.ui.user.token}}' bs-tooltip='' data-title='Copy security token to clipboard') + i.tipLabel.icon-help(ng-if=lines bs-tooltip='' data-title='The security token is used for authorization of web agent') + + .row + .col-50 + .panel--ignite.panel--collapse(ng-class='{ in: !$ctrl.ui.expandedPassword }') + header(ng-click='$ctrl.togglePassword()') + svg(ignite-icon='expand') + svg(ignite-icon='collapse') + + | {{ $ctrl.ui.expandedPassword ? 'Cancel password changing...' : 'Change password...' }} + hr + section(ng-if='$ctrl.ui.expandedPassword') + .row + .col-100 + +form-field__password({ + label: 'New password:', + model: '$ctrl.ui.user.password', + name: '"password"', + required: true, + placeholder: 'New password' + })( + ignite-auto-focus + ignite-on-enter-focus-move='passwordConfirmInput' + ) + + .row + .col-100 + +form-field__password({ + label: 'Confirm password:', + model: 'user.confirm', + name: '"passwordConfirm"', + required: true, + placeholder: 'Confirm new password' + })( + ignite-on-enter-focus-move='passwordConfirmInput' + ignite-match='$ctrl.ui.user.password' + ) + + hr + + footer + a.btn-ignite.btn-ignite--link-success(type='button' ui-sref='default-state') Cancel + button.btn-ignite.btn-ignite--success( + ng-click='$ctrl.saveUser()' + ng-disabled='$ctrl.form.$invalid' + ) + svg.icon-left(ignite-icon='checkmark') + | Save Changes http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-signin/controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-signin/controller.js b/modules/web-console/frontend/app/components/page-signin/controller.js new file mode 100644 index 0000000..585bb7a --- /dev/null +++ b/modules/web-console/frontend/app/components/page-signin/controller.js @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Sign in controller. +export default class { + static $inject = ['$scope', '$uiRouterGlobals', 'IgniteFocus', 'IgniteCountries', 'Auth']; + + constructor($scope, $uiRouterGlobals, Focus, Countries, Auth) { + this.auth = Auth.auth; + this.forgotPassword = Auth.forgotPassword; + this.action = 'signin'; + this.countries = Countries.getAll(); + + Focus.move('user_email'); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-signin/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-signin/index.js b/modules/web-console/frontend/app/components/page-signin/index.js new file mode 100644 index 0000000..6be374f --- /dev/null +++ b/modules/web-console/frontend/app/components/page-signin/index.js @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import angular from 'angular'; + +import template from './template.pug'; +import controller from './controller'; +import './style.scss'; + +export default angular + .module('ignite-console.sign-in', [ + 'ui.router', + 'ignite-console.user' + ]) + .component('pageSignIn', { + controller, + template + }) + .config(['$stateProvider', function($stateProvider) { + // set up the states + $stateProvider + .state('signin', { + url: '/signin', + template: '<page-sign-in></page-sign-in>', + redirectTo: (trans) => { + return trans.injector().get('User').read() + .then(() => { + try { + const {name, params} = JSON.parse(localStorage.getItem('lastStateChangeSuccess')); + + const restored = trans.router.stateService.target(name, params); + + return restored.valid() ? restored : 'default-state'; + } catch (ignored) { + return 'default-state'; + } + }) + .catch(() => true); + }, + unsaved: true + }); + }]); http://git-wip-us.apache.org/repos/asf/ignite/blob/19256745/modules/web-console/frontend/app/components/page-signin/style.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-signin/style.scss b/modules/web-console/frontend/app/components/page-signin/style.scss new file mode 100644 index 0000000..7e13ffe --- /dev/null +++ b/modules/web-console/frontend/app/components/page-signin/style.scss @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +page-sign-in { + display: flex; + flex-direction: column; + flex: 1 0 auto; + + font-family: Roboto; + + h3 { + font-size: 38px; + font-weight: 300; + margin: 30px 0 60px; + } + + section { + flex-grow: 1; + padding: 25px 0 60px; + + background-color: #ffffff; + color: #444444; + } +} \ No newline at end of file