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