diff --git a/src/components/login/login.js b/src/components/login/login.js index cea0090a0..cfc3dd103 100644 --- a/src/components/login/login.js +++ b/src/components/login/login.js @@ -7,7 +7,7 @@ app.component('login', { /* eslint no-param-reassign: ["error", { "props": false }] */ constructor($scope, $rootScope, $timeout, $document, $mdMedia, - $cookies, $location, Passphrase, $state, Account, Peers) { + $cookies, $location, Passphrase, $state, Account, Peers, dialog) { this.$scope = $scope; this.$rootScope = $rootScope; this.$timeout = $timeout; @@ -18,9 +18,11 @@ app.component('login', { this.$state = $state; this.account = Account; this.peers = Peers; + this.dialog = dialog; this.Passphrase = Passphrase; this.generatingNewPassphrase = false; + this.$rootScope.loggingIn = false; this.networks = [{ name: 'Mainnet', @@ -57,14 +59,20 @@ app.component('login', { * @param {String} [_passphrase=this.input_passphrase] */ passConfirmSubmit(_passphrase = this.input_passphrase) { + this.$rootScope.loggingIn = true; if (this.Passphrase.normalize.constructor === Function) { - this.peers.setActive(this.network); - - this.account.set({ - passphrase: this.Passphrase.normalize(_passphrase), - network: this.network, + this.peers.setActive(this.network).then(() => { + this.$rootScope.loggingIn = false; + if (this.peers.online) { + this.account.set({ + passphrase: this.Passphrase.normalize(_passphrase), + network: this.network, + }); + this.$state.go(this.$rootScope.landingUrl || 'main.transactions'); + } else { + this.dialog.errorToast(`Failed to connect to node ${this.network.address}`); + } }); - this.$state.go(this.$rootScope.landingUrl || 'main.transactions'); } } diff --git a/src/components/login/login.pug b/src/components/login/login.pug index 98ad3406e..4323ee87a 100644 --- a/src/components/login/login.pug +++ b/src/components/login/login.pug @@ -20,5 +20,5 @@ md-card md-content(layout='row', layout-align='center center') // md-button(ng-disabled='$ctrl.generatingNewPassphrase', ng-click='$ctrl.devTestAccount()') Dev Test Account md-button.md-primary.new-account-button(ng-disabled='$ctrl.random || $ctrl.generatingNewPassphrase', ng-click='$ctrl.generatePassphrase()') NEW ACCOUNT - md-button.md-raised.md-primary.login-button(md-autofocus, ng-disabled='$ctrl.valid != undefined && $ctrl.valid !== 1', type='submit') Login + md-button.md-raised.md-primary.login-button(md-autofocus, ng-disabled='($ctrl.valid != undefined && $ctrl.valid !== 1) || $root.loggingIn', type='submit') Login passphrase(ng-if='$ctrl.generatingNewPassphrase', data-on-login='$ctrl.onLogin', data-target='primary-pass') diff --git a/src/components/top/top.less b/src/components/top/top.less index 8c9bb3f3b..0df80bad2 100644 --- a/src/components/top/top.less +++ b/src/components/top/top.less @@ -11,7 +11,6 @@ top { display: block; width: 100%; text-align: center; - padding-top: 12px; } .status { @@ -27,15 +26,29 @@ top { color: #F45D4C; } } - - .value { - font-size: 120%; - font-weight: bold; - background-color: #5f696e; - color: #fff; - border-radius: 3px; - padding: 9px 9px; + .value-wrapper { + width: 100%; + height: 70px; + text-align: center; + background: #eee; + .primary { + font-size: 120%; + font-weight: bold; + color: #5f696e; + padding: 9px 9px; + display: inline-block; + &.full { + height: 51px; + line-height: 51px; + } + } + .secondary { + color: #5f696e; + border-radius: 3px; + font-size: 100%; + } } + md-select { margin: 0; @@ -46,8 +59,34 @@ top { .balance-wrapper { display: inline-block; line-height: 41px; + position: relative; + overflow: hidden; &.has-send-modal { cursor: pointer; + + .tooltip { + position: absolute; + z-index: 1; + width: 100%; + text-align: center; + left: 0; + top: 100%; + transition: all ease 200ms; + font-size: 85%; + } + + lsk { + position: relative; + transition: all ease 200ms; + z-index: 2; + &:hover { + color: #000; + + & + .tooltip { + transform: translateY(-33px); + } + } + } } } } diff --git a/src/components/top/top.pug b/src/components/top/top.pug index e31eea089..18d9ecf76 100644 --- a/src/components/top/top.pug +++ b/src/components/top/top.pug @@ -2,25 +2,30 @@ md-content(layout='column', layout-gt-xs='row') md-card.offline-hide(flex-gt-xs=33) md-card-content(layout='column', layout-align='center center', ng-if='!$ctrl.account.get().isDelegate') span.md-title.title Address - .address.value {{ $ctrl.account.get().address }} + div.value-wrapper + .address.value.primary.full {{ $ctrl.account.get().address }} md-card-content(layout='column', layout-align='center center', ng-if='$ctrl.account.get().isDelegate') span.md-title.title Delegate - .address.value {{ $ctrl.account.get().username }} - small.username {{ $ctrl.account.get().address }} + div.value-wrapper + .address.value.primary {{ $ctrl.account.get().username }} + small.username.secondary {{ $ctrl.account.get().address }} md-card.peer.offline-hide(flex-gt-xs=33) md-card-content(layout='column', layout-align='center center') span.status i.material-icons.offline(ng-show='!$ctrl.peers.online') error i.material-icons.online(ng-show='$ctrl.peers.online') check circle span.md-title.title Peer - div.active-peer.value - span(ng-bind="$ctrl.peers.active.currentPeer") - span(ng-if="$ctrl.peers.active.port && $ctrl.peers.active.port != '8000' ") - span : - span(ng-bind="$ctrl.peers.active.port") + div.value-wrapper + span.primary {{ $ctrl.peers.active.options.name }} + div.active-peer.value.secondary + span(ng-bind="$ctrl.peers.active.currentPeer") + span(ng-if="$ctrl.peers.active.port && $ctrl.peers.active.port != '8000' ") + span : + span(ng-bind="$ctrl.peers.active.port") md-card.offline-hide(flex-gt-xs=33) md-card-content(layout='column', layout-align='center center') span.md-title.title Balance - div(class='balance-wrapper', data-show-send-modal, data-amount='$ctrl.totalSendable', data-ng-class='{"has-send-modal": $ctrl.totalSendable > 0}') - lsk.balance.value(amount='$ctrl.account.get().balance', nocolor, append) - md-tooltip(md-direction='top', md-delay='350', data-ng-if='$ctrl.account.get().balance > 0') Send all funds + div.value-wrapper + div(class='balance-wrapper', data-show-send-modal, data-amount='$ctrl.totalSendable', data-ng-class='{"has-send-modal": $ctrl.totalSendable > 0}') + lsk.balance.value.primary.full(amount='$ctrl.account.get().balance', nocolor, append) + span.tooltip.secondary(data-ng-if='$ctrl.account.get().balance > 0') Click to send all funds diff --git a/src/index.pug b/src/index.pug index 8a46cee4e..a74c42ebd 100644 --- a/src/index.pug +++ b/src/index.pug @@ -11,7 +11,7 @@ html div.body-wrapper md-content(id="main", flex='100', flex-gt-sm='80', flex-offset-gt-sm='10') header - div.absolutely-positioned-loading(layout='row', layout-align='space-around', ng-show='prelogged') + div.absolutely-positioned-loading(layout='row', layout-align='space-around', ng-show='prelogged || loggingIn') md-progress-circular.md-warn(md-mode='indeterminate', md-diameter='80') div(ng-class='{ online: $root.peers.online, offline: !$root.peers.online }') div(data-ui-view) diff --git a/src/services/api/peers.js b/src/services/api/peers.js index 45e1f35d7..6b57e2424 100644 --- a/src/services/api/peers.js +++ b/src/services/api/peers.js @@ -54,7 +54,7 @@ app.factory('Peers', ($timeout, $cookies, $location, $q, $rootScope) => { conf = network; if (network.address) { conf.node = network.address.split(':')[1].replace('//', ''); - conf.port = network.address.match(/:([0-9]{1,5})$/)[1]; + conf.port = network.address.match(/:([0-9]{1,5})\/?$/) && network.address.match(/:([0-9]{1,5})\/?$/)[1]; conf.ssl = network.address.split(':')[0] === 'https'; } if (conf.testnet === undefined && conf.port !== undefined) { @@ -63,7 +63,7 @@ app.factory('Peers', ($timeout, $cookies, $location, $q, $rootScope) => { } this.active = lisk.api(conf); - this.check(); + return this.check(); } /** @@ -95,9 +95,7 @@ app.factory('Peers', ($timeout, $cookies, $location, $q, $rootScope) => { * @method check */ check() { - this.reset(); - - this.sendRequestPromise('loader/status', {}) + return this.sendRequestPromise('loader/status', {}) .then(() => this.online = true) .catch(() => this.online = false); } diff --git a/test/components/login/login.spec.js b/test/components/login/login.spec.js index b7c02493f..73eb076f3 100644 --- a/test/components/login/login.spec.js +++ b/test/components/login/login.spec.js @@ -69,9 +69,10 @@ describe('Login controller', () => { /* eslint-disable no-unused-vars */ let $timeout; /* eslint-enable no-unused-vars */ + let $q; beforeEach(inject((_$componentController_, _$rootScope_, _$state_, - _Passphrase_, _$cookies_, _$timeout_, _Account_) => { + _Passphrase_, _$cookies_, _$timeout_, _Account_, _$q_) => { $componentController = _$componentController_; $rootScope = _$rootScope_; $state = _$state_; @@ -81,6 +82,7 @@ describe('Login controller', () => { /* eslint-disable no-unused-vars */ $timeout = _$timeout_; /* eslint-enable no-unused-vars */ + $q = _$q_; })); beforeEach(() => { @@ -122,15 +124,29 @@ describe('Login controller', () => { }); describe('passConfirmSubmit()', () => { + let peersMock; + let deferred; + + beforeEach(() => { + deferred = $q.defer(); + peersMock = sinon.mock(controller.peers); + peersMock.expects('setActive').returns(deferred.promise); + controller.peers.online = true; + }); + it('sets account.phassphrase as this.input_passphrase processed by normalizer', () => { controller.input_passphrase = '\tTEST PassPHrASe '; controller.passConfirmSubmit(); + deferred.resolve(); + $scope.$apply(); expect(account.get().passphrase).to.equal('test passphrase'); }); it('calls Passphrase.normalize()', () => { const spy = sinon.spy(Passphrase, 'normalize'); controller.passConfirmSubmit(); + deferred.resolve(); + $scope.$apply(); expect(spy).to.have.been.calledWith(); }); @@ -138,8 +154,19 @@ describe('Login controller', () => { controller.input_passphrase = testPassphrase; const spy = sinon.spy($state, 'go'); controller.passConfirmSubmit(); + deferred.resolve(); + $scope.$apply(); expect(spy).to.have.been.calledWith(); }); + + it('shows error toast if peers.setActive sets peers.online = false', () => { + const spy = sinon.spy(controller.dialog, 'errorToast'); + controller.peers.online = false; + controller.passConfirmSubmit(); + deferred.resolve(); + $scope.$apply(); + expect(spy).to.have.been.calledWith(`Failed to connect to node ${controller.network.address}`); + }); }); describe('devTestAccount()', () => {