diff --git a/bower.json b/bower.json index 2995b60f784afe223b5deb5707a8a3f330119bae..26ce45b551932ad451926a99a7b8a61752329470 100644 --- a/bower.json +++ b/bower.json @@ -3,5 +3,8 @@ "private": "true", "devDependencies": { "ionic": "driftyco/ionic-bower#1.0.1" + }, + "dependencies": { + "angular-messages": "1.3.13" } } diff --git a/www/css/style.css b/www/css/style.css index 46db401e9cee2a397a558eb8e0abff9b02241640..bfe19f0fe931d93b6efc392c87a1161b088f06a5 100644 --- a/www/css/style.css +++ b/www/css/style.css @@ -18,10 +18,6 @@ body { margin-top: 30px; } -#newAccount .button { - height: 50px; -} - .badge sub, .badge sup { line-height: inherit; } @@ -67,6 +63,36 @@ body { /*-webkit-transform: initial !important;*/ /*}*/ +/********** + Form validation +**********/ + +.form-errors:first-child { + margin: 5px 0; +} + +.form-errors:last-child { + margin: 5px 0 0; +} + +.form-error { + padding: 8px 16px; + font-size: 12px; + color: red; + vertical-align: middle; + text-align: end; +} + +.form-error i { + font-size: 24px; + color: #B83E2C; + vertical-align: middle; +} + +.item-input-error { + border-bottom: 2px solid red; +} + /********** MODAL **********/ @@ -78,11 +104,8 @@ body { height: 100%; } .slider-slide { - padding-top: 25px; color: #000; background-color: #fff; - text-align: center; - font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; font-weight: 300; } diff --git a/www/index.html b/www/index.html index eb0d15a85c8a49e7e65cfd2ec1d6fa6a6cc2a096..5b6c183818d36a3899debdde28aa9f578bc60fe8 100644 --- a/www/index.html +++ b/www/index.html @@ -15,6 +15,10 @@ <!-- ionic/angularjs js --> <script src="lib/ionic/js/ionic.bundle.js"></script> <script src="lib/ionic/js/angular/angular-resource.min.js"></script> + <script src="lib/ionic/js/angular/angular-sanitize.min.js"></script> + <script src="lib/ionic/js/angular/angular-translate.min.js"></script> + <script src="lib/ionic/js/angular/angular-translate-loader-static-files.min.js"></script> + <script src="lib/ionic/js/angular/angular-messages.min.js"></script> <script src="js/vendor/moment.min.js"></script> <script src="js/vendor/numeral.js"></script> <script src="js/vendor/socket-io.js"></script> diff --git a/www/js/app.js b/www/js/app.js index bc9ab915a74ef33df27aa93732c1356a82325485..c06b42d84c766c3bbe67875e694bc86d074b795e 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -4,7 +4,7 @@ // 'starter' is the name of this angular module example (also set in a <body> attribute in index.html) // the 2nd parameter is an array of 'requires' // 'starter.controllers' is found in controllers.js -angular.module('cesium', ['ionic', 'cesium.controllers']) +angular.module('cesium', ['ionic', 'ngMessages', 'pascalprecht.translate', 'cesium.controllers']) .filter('formatInteger', function() { return function(input) { @@ -44,6 +44,41 @@ angular.module('cesium', ['ionic', 'cesium.controllers']) } }) + // Translation i18n + .config(function ($translateProvider) { + $translateProvider.useStaticFilesLoader({ + prefix: 'i18n/locale-', + suffix: '.json' + }) + .uniformLanguageTag('bcp47') + .determinePreferredLanguage() + .useSanitizeValueStrategy('sanitize') + .fallbackLanguage(['en', 'fr']) + .useLoaderCache(true); + + }) + + // Add new compare-to directive (need for form validation) + .directive("compareTo", function() { + return { + require: "ngModel", + scope: { + otherModelValue: "=compareTo" + }, + link: function(scope, element, attributes, ngModel) { + + ngModel.$validators.compareTo = function(modelValue) { + return modelValue == scope.otherModelValue; + }; + + scope.$watch("otherModelValue", function() { + ngModel.$validate(); + }); + } + }; + }) + + .run(function($ionicPlatform) { $ionicPlatform.ready(function() { // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard diff --git a/www/js/controllers/currency-controllers.js b/www/js/controllers/currency-controllers.js index d8989dbaaf86b494701f1e6c22bb65e4c7aa979f..7c8bed42b7170be8234be806b03d63b5aebbc10c 100644 --- a/www/js/controllers/currency-controllers.js +++ b/www/js/controllers/currency-controllers.js @@ -5,7 +5,7 @@ angular.module('cesium.currency.controllers', ['cesium.services']) $stateProvider .state('app.explore_currency', { - url: "/home/explore", + url: "/currency", views: { 'menuContent': { templateUrl: "templates/explore/explore_currency.html", @@ -15,7 +15,7 @@ angular.module('cesium.currency.controllers', ['cesium.services']) }) .state('app.explore_tabs', { - url: "/currency", + url: "/currency/view", views: { 'menuContent': { templateUrl: "templates/explore/explore_tabs.html", diff --git a/www/js/controllers/home-controllers.js b/www/js/controllers/home-controllers.js index 5a55420b159970654e113c708afe20daced71b58..34d490c1a8e597d63586393ca97f72eea6c10fce 100644 --- a/www/js/controllers/home-controllers.js +++ b/www/js/controllers/home-controllers.js @@ -37,14 +37,9 @@ angular.module('cesium.home.controllers', ['cesium.services']) ; function LoginController($scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate) { - // Form data for the login modal - $scope.loginData = { - username: null, - password: null - }; - // Login modal $scope.loginModal = "undefined"; + $scope.loginData = {}; // Create the login modal that we will use later $ionicModal.fromTemplateUrl('templates/login.html', { @@ -55,6 +50,10 @@ function LoginController($scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $scope.loginModal.hide(); }); + $scope.setLoginForm = function(loginForm) { + $scope.loginForm = loginForm; + } + // Open login modal $scope.login = function(callback) { if ($scope.loginModal != "undefined" && $scope.loginModal != null) { @@ -76,9 +75,9 @@ function LoginController($scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, resolve(walletData); }) .catch(function(err) { - console.error('>>>>>>>' , err); - UIUtils.alert.error('Your browser is not compatible with cryptographic features.'); UIUtils.loading.hide(); + console.error('>>>>>>>' , err); + UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); reject(err); }); }); @@ -89,9 +88,9 @@ function LoginController($scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, resolve(walletData); }) .catch(function(err) { + UIUtils.loading.hide(); console.error('>>>>>>>' , err); UIUtils.alert.error('Could not fetch wallet data from remote uCoin node.'); - UIUtils.loading.hide(); reject(err); }); } @@ -102,35 +101,43 @@ function LoginController($scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, }; // Triggered in the login modal to close it - $scope.closeLogin = function() { - return $scope.loginModal.hide(); + $scope.cancelLogin = function() { + $scope.loginData = {}; // Reset login data + $scope.loginForm.$setPristine(); // Reset form + $scope.loginModal.hide(); }; // Login form submit $scope.doLogin = function() { - $scope.closeLogin(); - UIUtils.loading.show(); + if(!$scope.loginForm.$valid) { + return; + } + UIUtils.loading.show(); - // Call wallet login - Wallet.login($scope.loginData.username, $scope.loginData.password) - .catch(function(err) { - $scope.loginData = {}; // Reset login data - UIUtils.loading.hide(); - console.error('>>>>>>>' , err); - UIUtils.alert.error('Your browser is not compatible with cryptographic libraries.'); - }) + $scope.loginModal.hide() .then(function(){ - UIUtils.loading.hide(); - var callback = $scope.loginData.callback; - $scope.loginData = {}; // Reset login data - if (callback != "undefined" && callback != null) { - callback(); - } - // Default: redirect to wallet view - else { - $state.go('app.view_wallet'); - } - }); + // Call wallet login, then execute callback function + Wallet.login($scope.loginData.username, $scope.loginData.password) + .then(function(){ + var callback = $scope.loginData.callback; + $scope.loginData = {}; // Reset login data + $scope.loginForm.$setPristine(); // Reset form + if (callback != "undefined" && callback != null) { + callback(); + } + // Default: redirect to wallet view + else { + $state.go('app.view_wallet'); + } + }) + .catch(function(err) { + $scope.loginData = {}; // Reset login data + $scope.loginForm.$setPristine(); // Reset form + UIUtils.loading.hide(); + console.error('>>>>>>>' , err); + UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); + }); + }) }; $scope.loginDataChanged = function() { @@ -150,7 +157,7 @@ function LoginController($scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $scope.loginData.computing=false; UIUtils.loading.hide(); console.error('>>>>>>>' , err); - UIUtils.alert.error('Your browser is not compatible with cryptographic libraries.'); + UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); }); }; @@ -186,78 +193,132 @@ function HomeController($scope, $ionicSlideBoxDelegate, $ionicModal, $state, BMA //$scope.$on('$ionicView.enter', function(e) { //}); - //CurrenciesController.call(this, $scope, $state); - //LookupController.call(this, $scope, BMA, $state); LoginController.call(this, $scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate); - $scope.accountTypeMember = null; $scope.accounts = []; $scope.search = { text: '', results: {} }; $scope.knownCurrencies = ['meta_brouzouf']; + $scope.slideIndex = 0; + $scope.accountData = {}; + $scope.accountForm = {}; // Called to navigate to the main app $scope.cancel = function() { - $scope.modal.hide(); + $scope.newAccountModal.hide(); $timeout(function(){ - $scope.selectedCurrency = ''; - $scope.accountTypeMember = null; - $scope.search.text = ''; - $scope.search.results = []; + $scope.accountData = {}; + $scope.accountForm = {}; }, 200); }; - $scope.$on('currencySelected', function() { - $ionicSlideBoxDelegate.slide(1); - }); + $scope.setAccountForm = function(accountForm) { + $scope.accountForm = accountForm; + }; - $scope.selectAccountTypeMember = function(bool) { - $scope.accountTypeMember = bool; - $ionicSlideBoxDelegate.slide(2); + // Called each time the slide changes + $scope.slide = function(index) { + $ionicSlideBoxDelegate.slide(index); + $scope.slideIndex = index; + $scope.nextStep = $scope.slideIndex == 2 ? 'Start' : 'Next'; }; $scope.next = function() { - $ionicSlideBoxDelegate.next(); + $scope.slide($scope.slideIndex + 1); }; + $scope.previous = function() { - $ionicSlideBoxDelegate.previous(); + $scope.slide($scope.slideIndex - 1); }; - // Called each time the slide changes - $scope.slideChanged = function(index) { - $scope.slideIndex = index; - $scope.nextStep = $scope.slideIndex == 2 ? 'Start using MyApp' : 'Next'; - }; + $scope.newAccount = function() { + var showModal = function() { + $ionicSlideBoxDelegate.enableSlide(false); + $scope.slide(0); + $scope.newAccountModal.show(); + // TODO: remove default + /*$timeout(function() { + $scope.accountData.currency = $scope.knownCurrencies[0]; + $scope.accountData.isMember = true; + $scope.next(); + $scope.next(); + }, 300);*/ + } - $scope.addAccount = function() { - $scope.modal.show(); - $scope.slideChanged(0); - $ionicSlideBoxDelegate.slide(0); - $ionicSlideBoxDelegate.enableSlide(false); - // TODO: remove default - //$timeout(function() { - // $scope.selectedCurrency = $scope.knownCurrencies[0]; - // $scope.accountTypeMember = true; - // $scope.searchChanged(); - // $scope.search.text = 'cgeek'; - // $ionicSlideBoxDelegate.next(); - // $ionicSlideBoxDelegate.next(); - //}, 300); - }; + if (!$scope.newAccountModal) { + UIUtils.loading.show(); + // Create the account modal that we will use later + $ionicModal.fromTemplateUrl('templates/account/new_account.html', { + scope: $scope + }).then(function(modal) { + $scope.newAccountModal = modal; + $scope.newAccountModal.hide() + .then(function(){ + UIUtils.loading.hide(); + showModal(); + }); - // Create the account modal that we will use later - $ionicModal.fromTemplateUrl('templates/account/new_account.html', { - scope: $scope - }).then(function(modal) { - $scope.modal = modal; - $scope.modal.hide(); - // TODO: remove auto add account when done - //$timeout(function() { - // $scope.addAccount(); - //}, 400); - }); + }); + } + else { + showModal(); + } + }; $scope.selectCurrency = function(currency) { - $scope.selectedCurrency = currency; + $scope.accountData.currency = currency; + $ionicSlideBoxDelegate.slide(1); $scope.next(); - } + }; + + $scope.selectAccountTypeMember = function(bool) { + $scope.accountData.isMember = bool; + $scope.next(); + }; + + $scope.showAccountPubkey = function() { + $scope.accountData.computing=true; + CryptoUtils.connect($scope.accountData.username, $scope.accountData.password).then( + function(keypair) { + $scope.accountData.pubkey = CryptoUtils.util.encode_base58(keypair.signPk); + $scope.accountData.computing=false; + } + ) + .catch(function(err) { + $scope.accountData.computing=false; + console.error('>>>>>>>' , err); + UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); + }); + }; + + $scope.doNewAccount = function() { + $scope.accountForm.$submitted=true; + if(!$scope.accountForm.$valid) { + return; + } + + UIUtils.loading.show(); + $scope.newAccountModal.hide() + .then(function(){ + Wallet.login($scope.accountData.username, $scope.accountData.password) + .then(function() { + // Reset account data + delete $scope.accountForm; + $scope.accountData = {}; + UIUtils.loading.hide(); + $state.go('app.view_wallet'); + }) + .catch(function(err) { + UIUtils.loading.hide(); + console.error('>>>>>>>' , err); + UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); + }); + }) + }; + + // TODO: remove auto add account when done + /*$timeout(function() { + $scope.newAccount(); + }, 400); + */ } + diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js index 37b996a5ea1baba6a888a224635c9a00004f36aa..26594199cb4726ecb76e356b2dfb6a5fe478c7a9 100644 --- a/www/js/controllers/wallet-controllers.js +++ b/www/js/controllers/wallet-controllers.js @@ -41,7 +41,7 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency .controller('TransferCtrl', TransferController) ; -function WalletController($scope, $state, $q, $ionicPopup, UIUtils, Wallet) { +function WalletController($scope, $state, $q, $ionicPopup, UIUtils, Wallet, BMA, $translate) { $scope.walletData = {}; $scope.convertedBalance = 0; @@ -52,6 +52,7 @@ function WalletController($scope, $state, $q, $ionicPopup, UIUtils, Wallet) { $scope.loadWallet() .then(function(wallet) { $scope.updateWalletView(wallet); + UIUtils.loading.hide(); }); }); @@ -87,41 +88,79 @@ function WalletController($scope, $state, $q, $ionicPopup, UIUtils, Wallet) { $state.go('app.view_transfer'); }; + $scope.setRegisterForm = function(registerForm) { + $scope.registerForm = registerForm; + }; + // Self cert $scope.self= function() { - // Choose UID popup - $ionicPopup.show({ - template: '<input type="text" ng-model="walletData.uid">', - title: 'Enter a pseudo', - subTitle: 'A pseudo is need to let other member find you.', - scope: $scope, - buttons: [ - { text: 'Cancel' }, - { - text: '<b>Send</b>', - type: 'button-positive', - onTap: function(e) { - if (!$scope.walletData.uid) { - //don't allow the user to close unless he enters a uid - e.preventDefault(); - } else { - // TODO : check if not already used - return $scope.walletData.uid; + $translate(['ACCOUNT.NEW.TITLE', 'ACCOUNT.POPUP_REGISTER.TITLE', 'ACCOUNT.POPUP_REGISTER.HELP', 'COMMON.BTN_ADD_ACCOUNT', 'COMMON.BTN_CANCEL']) + .then(function (translations) { + + // Choose UID popup + $ionicPopup.show({ + templateUrl: 'templates/account/popup_register.html', + title: translations['ACCOUNT.POPUP_REGISTER.TITLE'], + subTitle: translations['ACCOUNT.POPUP_REGISTER.HELP'], + scope: $scope, + buttons: [ + { text: translations['COMMON.BTN_CANCEL'] }, + { + text: translations['COMMON.BTN_ADD_ACCOUNT'] /*'<b>Send</b>'*/, + type: 'button-positive', + onTap: function(e) { + $scope.registerForm.$submitted=true; + if(!$scope.registerForm.$valid || !$scope.walletData.uid) { + //don't allow the user to close unless he enters a uid + e.preventDefault(); + } else { + return $scope.walletData.uid; + } + } } + ] + }) + .then(function(uid) { + if (!uid) { // user cancel + $scope.walletData.uid = null; + UIUtils.loading.hide(); + return; } - } - ] - }) - .then(function(uid) { - UIUtils.loading.show(); - Wallet.self(uid) - .then(function() { - UIUtils.loading.hide(); - }) - .catch(UIUtils.onError('Could not send self certification')); - }); - + var doSendSelf = function() { + Wallet.self(uid) + .then(function() { + UIUtils.loading.hide(); + }) + .catch(UIUtils.onError('ERROR.SEND_SELF_REGISTRATION')); + }; + // Check uid is not used by another member + UIUtils.loading.show(); + BMA.wot.lookup({ search: uid }) + .then(function(res) { + var found = typeof res.results != "undefined" && res.results != null && res.results.length > 0 + && res.results.some(function(pub){ + return typeof pub.uids != "undefined" && pub.uids != null && pub.uids.length > 0 + && pub.uids.some(function(idty){ + return (idty.uid == uid); + }); + }); + if (found) { // uid is already used : display a message and reopen the popup + UIUtils.loading.hide(); + UIUtils.alert.info('ACCOUNT.NEW.MSG_UID_ALREADY_USED') + .then(function(){ + $scope.self(); + }); + } + else { + doSendSelf(); + } + }) + .catch(function() { + doSendSelf(); + }); + }); + }); }; } @@ -157,6 +196,7 @@ function TransferController($scope, $ionicModal, $state, $ionicHistory, BMA, Wal .then(function(walletData) { $scope.walletData = walletData; $scope.onUseRelativeChanged(); + UIUtils.loading.hide(); }); }); diff --git a/www/js/services/crypto-services.js b/www/js/services/crypto-services.js index 77d5b07da3776626cd1c06e4feafdac3e4a3ab95..0026e026bd43aff8829de58cfa081a2c4eb1f74f 100644 --- a/www/js/services/crypto-services.js +++ b/www/js/services/crypto-services.js @@ -85,6 +85,13 @@ angular.module('cesium.crypto.services', ['ngResource']) return base58.encode(a); }, + hash_sha256 = function(s) { + return $q(function(resolve, reject) { + var hash = nacl.crypto_hash_sha256(s); + resolve(hash); + }); + }, + /** * Create a key pair, from salt+password, and return a wallet object */ @@ -148,10 +155,9 @@ angular.module('cesium.crypto.services', ['ngResource']) util: { encode_utf8: nacl.encode_utf8, decode_utf8: decode_utf8, - encode_base58: encode_base58 + encode_base58: encode_base58, + hash_sha256: hash_sha256 }, - - connect: connect, sign: sign, verify: verify diff --git a/www/js/services/utils-services.js b/www/js/services/utils-services.js index 41ce70c4d37e8916198795cca61217d9ad44928a..2c209d31cbbee0241816cbda788182364a402905 100644 --- a/www/js/services/utils-services.js +++ b/www/js/services/utils-services.js @@ -2,36 +2,46 @@ angular.module('cesium.utils.services', ['ngResource']) -.factory('UIUtils', function($ionicLoading, $ionicPopup) { +.factory('UIUtils', function($ionicLoading, $ionicPopup, $translate, $q) { function alertError(err, subtitle) { - var message = err.message || err; - return $ionicPopup.show({ - template: '<p>' + (message || 'Unknown error') + '</p>', - title: 'Application error', - subTitle: subtitle, - buttons: [ - { - text: '<b>OK</b>', - type: 'button-assertive' - } - ] - }); - } - - function alertInfo(message, subtitle) { - var message = err.message || err; + $translate([err, 'ERROR.POPUP_TITLE', 'ERROR.UNKNOWN_ERROR', 'COMMON.BTN_OK']) + .then(function (translations) { + var message = err.message || translations[err]; return $ionicPopup.show({ - template: '<p>' + message + '</p>', - title: 'Information', + template: '<p>' + (message || translations['ERROR.UNKNOWN_ERROR']) + '</p>', + title: translations['ERROR.POPUP_TITLE'], subTitle: subtitle, buttons: [ { - text: '<b>OK</b>', - type: 'button-positive' + text: '<b>'+translations['COMMON.BTN_OK']+'</b>', + type: 'button-assertive' } ] }); - } + }); + } + + function alertInfo(message, subtitle) { + return $q(function(resolve, reject) { + $translate([message, 'INFO.POPUP_TITLE', 'COMMON.BTN_OK']) + .then(function (translations) { + return $ionicPopup.show({ + template: '<p>' + translations[message] + '</p>', + title: translations['INFO.POPUP_TITLE'], + subTitle: subtitle, + buttons: [ + { + text: '<b>'+translations['COMMON.BTN_OK']+'</b>', + type: 'button-positive', + onTap: function(e) { + resolve(e); + } + } + ] + }); + }); + }); + } function hideLoading(){ $ionicLoading.hide(); @@ -46,14 +56,15 @@ angular.module('cesium.utils.services', ['ngResource']) function onError(msg) { return function(err) { console.error('>>>>>>>' , err); - alertError(msg + ': ' + err); hideLoading(); + alertError(msg + ': ' + err); } } return { alert: { - error: alertError + error: alertError, + info: alertInfo }, loading: { show: showLoading, diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index 248bddefb87933a89d1e1b7c3026227e3916b7d5..6da5f8cdb017c28fa73cdf528bc899461c72c9d5 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -87,6 +87,10 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' && data.pubkey != null; }, + getData = function() { + return data; + }, + isSourceEquals = function(arg1, arg2) { return arg1.type == arg2.type && arg1.fingerprint == arg2.fingerprint @@ -94,7 +98,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' && arg1.amount == arg2.amount; }, - loadData = function() { + loadData = function(refresh) { if (data.loaded) { return refreshData(); } @@ -469,6 +473,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' login: login, logout: logout, isLogin: isLogin, + getData: getData, loadData: loadData, refreshData: refreshData, // operations diff --git a/www/templates/account/new_account.html b/www/templates/account/new_account.html index 82683e11c9c451c79880bb11f99aae5f7b0b5907..91bd5c84e3bf5db01e613d0977ca076856fd6cfe 100644 --- a/www/templates/account/new_account.html +++ b/www/templates/account/new_account.html @@ -1,33 +1,147 @@ -<ion-view class="modal slide-in-up ng-enter active ng-enter-active padding"> +<ion-view class="modal slide-in-up ng-enter active ng-enter-active"> <ion-header-bar class="bar-positive"> - <button class="button button-positive icon ion-chevron-left" ng-click="previous()" ng-show="slideIndex > 0"> Back</button> + <button class="button button-positive icon icon-left ion-chevron-left" ng-click="previous()" ng-show="slideIndex > 0" translate>COMMON.BTN_BACK</button> + <button class="button button-positive" ng-click="cancel()" ng-show="slideIndex == 0" translate>COMMON.BTN_CANCEL</button> - <h1 class="title">New account</h1> + <h1 class="title" translate>ACCOUNT.NEW.TITLE</h1> - <button class="button button-positive" ng-click="cancel()">Cancel</button> + <button class="button button-positive button-icon ion-android-send" ng-click="doNewAccount()" ng-show="slideIndex == 2"></button> </ion-nav-buttons> </ion-header-bar> - <ion-slide-box on-slide-changed="slideChanged(index)" id="newAccount"> - <ion-slide> - <ng-include src="'templates/currency/select_currency.html'"></ng-include> - </ion-slide> + + <ion-slide-box on-slide-changed="slideChanged(index)" id="newAccount" class="has-header"> <ion-slide> - <h1>Kind of account:</h1> - <button class="button button-block button-stable icon ion-person" ng-click="selectAccountTypeMember(true)" ng-class="{ selected: accountTypeMember != null && accountTypeMember }">Â Member account</button> - <button class="button button-block button-stable icon ion-card" ng-click="selectAccountTypeMember(false)" ng-class="{ selected: accountTypeMember != null && !accountTypeMember }">Â Wallet account</button> + <div class="padding"> + <ng-include src="'templates/currency/select_currency.html'"></ng-include> + </div> </ion-slide> <ion-slide> - <ng-include src="'templates/wot/lookup.html'"></ng-include> + <div class="padding"> + <h1 translate>ACCOUNT.NEW.SLIDE_2_TITLE</h1> + <button class="button button-block button-stable icon icon-left ion-person" ng-click="selectAccountTypeMember(true)" ng-class="{ selected: accountTypeMember != null && accountTypeMember }" translate>ACCOUNT.NEW.MEMBER_ACCOUNT</button> + <button class="button button-block button-stable icon icon-left ion-card" ng-click="selectAccountTypeMember(false)" ng-class="{ selected: accountTypeMember != null && !accountTypeMember }" translate>ACCOUNT.NEW.WALLET_ACCOUNT</button> + </div> </ion-slide> <ion-slide> - <h3>Any questions?</h3> - <p> - Too bad! - </p> + <form name="accountForm" novalidate="" ng-submit="doNewAccount()"> + <div class="list" + ng-init="setAccountForm(accountForm)"> + + <!-- pseudo --> + <label class="item item-input" + ng-class="{'item-input-error': accountForm.$submitted && accountForm.pseudo.$invalid}"> + <span class="input-label" translate>ACCOUNT.NEW.PSEUDO</span> + <input name="pseudo" type="text" placeholder="{{'ACCOUNT.NEW.PSEUDO_HELP' | translate}}" + ng-model="accountData.pseudo" + ng-minlength="3" + required> + </label> + <div class="form-errors" + ng-if="accountForm.$submitted && accountForm.pseudo.$error" + ng-messages="accountForm.pseudo.$error"> + <div class="form-error" ng-message="required"> + <span translate="ERROR.FIELD_REQUIRED"></span> + </div> + <div class="form-error" ng-message="minlength"> + <span translate="ERROR.FIELD_TOO_SHORT"></span> + </div> + </div> + + <!-- salt --> + <label class="item item-input" + ng-class="{ 'item-input-error': accountForm.$submitted && accountForm.username.$invalid}"> + <span class="input-label" translate>LOGIN.USERNAME</span> + <input name="username" type="text" placeholder="{{'LOGIN.USERNAME_HELP' | translate}}" + ng-model="accountData.username" + ng-minlength="8" + required> + </label> + <div class="form-errors" + ng-show="accountForm.$submitted && accountForm.username.$error" + ng-messages="accountForm.username.$error"> + <div class="form-error" ng-message="required"> + <span translate="ERROR.FIELD_REQUIRED"></span> + </div> + <div class="form-error" ng-message="minlength"> + <span translate="ERROR.FIELD_TOO_SHORT"></span> + </div> + </div> + + <!-- password --> + <label class="item item-input" + ng-class="{ 'item-input-error': accountForm.$submitted && accountForm.password.$invalid}"> + <span class="input-label" translate>LOGIN.PASSWORD</span> + <input name="password" type="password" placeholder="{{'LOGIN.PASSWORD_HELP' | translate}}" + ng-model="accountData.password" + ng-minlength="8" + required> + </label> + <div class="form-errors" + ng-show="accountForm.$submitted && accountForm.password.$error" + ng-messages="accountForm.password.$error"> + <div class="form-error" ng-message="required"> + <span translate="ERROR.FIELD_REQUIRED"></span> + </div> + <div class="form-error" ng-message="minlength"> + <span translate="ERROR.FIELD_TOO_SHORT"></span> + </div> + </div> + + <!-- confirm password --> + <label class="item item-input" + ng-class="{ 'item-input-error': accountForm.$submitted && accountForm.confirmPassword.$invalid}"> + <span class="input-label" translate>ACCOUNT.NEW.PASSWORD_CONFIRM</span> + <input name="confirmPassword" type="password" placeholder="{{'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP' | translate}}" ng-model="accountData.confirmPassword" ng-change="loginDataChanged()" + compare-to="accountData.password"> + </label> + <div class="form-errors" + ng-show="accountForm.$submitted && accountForm.confirmPassword.$error" + ng-messages="accountForm.confirmPassword.$error"> + <div class="form-error" ng-message="required"> + <span translate="ERROR.FIELD_REQUIRED"></span> + </div> + <div class="form-error" ng-message="compareTo"> + <span translate="ERROR.PASSWORD_NOT_CONFIRMED"></span> + </div> + </div> + + <!-- Show public key--> + <div class="item item-icon-left item-button-right"> + <i class="icon ion-key"/> + <span translate>COMMON.PUBKEY</span> + <a class="button button-light button-small" + ng-click="showAccountPubkey()" + ng-if="!accountData.pubkey && accountForm.$valid" + class="animate-if" translate> + COMMON.BTN_SHOW + </a> + <span class="badge badge-energized" ng-if="accountData.pubkey"> + {{accountData.pubkey | formatPubkey}} + </span> + </div> + </div> + + <div class="padding"> + <button class="button button-block button-positive" type="submit"> + {{'COMMON.BTN_OK' | translate}} + </button> + </div> + </form> </ion-slide> </ion-slide-box> </ion-view> + +<script type="text/ng-template" id="error-messages"> + <div class="error" ng-message="required"> + <i class="ion-information-circled"></i> + <div translate="ERROR.FIELD_REQUIRED"></div> + </div> + <div class="error" ng-message="minlength"> + <i class="ion-information-circled"></i> + <div translate="ERROR.FIELD_TOO_SHORT"></div> + </div> +</script> \ No newline at end of file diff --git a/www/templates/account/view_transfer.html b/www/templates/account/view_transfer.html index 1d77a5707ef7a4853161c3461196cfcef3042917..45975b126de39d21161ec9d5377fe9b78c26f8e9 100644 --- a/www/templates/account/view_transfer.html +++ b/www/templates/account/view_transfer.html @@ -1,4 +1,4 @@ -<ion-view view-title="Transfer" left-buttons="leftButtons"> +<ion-view view-title="{{'TRANSFER.TITLE' | translate}}" left-buttons="leftButtons"> <ion-nav-buttons side="secondary"> <button class="button button-positive" ng-click="doTransfer()"> <i class="icon ion-android-send"></i> @@ -10,29 +10,29 @@ <div class="list"> <span class="item item-icon-left"> <i class="icon ion-key"></i> - From + {{'TRANSFER.FROM' | translate}} <span class="badge badge-calm">{{walletData.pubkey.substr(0,8)}}</span> </span> <span class="item item-icon-left item-button-right" ng-click="openSearch()"> <i class="icon ion-person"></i> - To + {{'TRANSFER.TO' | translate}} <span class="badge badge-royal">{{dest}}</span> <i class="button button-clear ion-chevron-right"></i> </span> <div class="item item-input item-floating-label" ng-if="!walletData.useRelative"> - <span class="input-label">Amount ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> - <input type="number" placeholder="Amount ({{unit | abbreviate}}{{udUnit | abbreviate}})" ng-model="formData.amount" > + <span class="input-label">{{'TRANSFER.AMOUNT' | translate}} ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> + <input type="number" placeholder="{{'TRANSFER.AMOUNT_HELP' | translate}} ({{unit | abbreviate}}{{udUnit | abbreviate}})" ng-model="formData.amount" > </div> <div class="item item-input item-floating-label" ng-if="walletData.useRelative"> - <span class="input-label">Amount ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> - <input type="text" placeholder="Amount ({{unit | abbreviate}}{{udUnit | abbreviate}})" ng-model="formData.amount" > + <span class="input-label">{{'TRANSFER.AMOUNT' | translate}} ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> + <input type="text" placeholder="{{'TRANSFER.AMOUNT_HELP' | translate}} ({{unit | abbreviate}}{{udUnit | abbreviate}})" ng-model="formData.amount" > </div> <div class="item item-toggle dark"> - Use Relative Unit (UD) + {{'COMMON.BTN_RELATIVE_UNIT' | translate}} <label class="toggle toggle-royal"> <input type="checkbox" ng-model="walletData.useRelative"> <div class="track"> @@ -42,7 +42,7 @@ </div> <label class="item item-input"> - <textarea placeholder="Comments" ng-model="formData.comments"></textarea> + <textarea placeholder="{{'TRANSFER.COMMENTS_HELP' | translate}}" ng-model="formData.comments"></textarea> </label> </div> diff --git a/www/templates/account/view_wallet.html b/www/templates/account/view_wallet.html index 3b82e5ebbd8095e958f4a35f826de6dbe6364427..7a87eb763b1f16e990c15fb2162b57d36a818b15 100644 --- a/www/templates/account/view_wallet.html +++ b/www/templates/account/view_wallet.html @@ -1,4 +1,4 @@ -<ion-view view-title="My Account" left-buttons="leftButtons"> +<ion-view view-title="{{'ACCOUNT.TITLE' | translate}}" left-buttons="leftButtons"> <ion-content> <div class="scroll"> <div class="list"> @@ -6,24 +6,24 @@ <span class="item item-icon-left" ng-if="isMember"> <i class="icon ion-person"></i> <h2>{{walletData.uid}}</h2> - <p>Public key: {{walletData.pubkey | formatPubkey}}</p> + <p>{{'COMMON.PUBKEY' | translate}}: {{walletData.pubkey | formatPubkey}}</p> </span> <span class="item item-icon-left" ng-if="!isMember"> <i class="icon ion-key"></i> - Public key + {{'COMMON.PUBKEY' | translate}} <span class="badge">{{walletData.pubkey | formatPubkey}}</span> </span> <span class="item item-icon-left"> <i class="icon ion-card"></i> - Balance + {{'ACCOUNT.BALANCE' | translate}} <span class="badge badge-balanced" ng-if="!walletData.useRelative">{{convertedBalance | formatInteger}} {{unit | abbreviate}}</span> <span class="badge badge-balanced" ng-if="walletData.useRelative">{{convertedBalance | formatDecimal}} {{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub></span> </span> <div class="item item-toggle dark"> - Use Relative Unit (UD) + {{'COMMON.BTN_RELATIVE_UNIT' | translate}} <label class="toggle toggle-royal"> <input type="checkbox" ng-model="walletData.useRelative"> <div class="track"> @@ -37,14 +37,14 @@ </div> <div class="item item-button-right positive" ng-if="hasCredit" ng-click="transfer()"> - Send money + {{'ACCOUNT.BTN_SEND_MONEY' | translate}} <a class="button button-clear button-positive" > <i class="icon-right ion-chevron-right"></i> </a> </div> <div class="item item-button-right positive" ng-if="!isMember" ng-click="self()"> - Send self certification + {{'ACCOUNT.BTN_REGISTER' | translate}} <a class="button button-clear button-positive" > <i class="icon-right ion-chevron-right"></i> </a> @@ -55,12 +55,12 @@ </div> <div class="item item-divider"> - Last transactions + {{'ACCOUNT.LAST_TX' | translate}} </div> <a href="#" class="item" ng-repeat="tx in walletData.history" ng-if="walletData.history"> <h3>{{tx.time | formatDate}}</h3> - <p ng-if="tx.issuer">pubkey: {{tx.issuer | formatPubkey}}</p> + <p ng-if="tx.issuer">{{'COMMON.PUBKEY' | translate}}: {{tx.issuer | formatPubkey}}</p> <span class="badge item-note" ng-if="!walletData.useRelative">{{tx.amount | formatInteger}}</span> <span class="badge item-note" ng-if="walletData.useRelative">{{tx.amount/walletData.currentUD | formatDecimal}}</span> </a> diff --git a/www/templates/currency/select_currency.html b/www/templates/currency/select_currency.html index 088b1c1497b5bb9a7353f16a3d98dae58ec8a29d..6d2fd691a7ae534142b3bb81e6336519541a8d45 100644 --- a/www/templates/currency/select_currency.html +++ b/www/templates/currency/select_currency.html @@ -1,6 +1,6 @@ <div class="card"> <div class="item item-divider"> - Known currencies + {{'CURRENCY.SELECT.CURRENCIES' | translate}} </div> <a class="item item-text-wrap" ng-repeat="currency in knownCurrencies" ng-click="selectCurrency(currency)" ng-class="{ selected: selectedCurrency == currency }"> {{currency}} diff --git a/www/templates/explore/explore_currency.html b/www/templates/explore/explore_currency.html index a7fc8930ae80bd79c46645762084eec4706f48c8..a0c9b0bf97dcf9400f2300bb5640200a747a287e 100644 --- a/www/templates/explore/explore_currency.html +++ b/www/templates/explore/explore_currency.html @@ -1,4 +1,4 @@ -<ion-view view-title="Explore"> +<ion-view view-title="{{'CURRENCY.SELECT.TITLE' | translate}}"> <ion-content> <ng-include src="'templates/currency/select_currency.html'"/> </ion-content> diff --git a/www/templates/explore/explore_tabs.html b/www/templates/explore/explore_tabs.html index bc95075abd4f4052bcec0d3a16070fb6b12f41ce..05819a7a9072f33cf456dd1ee52cc79d56dc1302 100644 --- a/www/templates/explore/explore_tabs.html +++ b/www/templates/explore/explore_tabs.html @@ -1,4 +1,4 @@ -<ion-view view-title="Explore" left-buttons="leftButtons"> +<ion-view view-title="{{'CURRENCY.VIEW.TITLE' | translate}}" left-buttons="leftButtons"> <ion-nav-buttons side="secondary"> <button class="button button-icon" ng-click="doUpdate()"> <i class="icon ion-loop"></i> @@ -7,17 +7,17 @@ <div class="scroll"> <ion-tabs class="tabs-icon-top tabs-positive has-header"> - <ion-tab title="Currency" icon="ion-stats-bars"> + <ion-tab title="{{'CURRENCY.VIEW.TAB_CURRENCY'|translate}}" icon="ion-stats-bars"> <ion-nav-view name="currency-tab"/> <ng-include src="'templates/explore/tabs/explore_tab_currency.html'"/> </ion-tab> - <ion-tab title="Web of Trust" icon="ion-ios-world-outline"> + <ion-tab title="{{'CURRENCY.VIEW.TAB_WOT'|translate}}" icon="ion-person-stalker"> <ion-nav-view name="wot-tab"/> <ng-include src="'templates/explore/tabs/explore_tab_wot.html'"/> </ion-tab> - <ion-tab title="Network" icon="ion-network"> + <ion-tab title="{{'CURRENCY.VIEW.TAB_NETWORK'|translate}}" icon="ion-network"> <ion-nav-view name="network-tab"/> <ng-include src="'templates/explore/tabs/explore_tab_network.html'"/> </ion-tab> diff --git a/www/templates/explore/tabs/explore_tab_currency.html b/www/templates/explore/tabs/explore_tab_currency.html index 9ed81dac17cb48f75573c6f3d669c308a5b7385c..52e128e8a9fed876bb88d83b894e3c524e255d70 100644 --- a/www/templates/explore/tabs/explore_tab_currency.html +++ b/www/templates/explore/tabs/explore_tab_currency.html @@ -3,54 +3,54 @@ <a href="#" class="item item-icon-left"> <i class="icon ion-android-bookmark"></i> - Currency name + <span translate>CURRENCY.VIEW.CURRENCY_NAME</span> <span class="item-note">{{selectedCurrency}} meta_brouzouf ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> </a> <a class="item item-icon-left" href="#"> <i class="icon ion-person-stalker"></i> - Members + <span translate>CURRENCY.VIEW.MEMBERS</span> <span class="badge badge-assertive">{{Nprev | formatInteger}}</span> </a> <a class="item item-icon-left" href="#"> <i class="icon ion-person-add"></i> - Incoming members + <span translate>CURRENCY.VIEW.INCOMING_MEMBERS</span> <span ng-if="N > Nprev" class="badge badge-balanced">+{{N-Nprev | formatInteger}}</span> <span ng-if="N < Nprev" class="badge badge-calm">-{{N-Nprev | formatInteger}}</span> <span ng-if="N == Nprev" class="badge badge-stable">{{0}}</span> </a> <div class="item item-divider"> - Money + <span translate>CURRENCY.VIEW.MONEY_DIVIDER</span> </div> <a class="item item-icon-left" href="#"> <i class="icon ion-record"></i> - Monetary mass + <span translate>CURRENCY.VIEW.MASS</span> <span class="badge badge-stable">{{M | formatInteger}} {{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub></span> </a> <a class="item item-icon-left" href="#"> <i class="icon ion-pie-graph"></i> - Money share + {{'CURRENCY.VIEW.SHARE'|translate}} <span class="badge badge-energized">{{MoverN | formatInteger}} {{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</span> </a> <a class="item item-icon-left" href="#"> <i class="icon ion-load-c"></i> - Universal Dividend + <span translate>CURRENCY.VIEW.UD</span> <span class="badge badge-royal">{{UD | formatInteger}} {{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</span> </a> <a class="item item-icon-left" href="#"> <i class="icon ion-arrow-graph-up-right"></i> - c<sub>actual</sub> + <span translate>CURRENCY.VIEW.C_ACTUAL</span> <span class="badge badge-stable">{{cactual | formatInteger}} %</span> </a> <div class="item item-toggle dark"> - Use Relative Units (UD) + <span translate>COMMON.BTN_RELATIVE_UNIT</span> <label class="toggle toggle-royal"> <input type="checkbox" ng-model="formData.useRelative"> <div class="track"> @@ -60,34 +60,34 @@ </div> <div class="item item-divider"> - Blockchain + <span translate>CURRENCY.VIEW.BLOCKCHAIN_DIVIDER</span> </div> <a class="item item-icon-left" href="#"> <i class="icon ion-clock"></i> - Current time + <span translate>CURRENCY.VIEW.TIME</span> <span class="item-note">{{time}}</span> </a> <a class="item item-icon-left" href="#"> <i class="icon ion-lock-combination"></i> - Common difficulty + <span translate>CURRENCY.VIEW.POW_MIN</span> <span class="badge badge-stable">{{difficulty | formatInteger}}</span> </a> <div class="item item-divider"> - Rules + <span translate>CURRENCY.VIEW.RULES_DIVIDER</span> </div> <a class="item item-icon-left" href="#"> <i class="icon ion-arrow-graph-up-right"></i> - c + <span translate>CURRENCY.VIEW.C_RULE</span> <span class="badge badge-stable">{{c*100 | formatInteger}}%</span> </a> <a class="item item-icon-left" href="#"> <i class="icon ion-load-c"></i> - Universal Dividend + <span translate>CURRENCY.VIEW.UD</span> <span class="item-note">MAX(UD<sub>t-1</sub>, c*M/N)</span> </a> </div> diff --git a/www/templates/explore/tabs/explore_tab_network.html b/www/templates/explore/tabs/explore_tab_network.html index 037560a65c481ef4b94e77257a8af7607f9ff55e..ada8aec455d010a7803e8934e423d6b2d26b5f96 100644 --- a/www/templates/explore/tabs/explore_tab_network.html +++ b/www/templates/explore/tabs/explore_tab_network.html @@ -3,7 +3,7 @@ <div class="list"> <div class="item item-divider item-icon-right"> - Peers + {{'PEER.PEERS'|translate}} <ion-spinner class="icon" icon="android" ng-if="search.lookingForPeers"></ion-spinner> </div> diff --git a/www/templates/explore/view_peer.html b/www/templates/explore/view_peer.html index d89b48632b865eeef891d347a05fecc32c7b0a8c..bed9943b660af36e5064ad6200b76af7b440ce17 100644 --- a/www/templates/explore/view_peer.html +++ b/www/templates/explore/view_peer.html @@ -3,7 +3,7 @@ <div class="list"> <div class="item item-divider"> - <h2>Known peers</h2> + <h2 translate>PEER.KNOWN_PEERS</h2> </div> <div class="item center" ng-if="!loaded"> @@ -16,7 +16,7 @@ ng-href="http://{{peer.getURL()}}/blockchain/current"> <i class="icon ion-android-globe"></i> <h3><span ng-class="{ positive: peer.uid }">{{peer.uid || peer.pubkey.substr(0,8)}}</span> <span class="light">{{peer.dns && ' | ' + peer.dns}}</span></h3> - <h4>{{peer.getURL()}} <span class="light">| Signed on block</span> #{{peer.blockNumber}}</h4> + <h4>{{peer.getURL()}} <span class="light">| {{'PEER.SIGNED_ON_BLOCK' | translate}}</span> #{{peer.blockNumber}}</h4> <span class="badge" ng-class="{ 'badge-balanced': peer.hasMainConsensusBlock, 'badge-energized': peer.hasConsensusBlock }">{{peer.current.number}}</span> </a> </div> diff --git a/www/templates/home.html b/www/templates/home.html index ad1ab233b739a218d832e6ddb6a4d7c40672e008..7e67c7c8f8c4f0960df49f407d63bd0a585ed54d 100644 --- a/www/templates/home.html +++ b/www/templates/home.html @@ -1,4 +1,4 @@ -<ion-view view-title="Home"> +<ion-view view-title="{{'HOME.TITLE'|translate}}"> <ion-content class="has-header padding" id="home"> <!-- <div class="card" ng-show="!isLogged()"> @@ -10,13 +10,19 @@ </div> --> - <h1>Welcome.</h1> - <h2><b>Cesium</b> is still in development phase. There is not much to see right now. :-)</h2> + <h1 translate>HOME.WELCOME</h1> + <h2 translate>HOME.MESSAGE</h2> - <a ui-sref="app.explore_currency" class="button button-block button-stable icon icon-left ion-search">Explore a currency</a> - - <button ng-click="login()" ng-show="!isLogged()" class="button button-block button-positive icon icon-left ion-log-in">Login</button> - <!-- <button ng-click="addAccount()" ng-show="!isLogged()" class="button button-block button-assertive icon icon-left ion-ios-color-wand">Add an account</button> --> + <a ui-sref="app.explore_currency" class="button button-block button-stable icon icon-left ion-ios-world-outline" translate>HOME.BTN_CURRENCIES</a> + <div class="row"> + <div class="col"> + <button ng-click="login()" ng-show="!isLogged()" class="button button-block button-positive icon icon-left ion-log-in" translate>COMMON.BTN_LOGIN</button> + </div> + <div class="col"> + <button ng-click="newAccount()" ng-show="!isLogged()" class="button button-block button-assertive icon icon-left ion-ios-color-wand" translate>COMMON.BTN_ADD_ACCOUNT</button> + </div> + </div> </ion-content> + </ion-view> diff --git a/www/templates/login.html b/www/templates/login.html index 95910a238be68e57cf4825bb43031fe702bc376e..632523cd7d4b7d115a5e3f063a1159252ae43762 100644 --- a/www/templates/login.html +++ b/www/templates/login.html @@ -1,32 +1,58 @@ <ion-modal-view> <ion-header-bar class="bar-positive"> - <button class="button button-positive" ng-click="closeLogin()">Cancel - </button> - <h1 class="title">Login</h1> - <button class="button button-positive" ng-click="doLogin()">OK + <button class="button button-positive" ng-click="cancelLogin()" translate>COMMON.BTN_CANCEL </button> + <h1 class="title" translate>LOGIN.TITLE</h1> + <button class="button button-positive button-icon ion-android-done" ng-click="doLogin()"></button> </ion-header-bar> <ion-content scroll="false"> - <form ng-submit="doLogin()"> - <div class="list"> - <label class="item item-input item-floating-label"> - <span class="input-label">Username</span> - <input type="text" placeholder="Username" ng-model="loginData.username" ng-change="loginDataChanged()"> + <form name="loginForm" novalidate="" ng-submit="doLogin()"> + <div class="list" + ng-init="setLoginForm(loginForm)"> + + <!-- username --> + <label class="item item-input" + ng-class="{ 'item-input-error': loginForm.$submitted && loginForm.username.$invalid}"> + <span class="input-label" translate>LOGIN.USERNAME</span> + <input name="username" type="text" placeholder="{{'LOGIN.USERNAME_HELP' | translate}}" + ng-model="loginData.username" + ng-change="loginDataChanged()" + required> </label> - <label class="item item-input item-floating-label"> - <span class="input-label">Password</span> - <input type="password" placeholder="Password" ng-model="loginData.password" ng-change="loginDataChanged()"> + <div class="form-errors" + ng-show="loginForm.$submitted && loginForm.username.$error" + ng-messages="loginForm.username.$error"> + <div class="form-error" ng-message="required"> + <span translate="ERROR.FIELD_REQUIRED"></span> + </div> + </div> + + <!-- password--> + <label class="item item-input" + ng-class="{ 'item-input-error': loginForm.$submitted && loginForm.password.$invalid}"> + <span class="input-label" translate>LOGIN.PASSWORD</span> + <input name="password" type="password" placeholder="{{'LOGIN.PASSWORD_HELP' | translate}}" + ng-model="loginData.password" + ng-change="loginDataChanged()" + required> </label> + <div class="form-errors" + ng-show="loginForm.$submitted && loginForm.password.$error" + ng-messages="loginForm.password.$error"> + <div class="form-error" ng-message="required"> + <span translate="ERROR.FIELD_REQUIRED"></span> + </div> + </div> + + <!-- show public key --> <div class="item item-icon-left item-button-right"> <i class="icon ion-key"/> - Public key + <span translate>COMMON.PUBKEY</span> <a class="button button-light button-small" ng-click="showLoginPubkey()" ng-if="!(loginData.pubkey || loginData.computing || !loginData.username || !loginData.password)" class="animate-if"> - Show - </a> - </label> - + {{'COMMON.BTN_SHOW' | translate}} + </a> <span class="badge badge-energized" ng-if="loginData.pubkey"> {{loginData.pubkey | formatPubkey}} </span> @@ -34,7 +60,7 @@ </div> <div class="padding"> <button class="button button-block button-positive" type="submit"> - OK + {{'COMMON.BTN_OK' | translate}} </button> </div> </form> diff --git a/www/templates/menu.html b/www/templates/menu.html index 5e165b92c2606175fff7a9447007b0929d4e34c8..63cb9d4d0394a3eb939796fbca48fae486a06c33 100644 --- a/www/templates/menu.html +++ b/www/templates/menu.html @@ -3,27 +3,27 @@ <!-- MENU --> <ion-side-menu side="left"> <ion-header-bar class="bar-royal"> - <h1 class="title"> - Cesium + <h1 class="title" translate> + MENU.TITLE </h1> <button class="button button-assertive" ng-click="logout()" ng-if="isLogged()"> <i class="icon ion-log-out"></i> - Logout - </button> + <span translate>COMMON.BTN_LOGOUT</span> + </button> </ion-header-bar> <ion-content scroll="false"> <ion-item menu-close href="#/app/home"> - Home + <span translate>MENU.HOME</span> </ion-item> - <ion-item menu-close href="#/app/home/explore"> - Explore + <ion-item menu-close href="#/app/currency"> + <span translate>MENU.CURRENCIES</span> </ion-item> <ion-item menu-close ng-click="login()" ng-if="!isLogged()"> - My account + <span translate>MENU.ACCOUNT</span> </ion-item> <ion-item menu-close href="#" ui-sref="app.view_wallet" ng-if="isLogged()"> - My account + <span translate>MENU.ACCOUNT</span> </ion-item> <!-- <ion-item menu-close ng-click="addAccount()"> Add account @@ -36,7 +36,7 @@ <ion-side-menu-content> <ion-nav-bar class="bar-stable"> <ion-nav-back-button> - Back + {{'COMMON.BTN_BACK'|translate}} </ion-nav-back-button> <ion-nav-buttons side="left"> diff --git a/www/templates/wot/lookup.html b/www/templates/wot/lookup.html index d3f0df7ef377b15e0b03a095280b86fbd09dd421..5f657b3a81d6bda61d916168b95588f402a5af58 100644 --- a/www/templates/wot/lookup.html +++ b/www/templates/wot/lookup.html @@ -2,7 +2,7 @@ <div class="list list-inset"> <label class="item item-input"> <i class="icon ion-search placeholder-icon"></i> - <input type="text" placeholder="Search" ng-model="search.text" ng-change="searchChanged()"> + <input type="text" placeholder="{{'WOT.SEARCH_HELP'|translate}}" ng-model="search.text" ng-change="searchChanged()"> </label> <label class="item center" ng-if="search.looking"> @@ -12,7 +12,7 @@ <a class="item item-icon-left" ng-repeat="found in search.results" ng-click="doSelectIdentity('{{found.pub}}', '{{found.uid}}')"> <i class="icon ion-person"></i> <h2>{{found.uid}}</h2> - <p>pubkey: {{found.pub | formatPubkey}}</p> + <p><span translate>COMMON.PUBKEY</span>: {{found.pub | formatPubkey}}</p> <span class="badge item-note">{{found.sigDate | formatDate}}</span> </a> </div> diff --git a/www/templates/wot/modal_lookup.html b/www/templates/wot/modal_lookup.html index 9c5c2d912b554b57973217a552f4b6817851eb86..f8e9db03bce1507c8c2e0095c39e4ec0c9b95d82 100644 --- a/www/templates/wot/modal_lookup.html +++ b/www/templates/wot/modal_lookup.html @@ -1,14 +1,14 @@ <ion-modal-view> <ion-header-bar class="bar-positive"> - <h1 class="title">Search</h1> - <button class="button button-positive" ng-click="closeLookup()">Cancel</button> + <h1 class="title" translate>WOT.MODAL.TITLE</h1> + <button class="button button-positive" ng-click="closeLookup()" translate>COMMON.BTN_CANCEL</button> </ion-header-bar> <ion-content class="lookupForm"> <div class="list"> <label class="item item-input"> <i class="icon ion-search placeholder-icon"></i> - <input type="text" placeholder="Search" ng-model="search.text" ng-change="searchChanged()"> + <input type="text" placeholder="{{'WOT.SEARCH_HELP'|translate}}" ng-model="search.text" ng-change="searchChanged()"> </label> <label class="item center" ng-if="search.looking"> @@ -18,7 +18,7 @@ <a class="item item-icon-left" ng-repeat="found in search.results" ng-click="doSelectIdentity('{{found.pub}}', '{{found.uid}}')"> <i class="icon ion-person"></i> <h2>{{found.uid}}</h2> - <p>pubkey: {{found.pub.substr(0,24)}}</p> + <p>{{'COMMON.PUBKEY'|translate}}: {{found.pub.substr(0,24)}}</p> <span class="badge item-note">{{found.sigDate | formatDate}}</span> </a> </div>