diff --git a/.circleci/config.yml b/.circleci/config.yml index 18ceffcd..40ff9c96 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,100 +1,105 @@ version: 2 -jobs: - "build-dev": +defaults: &defaults docker: - - image: node:5.10.1 - steps: - - run: - name: Installation of build dependencies. + - image: node:5.10.1 +install_dependency: &install_dependency + name: Installation of build and deployment dependencies. + command: | + set +e + apt-get update -y + apt-get install g++-4.8 -y + apt install awscli -y + apt install jq -y + chmod 777 /etc/mime.types + sed -i 's/^application\/x-font-woff.*/application\/font-woff\t\t\t\twoff/' /etc/mime.types + sed -i 's/^image\/vnd.microsoft.icon.*/image\/vnd.microsoft.icon/' /etc/mime.types + sed -i 's/^image\/x-icon.*/image\/x-icon\t\t\t\tico/' /etc/mime.types +install_deploysuite: &install_deploysuite + name: Installation of install_deploysuite. + command: | + git clone --branch v1.4 https://github.com/topcoder-platform/tc-deploy-scripts ../buildscript + cp ./../buildscript/master_deploy.sh . + cp ./../buildscript/buildenv.sh . + cp ./../buildscript/awsconfiguration.sh . +restore_cache_settings_for_build: &restore_cache_settings_for_build + key: ac-node-modules-{{ checksum "package.json" }} +save_cache_settings: &save_cache_settings + key: ac-node-modules-{{ checksum "package.json" }} + paths: + - node_modules +running_npm_build: &running_npm_build + name: Running Npm Build command: | - set +e - apt-get update -y - apt-get install g++-4.8 -y - apt install awscli -y - chmod 777 /etc/mime.types - sed -i 's/^application\/x-font-woff.*/application\/font-woff\t\t\t\twoff/' /etc/mime.types - sed -i 's/^image\/vnd.microsoft.icon.*/image\/vnd.microsoft.icon/' /etc/mime.types - sed -i 's/^image\/x-icon.*/image\/x-icon\t\t\t\tico/' /etc/mime.types + source buildenvvar + npm rebuild node-sass + npm run build + npm run build-connector + npm test + +builddeploy_steps: &builddeploy_steps - checkout - - restore_cache: - key: ac-node-modules-{{ checksum "package.json" }} + - setup_remote_docker + - run: *install_dependency + - run: *install_deploysuite + - restore_cache: *restore_cache_settings_for_build - run: npm install - - save_cache: - key: ac-node-modules-{{ checksum "package.json" }} - paths: - - node_modules - - run: npm rebuild node-sass - - run: npm run build - - run: npm run build-connector - - run: npm test - - run: ./deploy.sh DEV - "build-qa": - docker: - - image: node:5.10.1 - steps: - - run: - name: Installation of build dependencies. + - save_cache: *save_cache_settings + - run: + name: "configuring environment" command: | - apt-get update -y - apt-get install g++-4.8 -y - apt install awscli -y - chmod 777 /etc/mime.types - sed -i 's/^application\/x-font-woff.*/application\/font-woff\t\t\t\twoff/' /etc/mime.types - sed -i 's/^image\/vnd.microsoft.icon.*/image\/vnd.microsoft.icon/' /etc/mime.types - sed -i 's/^image\/x-icon.*/image\/x-icon\t\t\t\tico/' /etc/mime.types - - checkout - - restore_cache: - key: ac-node-modules-{{ checksum "package.json" }} - - run: npm install - - save_cache: - key: ac-node-modules-{{ checksum "package.json" }} - paths: - - node_modules - - run: npm run build - - run: npm run build-connector - - run: npm test - - run: ./deploy.sh QA - "build-prod": - docker: - - image: node:5.10.1 - steps: - - run: - name: Installation of build dependencies. + ./awsconfiguration.sh $DEPLOY_ENV + ./buildenv.sh -e $DEPLOY_ENV -b ${LOGICAL_ENV}-${APPNAME}-buildvar + - run: *running_npm_build + - deploy: + name: Running MasterScript. command: | - set +e - apt-get update -y - apt-get install g++-4.8 -y - apt install awscli -y - chmod 777 /etc/mime.types - sed -i 's/^application\/x-font-woff.*/application\/font-woff\t\t\t\twoff/' /etc/mime.types - sed -i 's/^image\/vnd.microsoft.icon.*/image\/vnd.microsoft.icon/' /etc/mime.types - sed -i 's/^image\/x-icon.*/image\/x-icon\t\t\t\tico/' /etc/mime.types - - checkout - - restore_cache: - key: ac-node-modules-{{ checksum "package.json" }} - - run: npm install - - save_cache: - key: ac-node-modules-{{ checksum "package.json" }} - paths: - - node_modules - - run: npm rebuild node-sass - - run: npm run build - - run: npm run build-connector - - run: npm test - - run: ./deploy.sh PROD + # ./deploy.sh $DEPLOY_ENV + # ./awsconfiguration.sh $DEPLOY_ENV + source awsenvconf + ./buildenv.sh -e $DEPLOY_ENV -b ${LOGICAL_ENV}-${APPNAME}-deployvar + source buildenvvar + ./master_deploy.sh -d CFRONT -e $DEPLOY_ENV -c true + +jobs: + # Build & Deploy against development backend + "build-dev": + <<: *defaults + environment: + DEPLOY_ENV: "DEV" + LOGICAL_ENV: "dev" + APPNAME: "accounts-app" + steps: *builddeploy_steps + "build-qa": + <<: *defaults + environment: + DEPLOY_ENV: "QA" + LOGICAL_ENV: "qa" + APPNAME: "accounts-app" + steps: *builddeploy_steps + "build-prod": + <<: *defaults + environment: + DEPLOY_ENV: "PROD" + LOGICAL_ENV: "prod" + APPNAME: "accounts-app" + steps: *builddeploy_steps + workflows: version: 2 build: jobs: - build-dev: + context : org-global filters: branches: - only: [ dev, dev-circleci2 ] + only: [ dev, qa-accessibility ] - build-qa: + context : org-global filters: branches: only: qa - build-prod: + context : org-global filters: branches: - only: master + only: master diff --git a/app/app-config.coffee b/app/app-config.coffee index 3a9fcb3a..315ed98e 100644 --- a/app/app-config.coffee +++ b/app/app-config.coffee @@ -72,6 +72,7 @@ config = ( states['MEMBER_LOGIN'] = url: '/member?retUrl&handle&password&return_to&client_id&response_type&state&redirect_uri&scope' + title: 'Login' controller : 'TCLoginController as vm' template: require('./views/tc/login')() public: true @@ -87,6 +88,7 @@ config = ( # message : (optional) A message handed by Identity Service when some error occurs states['MEMBER_REGISTRATION'] = url: '/member/registration?retUrl&utm_source&utm_medium&utm_campaign&userJWTToken&auth0Jwt&auth0Refresh&message' + title: 'Register' params: { 'auth0Data', 'regForm' } controller : 'TCRegistrationController as vm' template: require('./views/tc/register.jade')() diff --git a/app/app-run.coffee b/app/app-run.coffee index 5ba2def2..afa3b6af 100644 --- a/app/app-run.coffee +++ b/app/app-run.coffee @@ -9,6 +9,8 @@ run = ($log, $rootScope, $state, $urlRouter, $location) -> # hide common footer and banner for connect pages to allow new styled footer for connect $rootScope.hideCommonFooter = toState.url && toState.url.indexOf('/connect') != -1 + # page title + $rootScope.pageTitle = toState.title path = $location.path() queryString = '' referrer = '' diff --git a/app/index.jade b/app/index.jade index 7d368b83..13b210e3 100644 --- a/app/index.jade +++ b/app/index.jade @@ -1,11 +1,11 @@ doctype html -html(ng-app='accounts') +html(ng-app='accounts', xmlns='http://www.w3.org/1999/xhtml', lang='en', xml:lang='en') head meta(http-equiv='Content-type', content='text/html; charset=utf-8') meta(http-equiv='X-UA-Compatible', content='IE=edge, chrome=1') - meta(name='viewport', content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no') + meta(name='viewport', content='width=device-width, initial-scale=1') base(href='/') - title Topcoder + title(ng-bind="pageTitle ? pageTitle + ' | Topcoder' : 'Topcoder'") style. .ng-hide { display: none !important; @@ -16,7 +16,7 @@ html(ng-app='accounts') .img ui-view.view-container - div(ui-view="footer", ng-controller="FooterController as vm", ng-hide="hideCommonFooter") + div(ui-view="footer", ng-controller="FooterController as vm", ng-hide="hideCommonFooter", role="contentinfo" aria-label="Footer") .account-footer a.privacy-policy(ng-href="https://www.topcoder.com/community/how-it-works/privacy-policy/", target="_blank") | Privacy Policy diff --git a/app/scripts/directives/toggle-password-directive-tips.js b/app/scripts/directives/toggle-password-directive-tips.js index 03eaadfc..21938c49 100644 --- a/app/scripts/directives/toggle-password-directive-tips.js +++ b/app/scripts/directives/toggle-password-directive-tips.js @@ -5,7 +5,9 @@ import angular from 'angular' angular.module('accounts.directives').directive('togglePasswordWithTips', togglePasswordWithTips) - function togglePasswordWithTips() { + togglePasswordWithTips.$inject = ['$timeout'] + + function togglePasswordWithTips($timeout) { return { restrict: 'E', require: '^form', @@ -46,7 +48,9 @@ import angular from 'angular' passwordInput.focus() } else { // If you are blurring from the password input and clicking anywhere but the checkbox - vm.passwordFocus = false + $timeout(function () { + vm.passwordFocus = false + }, 100) if (vm.password === '' || vm.password === undefined) { vm.placeholder = vm.defaultPlaceholder diff --git a/app/scripts/tc/register.controller.js b/app/scripts/tc/register.controller.js index 2bb46ff8..e94f3be9 100644 --- a/app/scripts/tc/register.controller.js +++ b/app/scripts/tc/register.controller.js @@ -14,9 +14,9 @@ import { getNewJWT } from '../../../core/auth.js' angular.module('accounts').controller('TCRegistrationController', TCRegistrationController) - TCRegistrationController.$inject = ['$log', '$scope', '$state', '$stateParams', 'UserService', 'ISO3166'] + TCRegistrationController.$inject = ['$log', '$scope', '$state', '$stateParams', 'UserService', 'ISO3166', '$timeout'] - function TCRegistrationController($log, $scope, $state, $stateParams, UserService, ISO3166) { + function TCRegistrationController($log, $scope, $state, $stateParams, UserService, ISO3166, $timeout) { var vm = this vm.registering = false // auth0 login data, passed from another states as state param @@ -58,6 +58,18 @@ import { getNewJWT } from '../../../core/auth.js' vm.ssoForced = !!(identifySSOProvider(email)) }) + $scope.usernameFocusLoss = function () { + $timeout(function () { + vm.usernameTips = false + }, 100); + } + + $scope.emailFocusLoss = function () { + $timeout(function () { + vm.emailTips = false + }, 100); + } + vm.updateCountry = function (angucompleteCountryObj) { var countryCode = _.get(angucompleteCountryObj, 'originalObject.code', undefined) diff --git a/app/styles/connect/connect.scss b/app/styles/connect/connect.scss index d034f0b0..4f1b0e4d 100644 --- a/app/styles/connect/connect.scss +++ b/app/styles/connect/connect.scss @@ -1,4 +1,4 @@ -@import "../tc-ui-variables"; +@import "../tc-ui-variables.scss"; .connect-accounts-container { background: $tc-gray-neutral-light; @@ -75,11 +75,17 @@ p.error { text-align: center; + color: $tc-red-110; } a { - color: #0B71E6; + color: $tc-dark-blue-90; text-decoration: none; + outline-width: 3px; + } + + a:focus{ + outline: 2px solid $tc-dark-blue-70; } .small-text { diff --git a/app/styles/connect/login.scss b/app/styles/connect/login.scss index 36af64da..ee7170c3 100644 --- a/app/styles/connect/login.scss +++ b/app/styles/connect/login.scss @@ -8,6 +8,10 @@ flex-direction: column; align-items: center; + span { + text-decoration: underline; + } + hr { width: 50%; } diff --git a/app/styles/directives/toggle-password-with-tips.directive.scss b/app/styles/directives/toggle-password-with-tips.directive.scss index a7863505..7a8f2923 100644 --- a/app/styles/directives/toggle-password-with-tips.directive.scss +++ b/app/styles/directives/toggle-password-with-tips.directive.scss @@ -1,4 +1,5 @@ @import 'topcoder/tc-includes'; +@import "../tc-ui-variables.scss"; // Toggle password with password tips directive toggle-password-with-tips { @@ -20,7 +21,7 @@ toggle-password-with-tips { .input-btn .input:focus ~ .tc-btn { color: #FFFFFF; - background: #59A7FF; + background: $tc-dark-blue-90; } .input-btn .tc-btn, @@ -30,7 +31,7 @@ toggle-password-with-tips { position: absolute; right: 1px; top: 1px; - background: #DCDCE0; + background: $tc-gray-60; border: 0; height: 38px; border-radius: 0 3px 3px 0; diff --git a/app/styles/directives/toggle-password.directive.scss b/app/styles/directives/toggle-password.directive.scss index 0bdc3476..3c2f7ff1 100644 --- a/app/styles/directives/toggle-password.directive.scss +++ b/app/styles/directives/toggle-password.directive.scss @@ -1,4 +1,5 @@ @import 'topcoder/tc-includes'; +@import '../tc-ui-variables.scss'; // Toggle password directive toggle-password { @@ -29,13 +30,15 @@ toggle-password { .input-btn .tc-btn:active { position: absolute; right: 1px; - top: 1px; - background: #DCDCE0; + top: 21px; + background: $tc-white; border: 0; + border-left: 1px solid $tc-gray-30; height: 38px; border-radius: 0 3px 3px 0; box-shadow: none; line-height: inherit; + color: $tc-gray-80; } button#toggleInputTypeBtn { @@ -43,11 +46,4 @@ toggle-password { margin-top: 0px; } - label { - display: flex !important; - line-height: 20px !important; - position: absolute; - top: 10px; - right: 0px; - } } diff --git a/app/styles/tc-ui-variables.scss b/app/styles/tc-ui-variables.scss index 4485962c..ea449c74 100644 --- a/app/styles/tc-ui-variables.scss +++ b/app/styles/tc-ui-variables.scss @@ -27,7 +27,7 @@ $tc-black : #262628; $tc-gray-90 : #37373C; $tc-gray-80 : #47474F; $tc-gray-70 : #5D5D66; -$tc-gray-60 : #747480; +$tc-gray-60 : #6B6B6B; $tc-gray-50 : #888894; $tc-gray-40 : #A3A3AD; $tc-gray-30 : #C3C3C8; @@ -36,10 +36,12 @@ $tc-gray-10 : #EDEDF2; $tc-gray-neutral-dark : #EBEBEB; $tc-gray-neutral-light : #FAFAFB; $tc-white : #FFFFFF; +$tc-white-cream : #F6F6F6; // Accents & Shades +$tc-dark-blue-110 : #006AD7; $tc-dark-blue : $tc-dark-blue; -$tc-dark-blue-90 : #1A85FF; +$tc-dark-blue-90 : #006AD7; $tc-dark-blue-70 : #59A7FF; $tc-dark-blue-30 : #CFE6FF; $tc-dark-blue-10 : #F4F9FF; @@ -56,6 +58,7 @@ $tc-orange-70 : #FDA464; $tc-orange-30 : #FEE3D0; $tc-orange-10 : #FFF0EB; +$tc-red-110 : #DF1E07; $tc-red : #F22F24; $tc-red-70 : #FF5B52; $tc-red-30 : #FFD4D1; diff --git a/app/styles/tc-ui.scss b/app/styles/tc-ui.scss index 7d400da4..2ec9a5d2 100644 --- a/app/styles/tc-ui.scss +++ b/app/styles/tc-ui.scss @@ -93,6 +93,10 @@ font-family: inherit; font-weight: inherit; } + + .tc-btn.show-password-btn:focus { + outline: 2px solid $tc-dark-blue-70; + } .tc-btn.loading:enabled, .tc-btn:focus:not(:disabled) { background: $tc-white; @@ -356,4 +360,4 @@ font-size: 15px; line-height: 20px; } -} \ No newline at end of file +} diff --git a/app/styles/tc/account.scss b/app/styles/tc/account.scss index 29a0bf50..a78d8ada 100644 --- a/app/styles/tc/account.scss +++ b/app/styles/tc/account.scss @@ -1,5 +1,6 @@ @import 'topcoder/tc-includes'; @import 'topcoder/tc-forms'; +@import '../tc-ui-variables.scss'; .login-container, .register-container, @@ -25,7 +26,7 @@ height: 70px; position: relative; - .logo-link img { + .logo-link img, .ico img { display: inline-block; height: 30px; } @@ -41,6 +42,7 @@ width: 380px; font-size: 20px; line-height: 30px; + margin: 0 auto; margin-bottom: 40px; margin-top: 39px; text-transform: uppercase; @@ -96,7 +98,7 @@ } span { @include font-with-weight('Sofia Pro', 500); - color: $accent-gray; + color: $tc-gray-60; cursor: pointer; font-size: 10px; line-height: 13px; @@ -115,7 +117,7 @@ margin-bottom: 40px; p { @include font-with-weight; - color: $accent-gray; + color: $tc-gray-60; font-size: 13px; line-height: 22px; text-transform: uppercase; @@ -146,25 +148,19 @@ } .github { .ico { - background-image: url(../../images/tc/github.svg); - background-repeat: no-repeat; color: #404041; } } .facebook { margin-left: 41px; .ico { - background-image: url(../../images/tc/facebook.svg); - background-repeat: no-repeat; color: #0d72b9; } } .google-plus { margin-left: 43px; .ico { - background-image: url(../../images/tc/gplus.svg); - background-position: center; - background-repeat: no-repeat; + padding-top: 10px; border: 1px solid #d1d3d4; border-radius: 4px; color: #ee4036; @@ -173,16 +169,12 @@ .twitter { margin-left: 40px; .ico { - background-image: url(../../images/tc/twitter.svg); - background-repeat: no-repeat; color: #26a9e0; } } .sso { margin-left: 22px; .ico { - background-image: url(../../images/tc/sso.svg); - background-repeat: no-repeat; color: #000000; } } @@ -201,6 +193,11 @@ text-transform: uppercase; a { display: inline; + color: $tc-dark-blue-90 !important; + text-decoration: underline; + &:focus { + outline: 3px auto $tc-dark-blue-90; + } } .redirect { width: 111px; @@ -219,8 +216,11 @@ justify-content: center; background-color: $gray-lighter; padding: 20px 30px 20px 30px; + a { + text-decoration: underline; + } .copyright-notice { - color: $gray-dark; + color: $tc-gray-60; } } diff --git a/app/styles/tc/footer.scss b/app/styles/tc/footer.scss index 03c096a8..c79da19a 100644 --- a/app/styles/tc/footer.scss +++ b/app/styles/tc/footer.scss @@ -1,43 +1,56 @@ @import 'topcoder/tc-includes'; +@import "../tc-ui-variables"; .bottom-footer { - background-color: $gray-darkest; - padding: 1px 20px 30px 20px; + background-color: $gray-darkest; + padding: 1px 20px 30px 20px; } .social-links { - font-size: 13px; - line-height: 1.2em; - text-align: center; - font-weight: normal; - margin: 35px 0; - color: #fff; - - a { - display: inline-block; - background-size: contain; - background-repeat: no-repeat; - margin: 23px 0; - - + a { - margin-left: 30px; - } - } + font-size: 13px; + line-height: 1.2em; + text-align: center; + font-weight: normal; + margin: 35px 0; + color: #fff; + + a { + display: inline-block; + background-size: contain; + background-repeat: no-repeat; + margin: 23px 0; + + + a { + margin-left: 30px; + } + } } .copyright-notice { - text-align: center; + text-align: center; font-size: 12px; line-height: 14px; color: #656565; @include font-with-weight('Sofia Pro', 500); - justify-content: center; - text-transform: uppercase; + justify-content: center; + text-transform: uppercase; } .privacy-policy { - @extend .copyright-notice; - margin-right: 1.0em; + @extend .copyright-notice; + margin-right: 1.0em; + + &:focus { + color: $tc-dark-blue; + } +} + +a.privacy-policy:focus { + outline: 2px solid $tc-dark-blue-90; +} + +a.privacy-policy:focus{ + outline: 2px solid $tc-dark-blue-70; } /* diff --git a/app/styles/tc/login.scss b/app/styles/tc/login.scss index d3b93a95..d5117fc4 100644 --- a/app/styles/tc/login.scss +++ b/app/styles/tc/login.scss @@ -1,6 +1,20 @@ @import 'topcoder/tc-includes'; +@import "../tc-ui-variables"; .login-container { + label { + @include font-with-weight('Sofia Pro', 500); + margin: 5px 0; + display: block; + margin-bottom: 5px; + text-align: left; + color: $tc-gray-80; + font-size: 10px; + line-height: 10px; + height: initial; + text-align: left; + } + form { display: flex; flex-flow: column wrap; @@ -9,6 +23,10 @@ p + button { margin-top: 0; + + &:focus { + outline: 3px auto $tc-dark-blue-90; + } } } .form-errors { @@ -16,6 +34,15 @@ margin-bottom: 20px; } } + + button[type=submit] { + background-color: $tc-dark-blue-110 !important; + } + + button[type=submit]:disabled { + background-color: $tc-gray-60 !important; + } + .problem-signin { @include font-with-weight('Merriweather Sans'); color: #a3a3ae; @@ -26,9 +53,26 @@ font-size: 12px; margin-bottom: 25px; margin-top: 25px; + color: #006DEA; + &:focus { + outline: 3px auto $tc-dark-blue-90; + } } } + + .tc-btn-wide { + background: $tc-gray-20; + color: $tc-gray-80; + } section.login-options { + a:focus { + outline: 3px auto $tc-dark-blue-90; + .network { + span { + text-decoration: underline; + } + } + } @media (max-width: 767px) { margin-bottom: 41px; } diff --git a/app/styles/tc/register.scss b/app/styles/tc/register.scss index 70813493..0c3b52c3 100644 --- a/app/styles/tc/register.scss +++ b/app/styles/tc/register.scss @@ -1,6 +1,29 @@ @import 'topcoder/tc-includes'; +@import '../tc-ui-variables.scss'; .register-container { + label { + @include font-with-weight('Sofia Pro', 500); + margin: 5px 0; + display: block; + margin-bottom: 5px; + text-align: left; + color: $tc-gray-80; + text-transform: uppercase; + font-size: 10px; + line-height: 10px; + height: initial; + text-align: left; + } + + a { + color: $tc-dark-blue-90; + text-decoration: underline; + &:focus { + outline: 2px solid $tc-dark-blue-70; + } + } + form { display: flex; flex-flow: column wrap; @@ -8,6 +31,15 @@ align-items: center; button { margin-top: 0; + background-color: $tc-dark-blue-90; + &:focus { + outline: 3px solid $tc-dark-blue-90; + } + &:disabled { + background-color: $tc-gray-60 !important; + color: $tc-white; + opacity: 1; + } } @media (min-width: 768px) { @@ -38,7 +70,7 @@ margin-bottom: 20px; margin-top: 10px; p { - color: #a3a3ae; + color: #3A3A3A; font-size: 12px; line-height: 15px; } @@ -48,10 +80,26 @@ hr { border: none; border-bottom: 1px solid $gray-light; - margin: 10px auto 20px; + margin: 10px auto; max-width: 180px; } } + + .login-options .networks .network { + span { + color: #757585; + text-decoration: underline; + } + .ico:focus { + outline: 3px solid #77A1F8; + } + } +} + +.join-topcoder { + a { + text-decoration: underline; + } } diff --git a/app/styles/tc/reset-password.scss b/app/styles/tc/reset-password.scss index 7e768db2..c3d5fa0d 100644 --- a/app/styles/tc/reset-password.scss +++ b/app/styles/tc/reset-password.scss @@ -1,4 +1,5 @@ -@import 'topcoder/tc-includes'; +@import "topcoder/tc-includes"; +@import "../tc-ui-variables"; .reset-password-container { form { @@ -10,7 +11,7 @@ align-self: center; margin-top: 0px; - &[type='submit'] { + &[type="submit"] { margin-top: 20px; } } @@ -20,4 +21,15 @@ margin-bottom: 25px; margin-top: 25px; } + .link { + a:focus { + outline: 2px solid $tc-dark-blue-90; + } + } + + .tc-btn:focus { + border: 1px solid $tc-dark-blue-90; + background-color: $tc-dark-blue-90; + box-shadow: 0 0 2px 1px $tc-dark-blue-70; + } } diff --git a/app/styles/tc/topcoder.scss b/app/styles/tc/topcoder.scss index 3faee36a..b7c2e75d 100644 --- a/app/styles/tc/topcoder.scss +++ b/app/styles/tc/topcoder.scss @@ -267,7 +267,7 @@ $tips-background: $gray-lighter; } } } - h3 { + h2 { @include sofia-pro-medium; font-size: 14px; padding-bottom: 15px; diff --git a/app/views/directives/toggle-password-with-tips.directive.jade b/app/views/directives/toggle-password-with-tips.directive.jade index 68633b05..e74efbc9 100644 --- a/app/views/directives/toggle-password-with-tips.directive.jade +++ b/app/views/directives/toggle-password-with-tips.directive.jade @@ -15,7 +15,9 @@ maxlength="64", has-letter, has-symbol-or-number, + aria-describedby="tp-help-password", + aria-required="false", class="input input-btn {{ vm.hasPasswordError() ? 'error' : ''}}" required) - \ No newline at end of file + diff --git a/app/views/directives/toggle-password.directive.jade b/app/views/directives/toggle-password.directive.jade index 6a9e6240..8991c6c9 100644 --- a/app/views/directives/toggle-password.directive.jade +++ b/app/views/directives/toggle-password.directive.jade @@ -1,4 +1,5 @@ .input-btn + label(for="current-password-input") PASSWORD input#current-password-input( ng-model="vm.currentPassword", ng-model-options="{allowInvalid: true}", @@ -9,8 +10,10 @@ name="currentPassword", type="password", placeholder="{{currentPasswordPlaceholder}}", - class="input input-btn" + class="input input-btn", + aria-label="password", + aria-invalid="false", required) \ No newline at end of file diff --git a/app/views/login.jade b/app/views/login.jade index aa4016d9..45743ecc 100644 --- a/app/views/login.jade +++ b/app/views/login.jade @@ -16,14 +16,14 @@ div | or Login with your social account. ul li - a(href="#" ng-click="vm.socialLogin('facebook')" ng-disabled='vm.loading') + a(href="#" ng-click="vm.socialLogin('facebook')" ng-disabled='vm.loading' tabindex="0") | Facebook li - a(href="#" ng-click="vm.socialLogin('github')" ng-disabled='vm.loading') + a(href="#" ng-click="vm.socialLogin('github')" ng-disabled='vm.loading' tabindex="0") | Github li - a(href="#" ng-click="vm.socialLogin('google-oauth2')" ng-disabled='vm.loading') + a(href="#" ng-click="vm.socialLogin('google-oauth2')" ng-disabled='vm.loading' tabindex="0") | Google li - a(href="#" ng-click="vm.socialLogin('twitter')" ng-disabled='vm.loading') + a(href="#" ng-click="vm.socialLogin('twitter')" ng-disabled='vm.loading' tabindex="0") | Twitter diff --git a/app/views/sso/sso-login.jade b/app/views/sso/sso-login.jade index 83fd3c82..79e5e491 100644 --- a/app/views/sso/sso-login.jade +++ b/app/views/sso/sso-login.jade @@ -18,7 +18,7 @@ main.layout-main.login-reg.flex.center.middle.connect-accounts-container.tc-ui(" input.input.input-sm(type="text" ng-model="vm.emailOrHandle" required=true placeholder="Email or handle" autofocus=true) button.action.tc-btn.tc-btn-primary(type="submit" style="margin-bottom:11px") Continue - p Back to Login + p Back to Login p.success(ng-show="vm.success") Redirecting to {{ vm.retUrl }} ... diff --git a/app/views/tc/login.jade b/app/views/tc/login.jade index f4bf57ba..a9b2b29b 100644 --- a/app/views/tc/login.jade +++ b/app/views/tc/login.jade @@ -1,50 +1,62 @@ - var logoMobile = require("../../images/logo_mobile.svg") +- var logoGithub = require("../../images/tc/github.svg") +- var logoGooglePlus = require("../../images/tc/gplus.svg") +- var logoFacebook = require("../../images/tc/facebook.svg") +- var logoTwitter = require("../../images/tc/twitter.svg") +- var logoSso = require("../../images/tc/sso.svg") .login-container - header + header(role="banner") a.logo-link(href="/", title="Back to the home page") img(src=logoMobile, alt="Topcoder Logo") - - h1 LOG IN TO TOPCODER - - form(name="vm.loginForm", role="form", ng-submit="vm.loginForm.$valid && vm.login()", novalidate) - .form-errors(ng-messages="vm.loginErrors") - p.form-error(ng-message="USERNAME_NONEXISTANT") We couldn't find a member with that {{vm.emailOrUsername || "username"}}. Please check that you entered it correctly. - - p.form-error(ng-message="WRONG_PASSWORD") That password is incorrect. Please check that you entered the right one. - - p.form-error(ng-message="SOCIAL_LOGIN_ERROR") User with that profile is not registered. - - div.validation-bar(ng-class="{'error-bar': vm.loginErrors.USERNAME_NONEXISTANT}") - input(ng-model="vm.username", name="username", placeholder="Username or Email", type="text", required) - - toggle-password - - p.problem-signin - a.forgot-password(href="{{vm.forgotPasswordUrl}}") Forgot your password? - - button.tc-btn.tc-btn-wide(type="submit", ng-disabled="vm.loginForm.$invalid || vm.loading") Log In - - section.login-options - p.tc-separator - span Or Log in With - - ul.networks - li.network.github - a.ico(ng-click="vm.socialLogin('github')") - span Github - li.network.google-plus - a.ico(ng-click="vm.socialLogin('google-oauth2')") - span Google - li.network.facebook - a.ico(ng-click="vm.socialLogin('facebook')") - span Facebook - li.network.twitter - a.ico(ng-click="vm.socialLogin('twitter')") - span Twitter - li.network.sso - a.ico(ui-sref="SSO_LOGIN({app:'member',retUrl:vm.$stateParams.retUrl})") - span Single Sign On - -p.join-topcoder Not a member yet?   + + main + h1 LOG IN TO TOPCODER + + form(name="vm.loginForm", role="form", ng-submit="vm.loginForm.$valid && vm.login()", novalidate) + .form-errors(ng-messages="vm.loginErrors") + p.form-error(ng-message="USERNAME_NONEXISTANT" role="alert") We couldn't find a member with that {{vm.emailOrUsername || "username"}}. Please check that you entered it correctly. + + p.form-error(ng-message="WRONG_PASSWORD" role="alert") That password is incorrect. Please check that you entered the right one. + + p.form-error(ng-message="SOCIAL_LOGIN_ERROR" role="alert") User with that profile is not registered. + + div.validation-bar(ng-class="{'error-bar': vm.loginErrors.USERNAME_NONEXISTANT}") + label(for="username") USERNAME OR EMAIL + input(ng-model="vm.username", id="username", placeholder="Username or Email", type="text", required, aria-invalid="false") + + toggle-password + + p.problem-signin + a.forgot-password(href="{{vm.forgotPasswordUrl}}", aria-label="forgot password") Forgot your password? + + button.tc-btn.tc-btn-wide(type="submit", ng-disabled="vm.loginForm.$invalid || vm.loading") Log In + + section.login-options + p.tc-separator + span Or Log in With + + ul.networks + li.network.github() + a.ico(ng-click="vm.socialLogin('github')", tabIndex="0", href="#", title="Login with GitHub") + img(src=logoGithub, alt="Github Logo") + span Github + li.network.google-plus() + a.ico(ng-click="vm.socialLogin('google-oauth2')", tabIndex="0", href="#", title="Login with Google") + img(src=logoGooglePlus, alt="Google Logo") + span Google + li.network.facebook() + a.ico(ng-click="vm.socialLogin('facebook')", tabIndex="0", href="#", title="Login with Facebook") + img(src=logoFacebook, alt="Facebook Logo") + span Facebook + li.network.twitter() + a.ico(ng-click="vm.socialLogin('twitter')", tabIndex="0", href="#", title="Login with Twitter") + img(src=logoTwitter, alt="Twitter Logo") + span Twitter + li.network.sso() + a.ico(ui-sref="SSO_LOGIN({app:'member',retUrl:vm.$stateParams.retUrl})", tabIndex="0", href="#", title="Login with Single Sign On") + img(src=logoSso, alt="Single Sign On Logo") + span Single Sign On + +p.join-topcoder(role="region") Not a member yet?   a(href="{{vm.registrationUrl}}") Join Now diff --git a/app/views/tc/register.jade b/app/views/tc/register.jade index 7ddac3b6..67f5d2fa 100644 --- a/app/views/tc/register.jade +++ b/app/views/tc/register.jade @@ -1,131 +1,146 @@ +- var logoMobile = require("../../images/logo_mobile.svg") +- var logoGithub = require("../../images/tc/github.svg") +- var logoGooglePlus = require("../../images/tc/gplus.svg") +- var logoFacebook = require("../../images/tc/facebook.svg") + .register-container - header + header(role="banner") a.logo-link(href="/") - img(src=require("../../images/logo_mobile.svg"), alt="Topcoder Logo") + img(src=logoMobile, alt="Topcoder Logo") .arrow //- h1 Join the Topcoder technology community to earn, learn, and connect - h1 Join Topcoder - - form(name="vm.registerForm", role="form", ng-submit="vm.registerForm.$valid && vm.register()", novalidate, autocomplete="off") - - // Stops Chrome from autofilling and autocompleting (along with autocomplete="off" on the form) - input(autocomplete="false", name="hidden", type="text", style="display:none;") + main + h1 Join Topcoder - p.form-error(ng-show="vm.errMsg") {{vm.errMsg}} + form(name="vm.registerForm", role="form", ng-submit="vm.registerForm.$valid && vm.register()", novalidate, autocomplete="off" aria-label="Registration") + label(for="registration") Registration form + // Stops Chrome from autofilling and autocompleting (along with autocomplete="off" on the form) + input(autocomplete="false", name="hidden", type="text", style="display:none;") - .first-last-names - input-sticky-placeholder(sticky-placeholder="First", ng-model="vm.firstname") - input(ng-model="vm.firstname", maxlength="64", name="firstname", placeholder="First Name", type="text", required) + p.form-error(ng-show="vm.errMsg" role="alert") {{vm.errMsg}} - input-sticky-placeholder(sticky-placeholder="Last", ng-model="vm.lastname") - input(ng-model="vm.lastname", maxlength="64", name="lastname", placeholder="Last Name", type="text", required) + .first-last-names + input-sticky-placeholder(sticky-placeholder="First", ng-model="vm.firstname") + label(for="firstname") First Name + input(ng-model="vm.firstname", maxlength="64", id="firstname", name="firstname", placeholder="First Name", type="text", required) - .country-dropdown - angucomplete-alt( - input-name="country", - placeholder="Country", - pause="100", - selected-object="vm.updateCountry", - local-data="vm.countries", - initial-value="vm.countryObj", - search-fields="name", - title-field="name", - match-class="angucomplete-highlight", + input-sticky-placeholder(sticky-placeholder="Last", ng-model="vm.lastname") + label(for="lastname") Last Name + input(ng-model="vm.lastname", maxlength="64", id="lastname", name="lastname", placeholder="Last Name", type="text", required) - minlength="1" - ) + .country-dropdown#country + label(for="country") Country + angucomplete-alt( + input-name="country", + placeholder="Country", + pause="100", + selected-object="vm.updateCountry", + local-data="vm.countries", + initial-value="vm.countryObj", + search-fields="name", + title-field="name", + match-class="angucomplete-highlight", + field-tabindex="0" + minlength="1" + ) - .form-input-error(ng-show="vm.registerForm.country.$dirty && !vm.isValidCountry") - p.form-error(ng-show="!vm.isValidCountry") Please choose a country from the list + .form-input-error(ng-show="vm.registerForm.country.$dirty && !vm.isValidCountry") + p.form-error(ng-show="!vm.isValidCountry" role="alert") Please choose a country from the list - .section-break - hr + .section-break + hr - .validation-bar(ng-class="{ 'error-bar': (vm.registerForm.username.$error.usernameIsFree || vm.registerForm.username.$error.minlength || vm.registerForm.username.$error.maxlength) }") - input-sticky-placeholder(sticky-placeholder="Username", ng-model="vm.username") - input(ng-model="vm.username", ng-model-options="{ debounce: {'default': 500} }", ng-focus="vm.usernameTips = true", ng-blur="vm.usernameTips = false", ng-minlength="2", ng-maxlength="15", name="username", placeholder="Username", type="text", username-is-free, required) + .validation-bar(ng-class="{ 'error-bar': (vm.registerForm.username.$error.usernameIsFree || vm.registerForm.username.$error.minlength || vm.registerForm.username.$error.maxlength) }") + input-sticky-placeholder(sticky-placeholder="Username", ng-model="vm.username") + label(for="username") Username + input#username(aria-describedby="tp-help-username", ng-model="vm.username", ng-model-options="{ debounce: {'default': 500} }", ng-focus="vm.usernameTips = true", ng-blur="usernameFocusLoss()", ng-minlength="2", ng-maxlength="15", name="username", placeholder="Username", type="text", username-is-free, required) - .tips.username-tips(ng-show="vm.usernameTips") - .arrow - h3 Username Tips: + .tips.username-tips(id="tp-help-username", role="tooltip", ng-show="vm.usernameTips") + .arrow + h2 Username Tips: - p Your username will be public + p Your username will be public - p Please choose one that is between 2 and 15 characters + p Please choose one that is between 2 and 15 characters - p It can contain letters, numbers, and these characters: -_.{}[] + p It can contain letters, numbers, and these characters: -_.{}[] - .form-input-error(ng-if="vm.registerForm.username.$dirty && vm.registerForm.username.$invalid", ng-messages="vm.registerForm.username.$error") - p.form-error(ng-message="required") Please enter a username. - p.form-error(ng-message="usernameIsFree") {{vm.usernameErrorMessage}} + .form-input-error(ng-if="vm.registerForm.username.$dirty && vm.registerForm.username.$invalid", ng-messages="vm.registerForm.username.$error") + p.form-error(ng-message="required" role="alert") Please enter a username. + p.form-error(ng-message="usernameIsFree" role="alert") {{vm.usernameErrorMessage}} - p.form-error(ng-message="minlength") That username is not the correct length or format. + p.form-error(ng-message="minlength" role="alert") That username is not the correct length or format. - p.form-error(ng-message="maxlength") That username is not the correct length or format. + p.form-error(ng-message="maxlength" role="alert") That username is not the correct length or format. - .validation-bar(ng-class="{ 'error-bar': (vm.registerForm.email.$dirty && vm.registerForm.email.$invalid) }") - input-sticky-placeholder.email(sticky-placeholder="Email", ng-model="vm.email") - input(ng-model="vm.email", ng-model-options="{ debounce: {'default': 500} }", ng-focus="vm.emailTips = true", ng-blur="vm.emailTips = false", name="email", placeholder="Enter Your Email", type="email", valid-email, email-is-available, required, ng-disabled="!!vm.ssoUser") + .validation-bar(ng-class="{ 'error-bar': (vm.registerForm.email.$dirty && vm.registerForm.email.$invalid) }") + input-sticky-placeholder.email(sticky-placeholder="Email", ng-model="vm.email") + label(for="email") Enter Your Email + input#email(aria-describedby="tp-help-email", ng-model="vm.email", ng-model-options="{ debounce: {'default': 500} }", ng-focus="vm.emailTips = true", ng-blur="emailFocusLoss()", name="email", placeholder="Enter Your Email", type="email", valid-email, email-is-available, required, ng-disabled="!!vm.ssoUser") - .tips.email-tips(ng-show="vm.emailTips") - .arrow - h3 Email Tips: + .tips.email-tips(id="tp-help-email", role="tooltip", ng-show="vm.emailTips") + .arrow + h2 Email Tips: - p Your email address will be private and not shared with anyone. + p Your email address will be private and not shared with anyone. - p We'll occasionally send you emails related to your activities or interests. + p We'll occasionally send you emails related to your activities or interests. - .tips.email-tips(ng-show="vm.ssoForced") - .arrow - h3 Note: + .tips.email-tips(ng-show="vm.ssoForced") + .arrow + h2 Note: - p Your email address will be linked with your Organization account. + p Your email address will be linked with your Organization account. - p Please use Single Sign On when you log in to Topcoder. + p Please use Single Sign On when you log in to Topcoder. - .form-input-error(ng-show="vm.registerForm.email.$dirty && vm.registerForm.email.$invalid", ng-messages="vm.registerForm.email.$error") - p.form-error(ng-message="emailIsAvailable") {{vm.emailErrorMessage}} + .form-input-error(ng-show="vm.registerForm.email.$dirty && vm.registerForm.email.$invalid", ng-messages="vm.registerForm.email.$error") + p.form-error(ng-message="emailIsAvailable" role="alert") {{vm.emailErrorMessage}} - p.form-error(ng-message="validEmail") {{vm.emailErrorMessage}} + p.form-error(ng-message="validEmail" role="alert") {{vm.emailErrorMessage}} - p.form-error(ng-message="required") Please enter an email address. + p.form-error(ng-message="required" role="alert") Please enter an email address. - .validation-bar - toggle-password-with-tips(ng-if="!vm.isSocialRegistration && !vm.ssoForced && !vm.ssoUser", placeholder="Create Password") + .validation-bar + label(for="password-input") Password + toggle-password-with-tips(ng-if="!vm.isSocialRegistration && !vm.ssoForced && !vm.ssoUser", placeholder="Create Password") - .tips.password-tips(ng-show="vm.passwordFocus && !vm.ssoForced") - .arrow - //- h3 Password Tips: + .tips.password-tips(id="tp-help-password", role="tooltip", ng-show="vm.passwordFocus && !vm.ssoForced") + .arrow + //- h3 Password Tips: - H3 Your password must have: + H2 Your password must have: - p(ng-class="{ 'has-length-between-range': (vm.registerForm.password.$dirty && !vm.registerForm.password.$error.minlength && !vm.registerForm.password.$error.maxlength && !vm.registerForm.password.$error.required) }") At least 8 characters + p(ng-class="{ 'has-length-between-range': (vm.registerForm.password.$dirty && !vm.registerForm.password.$error.minlength && !vm.registerForm.password.$error.maxlength && !vm.registerForm.password.$error.required) }") At least 8 characters - p(ng-class="{ 'has-letter': (vm.registerForm.password.$dirty && !vm.registerForm.password.$error.hasLetter) }") At least one letter + p(ng-class="{ 'has-letter': (vm.registerForm.password.$dirty && !vm.registerForm.password.$error.hasLetter) }") At least one letter - p(ng-class="{ 'has-symbol-or-number': (vm.registerForm.password.$dirty && !vm.registerForm.password.$error.hasSymbolOrNumber) }") At least one number or symbol + p(ng-class="{ 'has-symbol-or-number': (vm.registerForm.password.$dirty && !vm.registerForm.password.$error.hasSymbolOrNumber) }") At least one number or symbol - section.terms - p By clicking "Join" you agree to Topcoder's #[a(href="http://www.topcoder.com/community/how-it-works/terms/", target="_blank") Terms] and #[a(href="http://www.topcoder.com/community/how-it-works/privacy-policy/", target="_blank") Privacy Policy] + section.terms + p By clicking "Join" you agree to Topcoder's #[a(href="http://www.topcoder.com/community/how-it-works/terms/", target="_blank") Terms] and #[a(href="http://www.topcoder.com/community/how-it-works/privacy-policy/", target="_blank") Privacy Policy] - button.tc-btn.tc-btn-large(type="submit", tc-busy-button, tc-busy-when="vm.registering", ng-disabled="vm.registerForm.$invalid", ng-show="vm.isValidCountry") Join - button.tc-btn.tc-btn-large.disabled(type="submit", ng-show="!vm.isValidCountry", disabled="disabled") Join + button.tc-btn.tc-btn-large(type="submit", tc-busy-button, tc-busy-when="vm.registering", ng-disabled="vm.registerForm.$invalid || vm.registerForm.$pending", tabIndex="0") Join - section.login-options(ng-if="!vm.ssoUser") - p.tc-separator - span Or Register With + div(role="region" aria-label="Register With") + section.login-options(ng-if="!vm.ssoUser") + p.tc-separator + span Or Register With - ul.networks - li.network.github - a.ico(ng-click="vm.socialRegister('github')") - span Github - li.network.google-plus - a.ico(ng-click="vm.socialRegister('google-oauth2')") - span Google - li.network.facebook - a.ico(ng-click="vm.socialRegister('facebook')") - span Facebook + ul.networks + li.network.github + a.ico(ng-click="vm.socialRegister('github')", href="#", tabindex="0", title="Register with Github") + img(src=logoGithub, alt="Github Logo") + span Github + li.network.google-plus + a.ico(ng-click="vm.socialRegister('google-oauth2')", href="#", tabindex="0", title="Register with Google") + img(src=logoGooglePlus, alt="Google Logo") + span Google + li.network.facebook + a.ico(ng-click="vm.socialRegister('facebook')", href="#", tabindex="0", title="Register with Facebook") + img(src=logoFacebook, alt="Facebook Logo") + span Facebook -.join-topcoder +.join-topcoder(role="region" aria-label="Login") span Have an account?   a(ui-sref="MEMBER_LOGIN") Log in diff --git a/app/views/tc/reset-password.jade b/app/views/tc/reset-password.jade index 45d3dc0d..15c1fbc1 100644 --- a/app/views/tc/reset-password.jade +++ b/app/views/tc/reset-password.jade @@ -18,27 +18,28 @@ .tips.email-tips(ng-show="vm.emailTips") .arrow - h3 Email Tips: + h2 Email Tips: p Enter your email address and we'll get back to you with a reset link .form-errors - p.form-error(ng-show="vm.generateTokenForm.email.$dirty && vm.generateTokenForm.email.$invalid") Please enter a valid email address. + p.form-error(ng-show="vm.generateTokenForm.email.$dirty && vm.generateTokenForm.email.$invalid" role="alert") Please enter a valid email address. - p.form-error(ng-show="vm.alreadySent") You already requested a reset link recently. Please check your inbox or spam folder. If you have any trouble, please contact  + p.form-error(ng-show="vm.alreadySent" role="alert") You already requested a reset link recently. Please check your inbox or spam folder. If you have any trouble, please contact  a(href="mailto:support@topcoder.com?Subject=Unable%20to%20reset%20my%20password" target="_top") support@topcoder.com - p.form-error(ng-show="vm.emailNotFound") We couldn't find a member with that email address. Please check that you entered it correctly. If you continue to have trouble, please contact  + p.form-error(ng-show="vm.emailNotFound" role="alert") We couldn't find a member with that email address. Please check that you entered it correctly. If you continue to have trouble, please contact  a(href="mailto:support@topcoder.com?Subject=Unable%20to%20reset%20my%20password" target="_top") support@topcoder.com - p.form-error(ng-show="vm.unableToRest") We were unable to send you a reset link because your account is not allowed to reset password. If you are using Single Sign On, please follow the instructions of your SSO account to reset password. + p.form-error(ng-show="vm.unableToRest" role="alert") We were unable to send you a reset link because your account is not allowed to reset password. If you are using Single Sign On, please follow the instructions of your SSO account to reset password. - p.form-error(ng-show="vm.unkownError") We were unable to send you a reset link because of a temporary problem. Please try again. If you continue to have trouble, please contact  + p.form-error(ng-show="vm.unkownError" role="alert") We were unable to send you a reset link because of a temporary problem. Please try again. If you continue to have trouble, please contact  a(href="mailto:support@topcoder.com?Subject=Unable%20to%20reset%20my%20password" target="_top") support@topcoder.com button.tc-btn(type="submit", ng-disabled='vm.generateTokenForm.email.$invalid || vm.loading', ng-class="{'enabled-button': vm.generateTokenForm.$valid && !vm.loading}") Get Reset Link - a.link(ui-sref="MEMBER_LOGIN") Back to Login + p.link + a(ui-sref="MEMBER_LOGIN", aria-label="back to login") Back to Login .reset-password-container(ng-show="vm.resetTokenSent") header @@ -51,7 +52,8 @@ p(class="m-b-lg") We have sent you an email with a link to reset your password. - a.link(ui-sref="MEMBER_LOGIN") Back to Login + p.link + a(ui-sref="MEMBER_LOGIN") Back to Login .reset-password-container(ng-show="vm.token") header @@ -68,7 +70,7 @@ .tips.password-tips(ng-show="vm.passwordFocus") .arrow - h3 Password Tips: + h2 Password Tips: p(ng-class="{ 'has-length-between-range': (vm.resetPasswordForm.password.$dirty && !vm.resetPasswordForm.password.$error.minlength && !vm.resetPasswordForm.password.$error.maxlength && !vm.resetPasswordForm.password.$error.required) }") Must be between 8 and 64 characters @@ -77,9 +79,10 @@ p(ng-class="{ 'has-symbol-or-number': (vm.resetPasswordForm.password.$dirty && !vm.resetPasswordForm.password.$error.hasSymbolOrNumber) }") At least one number or symbol .form-errors - p.form-error(ng-show="vm.resetFailed") We were unable to reset your password. Please request another reset link. If you continue to have trouble, please contact + p.form-error(ng-show="vm.resetFailed" role="alert") We were unable to reset your password. Please request another reset link. If you continue to have trouble, please contact a(href="mailto:support@topcoder.com?Subject=Unable%20to%20reset%20my%20password" target="_top") support@topcoder.com button.tc-btn(type="submit", ng-disabled='vm.resetPasswordForm.password.$invalid || vm.loading', ng-class="{'enabled-button': vm.resetPasswordForm.$valid && !vm.loading}") Set Password - a.link(ui-sref="MEMBER_LOGIN") Back to Login + p.link + a(ui-sref="MEMBER_LOGIN") Back to Login diff --git a/connector/connector-wrapper.js b/connector/connector-wrapper.js index 645f7a1d..31e3439f 100644 --- a/connector/connector-wrapper.js +++ b/connector/connector-wrapper.js @@ -7,14 +7,14 @@ let url = '' let mock = false let token = '' -export function configureConnector({connectorUrl, frameId, mockMode, mockToken}) { +export function configureConnector({connectorUrl, frameId, mockMode, mockToken, frameTitle}) { if (mockMode) { mock = true token = mockToken } else if (iframe) { console.warn('tc-accounts connector can only be configured once, this request has been ignored.') } else { - iframe = createFrame(frameId, connectorUrl) + iframe = createFrame(frameId, connectorUrl, frameTitle) url = connectorUrl loading = new Promise( (resolve) => { diff --git a/connector/iframe.js b/connector/iframe.js index 50974691..6cb1de4f 100644 --- a/connector/iframe.js +++ b/connector/iframe.js @@ -1,4 +1,4 @@ -export default function createFrame(id, src) { +export default function createFrame(id, src, title) { const iframe = document.createElement('iframe') iframe.id = id @@ -6,7 +6,9 @@ export default function createFrame(id, src) { iframe.width = 0 iframe.height = 0 iframe.frameborder = 0 - + if (title) { + iframe.title = title + } document.body.appendChild(iframe) return iframe