diff --git a/Gruntfile.js b/Gruntfile.js index f8d2cdac74..31adcd98ee 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -62,7 +62,7 @@ module.exports = function (grunt) { 'bower_components/ngclipboard/dist/ngclipboard.js', 'bower_components/growl/javascripts/jquery.growl.js', 'bower_components/jquery-validation/dist/jquery.validate.js', - 'bower_components/jpkleemans-angular-validate/src/angular-validate.js', + 'bower_components/waves-angular-validate/src/angular-validate.js', 'src/js/vendor/jquery.modal.js', @@ -118,6 +118,7 @@ module.exports = function (grunt) { 'src/js/shared/password.strength.directive.js', 'src/js/shared/address.directive.js', 'src/js/shared/decimal.directive.js', + 'src/js/shared/focus.directive.js', 'src/js/shared/transaction.loading.service.js', 'src/js/shared/transaction.filter.js', diff --git a/bower.json b/bower.json index efb32801b8..a0b994d408 100644 --- a/bower.json +++ b/bower.json @@ -23,7 +23,8 @@ "growl": "^1.3.2", "angular-messages": "^1.5.8", "angular-validation-match": "^1.9.0", - "jpkleemans-angular-validate": "^1.1.1" + "angular-material": "^1.1.1", + "waves-angular-validate": "git@github.com:beregovoy68/angular-validate.git#^1.1.2" }, "analytics": false } diff --git a/src/css/style.css b/src/css/style.css index 213226958c..e4fd7dd6c7 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -1188,6 +1188,14 @@ span.tabs-radio img.selected { color: #999999; } +.popup-autocomplete { + z-index: 160; +} + +.md-virtual-repeat-container.md-autocomplete-suggestions-container { + z-index: 160; +} + /* ======================================================================= */ diff --git a/src/js/app.js b/src/js/app.js index 9404f9fa38..38622ac1fc 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -4,22 +4,92 @@ * @see controllers * @see services */ -var app = angular.module('app', - [ - 'restangular', - 'waves.core', - 'waves.core.services', - - 'ngclipboard', - 'ngMessages', - 'ngValidate', - 'ngAnimate', - 'app.ui', - 'app.shared', - 'app.login', - 'app.navigation', - 'app.wallet', - 'app.history', - 'app.community' - ] -); + +// mock methods to implement late binding +var __mockShowError = function(message) {}; +var __mockValidateAddress = function(address) {}; + +var app = angular.module('app', [ + 'restangular', + 'waves.core', + 'waves.core.services', + + 'ngclipboard', + 'ngMessages', + 'ngAnimate', + 'ngMaterial', + 'ngValidate', + 'app.ui', + 'app.shared', + 'app.login', + 'app.navigation', + 'app.wallet', + 'app.history', + 'app.community' +]).config(AngularApplicationConfig).run(AngularApplicationRun); + +function AngularApplicationConfig($validatorProvider) { + $validatorProvider.setDefaults({ + errorClass: 'wInput-error', + onkeyup: false, + showErrors : function(errorMap, errorList) { + errorList.forEach(function(error) { + // can't use notificationService here cos services are not available in config phase + __mockShowError(error.message); + }); + + var i, elements; + for (i = 0, elements = this.validElements(); elements[i]; i++) { + angular.element(elements[i]).removeClass(this.settings.errorClass); + } + + for (i = 0, elements = this.invalidElements(); elements[i]; i++) { + angular.element(elements[i]).addClass(this.settings.errorClass); + } + } + }); + $validatorProvider.addMethod('address', function(value, element) { + return this.optional(element) || __mockValidateAddress(value); + }, 'Account number must be a sequence of 35 alphanumeric characters with no spaces, ' + + 'optionally starting with \'1W\''); + $validatorProvider.addMethod('decimal', function(value, element, params) { + var maxdigits = angular.isNumber(params) ? params : Currency.WAV.precision; + + var regex = new RegExp('^(?:-?\\d+)?(?:\\.\\d{1,' + maxdigits + '})?$'); + return this.optional(element) || regex.test(value); + }, 'Amount is expected with a dot (.) as a decimal separator with no more than {0} fraction digits'); + $validatorProvider.addMethod('password', function(value, element) { + if (this.optional(element)) + return true; + + var containsDigits = /[0-9]/.test(value); + var containsUppercase = /[A-Z]/.test(value); + var containsLowercase = /[a-z]/.test(value); + + return containsDigits && containsUppercase && containsLowercase; + }, 'The password is too weak. A good password must contain at least one digit, ' + + 'one uppercase and one lowercase letter'); +} + +AngularApplicationConfig.$inject = ['$validatorProvider']; + +function AngularApplicationRun(rest, coreConstants, notificationService, addressService) { + // restangular configuration + rest.setDefaultHttpFields({ + timeout: 10000 // milliseconds + }); + //var url = coreConstants.NODE_ADDRESS; + var url = 'http://52.28.66.217:6869'; + rest.setBaseUrl(url); + + // override mock methods cos in config phase services are not available yet + __mockShowError = function (message) { + notificationService.error(message); + }; + __mockValidateAddress = function (address) { + return addressService.validateDisplayAddress(address); + }; +} + +AngularApplicationRun.$inject = ['Restangular', 'constants.core', 'notificationService', 'addressService']; + diff --git a/src/js/shared/address.directive.js b/src/js/shared/address.directive.js index 50f68f5fdf..f849c495cf 100644 --- a/src/js/shared/address.directive.js +++ b/src/js/shared/address.directive.js @@ -14,7 +14,7 @@ return true; return addressService.validateDisplayAddress(viewValue); - } + }; } }; }]); diff --git a/src/js/shared/decimal.directive.js b/src/js/shared/decimal.directive.js index 9f4da56c25..f879b7b9ee 100644 --- a/src/js/shared/decimal.directive.js +++ b/src/js/shared/decimal.directive.js @@ -23,10 +23,10 @@ return true; var maxdigits = isFinite(parseInt(digits)) ? digits : 8; - var regex = new RegExp("^(?:-?\\d+)?(?:\\.\\d{1," + maxdigits + "})?$"); + var regex = new RegExp('^(?:-?\\d+)?(?:\\.\\d{1,' + maxdigits + '})?$'); return regex.test(viewValue); - } + }; } }; }); diff --git a/src/js/shared/focus.directive.js b/src/js/shared/focus.directive.js new file mode 100644 index 0000000000..065be82378 --- /dev/null +++ b/src/js/shared/focus.directive.js @@ -0,0 +1,18 @@ +(function () { + 'use strict'; + + angular + .module('app.shared') + .directive('focusMe', ['$timeout', function WavesFocusDirective($timeout) { + return { + restrict: 'A', + link: function (scope, element, attributes) { + scope.$watch(attributes.focusMe, function (newValue) { + $timeout(function () { + return newValue && element[0].focus(); + }); + }, true); + } + }; + }]); +})(); diff --git a/src/js/shared/password.strength.directive.js b/src/js/shared/password.strength.directive.js index 15a346c562..4d32eefd83 100644 --- a/src/js/shared/password.strength.directive.js +++ b/src/js/shared/password.strength.directive.js @@ -18,7 +18,7 @@ var containsLowercase = /[a-z]/.test(viewValue); return containsDigits && containsUppercase && containsLowercase; - } + }; } }; }); diff --git a/src/js/shared/shared.dialog.directive.js b/src/js/shared/shared.dialog.directive.js index 77e827e164..12d5d76b9e 100644 --- a/src/js/shared/shared.dialog.directive.js +++ b/src/js/shared/shared.dialog.directive.js @@ -8,6 +8,7 @@ closeable: true, showButtons: true, okButtonCaption: 'OK', + okButtonEnabled: true, cancelButtonCaption: 'CANCEL' }; @@ -58,6 +59,7 @@ dialogOk: '&onDialogOk', dialogCancel: '&onDialogCancel', okButtonCaption: '@', + okButtonEnabled: '=?', cancelButtonCaption: '@', isError: '=?' }, @@ -66,7 +68,8 @@ '
' + '
' + '' + + 'title="{{::tooltip}}" ng-click="onOk()" ng-disabled="!okButtonEnabled">' + + '{{::okButtonCaption}}' + '' + ' - +

SEED NOTICE

@@ -181,7 +181,7 @@

NEW ACCOUNT - NOTICE

need to have assigned a name.">
- +

@@ -232,7 +232,7 @@

NEW ACCOUNT - NOTICE


- +

@@ -338,7 +338,7 @@

ACCOUNT INFO BACKUP

-
+

SEND PAYMENT

Balance:

{{wallet.current.balance.formatAmount(true)}} @@ -355,11 +355,7 @@

SEND PAYMENT

Recipient's Address
- -
-

Recipient account number is required

-

Recipient address is malformed

-
+
@@ -367,22 +363,21 @@

SEND PAYMENT

Amount
- -
-

Amount to send is required

-

The amount to send must be a number
with no more than {{wallet.current.balance.currency.precision}} digits after the decimal point (.)

-
+
Fee - + + + {{item.displayText}} + + @@ -390,7 +385,7 @@

SEND PAYMENT

-
+

You are sending {{wallet.confirm.amount.value}} {{wallet.confirm.amount.currency}} with {{wallet.confirm.fee.value}} @@ -418,7 +413,7 @@

SEND PAYMENT

- + {{tx.formatted.datetime}} {{tx.formatted.type}} {{tx.formatted.sender}} @@ -494,7 +489,7 @@

DECENTRALIZED VOTING

- + {{tx.formatted.datetime}} {{tx.formatted.type}} {{tx.formatted.sender}} @@ -504,7 +499,7 @@

DECENTRALIZED VOTING

- + {{tx.formatted.datetime}} {{tx.formatted.type}} {{tx.formatted.sender}} @@ -623,6 +618,8 @@

LATEST BLOCKS INFORMATION

+ + @@ -635,7 +632,7 @@

LATEST BLOCKS INFORMATION

- + @@ -657,6 +654,7 @@

LATEST BLOCKS INFORMATION

+