diff --git a/www/api/index.html b/www/api/index.html new file mode 100644 index 0000000000000000000000000000000000000000..0b0f2f6268eb862c8b1d1c9c6a3500b866d4d0c0 --- /dev/null +++ b/www/api/index.html @@ -0,0 +1,116 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, width=device-width, minimal-ui"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <title>Cesium API</title> + <link rel="icon" href="../img/favicon.ico"> + + <!-- build:css dist_css/cesium.css --> + <link rel="stylesheet" type="text/css" href="../css/ionic.app.min.css"> + <link rel="stylesheet" type="text/css" href="../css/style.css"> + <link rel="stylesheet" type="text/css" href="../css/angular-image-crop.css"> + <!--removeIf(device)--> + <link rel="stylesheet" type="text/css" href="../css/style-no-device.css"> + <!--endRemoveIf(device)--> + <!-- endbuild --> + +</head> +</head> +<body ng-app="cesium-api" id="cesium-api" ng-strict-di="true"> +<ion-nav-view> + <h3 style="text-align: center; padding-top: 25px; "><b>Cesium API</b></h3> + <h4 style="text-align: center;">Loading...</h4> +</ion-nav-view> + +<!-- build:js dist_js/vendor.js --> +<!-- vendor js --> +<script src="../js/vendor/moment.min.js"></script> +<script src="../js/vendor/moment.fr.js"></script> +<script src="../js/vendor/moment.nl.js"></script> +<script src="../js/vendor/moment.es.js"></script> +<script src="../js/vendor/numeral.js"></script> +<script src="../js/vendor/numeral.fr.js"></script> +<script src="../js/vendor/numeral.en.js"></script> +<script src="../js/vendor/numeral.nl.js"></script> +<script src="../js/vendor/numeral.es.js"></script> +<script src="../js/vendor/socket-io.js"></script> +<script src="../js/vendor/underscore.js"></script> + +<!-- ionic/angularjs js --> +<script src="../lib/ionic/js/ionic.bundle.js"></script> +<script src="../lib/ionic/js/ionic.material.js"></script> +<script src="../lib/ionic/js/angular/angular-resource.js"></script> +<script src="../lib/ionic/js/angular/angular-translate.js"></script> +<script src="../lib/ionic/js/angular/angular-messages.js"></script> +<script src="../lib/ionic/js/angular/angular-api.js"></script> +<script src="../lib/ionic/js/angular/angular-cache.js"></script> +<script src="../lib/ionic/js/angular/angular-screenmatch.min.js"></script> +<script src="../lib/ionic/js/angular/angular-bind-notifier.min.js"></script> +<script src="../lib/ionic/js/angular/angular-file-saver.bundle.js"></script> +<script src="../lib/ionic/js/angular/angular-idle.js"></script> + + <script src="../js/vendor/base58.js" async></script> + <!--removeIf(android)--> + <!--removeIf(ios)--> + <script src="../js/vendor/nacl_factory.js" async></script> + <script src="../js/vendor/scrypt-em.js" async></script> + <script src="../js/vendor/base64.js" async></script> + <!--endRemoveIf(ios)--> + <!--endRemoveIf(android)--> + <!--removeIf(no-device)--> + <script src="../js/vendor/sha256.min.js" async></script> + <script src="../js/vendor/ng-cordova.min.js"></script> + <!--endRemoveIf(no-device)--> + +<!-- endbuild --> + +<!--removeIf(no-device)--> +<script src="../cordova.js"></script> +<!--endRemoveIf(no-device)--> + +<!-- build:js dist_js/cesium.js --> +<!-- services --> +<script src="../dist/dist_js/app/services/settings-services.js"></script> +<script src="../dist/dist_js/app/services/network-services.js"></script> +<script src="../dist/dist_js/app/services/crypto-services.js"></script> +<script src="../dist/dist_js/app/services/utils-services.js"></script> +<script src="../dist/dist_js/app/services/cache-services.js"></script> +<script src="../dist/dist_js/app/services/modal-services.js"></script> +<script src="../dist/dist_js/app/services/http-services.js"></script> +<script src="../dist/dist_js/app/services/storage-services.js"></script> +<script src="../dist/dist_js/app/services/device-services.js"></script> +<script src="../dist/dist_js/app/services/currency-services.js"></script> +<script src="../dist/dist_js/app/services/bma-services.js"></script> +<script src="../dist/dist_js/app/services/wot-services.js"></script> +<script src="../dist/dist_js/app/services/tx-services.js"></script> +<script src="../dist/dist_js/app/services/wallet-services.js"></script> +<script src="../dist/dist_js/app/services/plugin-services.js"></script> +<script src="../dist/dist_js/app/services.js"></script> + +<!-- entities --> +<script src="../dist/dist_js/app/entities/peer.js"></script> +<script src="../dist/dist_js/app/entities/block.js"></script> + +<!-- controllers --> +<script src="../dist/dist_js/app/controllers/login-controllers.js"></script> +<script src="../dist/dist_js/app/controllers/help-controllers.js"></script> + +<!-- templates --> +<script src="../dist/dist_js/app/templates.js"></script> +<script src="../dist/dist_js/app/translations.js"></script> + +<!-- App --> +<script src="../dist/dist_js/app/api/app.js"></script> +<script src="../dist/dist_js/app/directives.js"></script> +<script src="../dist/dist_js/app/filters.js"></script> +<script src="../dist/dist_js/app/platform.js"></script> +<!-- endbuild --> + +<!-- build:js config.js --> +<!-- config --> +<script src="../dist/dist_js/app/config.js"></script> +<!-- endbuild --> +</body> +</html> diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json index 142bc212fa329a76c28f16465dc61266df08eff2..ecf9836d30558c12ebc5c8d3d9ab6f92e26d436c 100644 --- a/www/i18n/locale-fr-FR.json +++ b/www/i18n/locale-fr-FR.json @@ -763,5 +763,49 @@ "END_LOGIN": "Cette visite guidée est <b>terminée</b> !<br/><br/>Bonne continuation à vous, dans le nouveau monde de l'<b>économie libre</b> !", "END_NOT_LOGIN": "Cette visite guidée est <b>terminée</b> !<br/><br/>Si vous souhaitez rejoindre la monnaie {{currency|capitalize}}, il vous suffira de cliquer sur <b>{{'LOGIN.CREATE_ACCOUNT'|translate}}</b> ci-dessous." } + }, + "API" :{ + "COMMON": { + "LINK_DOC": "documentation API", + "LINK_DOC_HELP": "Documentation pour les développeurs" + }, + "HOME": { + "TITLE": "Documentation API {{'COMMON.APP_NAME'|translate}}", + "MESSAGE": "Bienvenue dans la <b>documentation de l'API</b> {{'COMMON.APP_NAME'|translate}}.<br/>Connecter vos sites web à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", + "MESSAGE_SHORT": "Connecter vos sites à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", + "DOC_HEADER": "Services disponibles :" + }, + "TRANSFER": { + "TITLE": "{{'COMMON.APP_NAME'|translate}} - Paiement en ligne", + "TITLE_SHORT": "Paiement en ligne", + "SUMMARY": "Récapitulatif de la commande :", + "AMOUNT": "Montant :", + "NAME": "Destinataire :", + "PUBKEY": "Clé publique du destinaire :", + "COMMENT": "Référence de la commande :", + "ERROR": { + "TRANSFER_FAILED": "Echec du paiement" + } + }, + "DOC": { + "BTN_DEMO": "Démo", + "DESCRIPTION_DIVIDER": "Description", + "URL_DIVIDER": "URL d'accès", + "PARAMETERS_DIVIDER": "Options", + "AVAILABLE_PARAMETERS": "Voici la liste des options possibles :", + "SUCCEED": "<i class=\"icon ion-checkmark\"></i> Succès !", + "CANCELLED": "<i class=\"icon ion-close\"></i> Annulé par l'utilisateur", + "RESULT": "Résultat retourné par l'appel :", + "TRANSFER": { + "TITLE": "Paiements", + "DESCRIPTION": "Depuis un site (ex: vente en ligne) vous pouvez déléguer le paiement en monnaie libre à Cesium API. Pour cela, il vous suffit de déclencher l'ouveture d'un page sur l'adresse suivante :", + "PARAM_AMOUNT": "Montant", + "PARAM_AMOUNT_HELP": "Montant de la transaction (obligatoire)", + "PARAM_COMMENT_HELP": "Référence ou commentaire. Vous permettra par exemple d'identifier le paiement dans la BlockChain.", + "PARAM_NAME_HELP": "Le nom de votre site. Cela peut-etre un nom lisible (\"Mon site en ligne\"), ou encore une pseudo-adresse web (\"MonSite.com\").", + "PARAM_REDIRECT_URL_HELP": "URL de redirection", + "PARAM_CANCEL_URL_HELP": "URL en cas d'annulation" + } + } } } diff --git a/www/index.html b/www/index.html index 5d663eff96de0979b17fcdf2287f45b46a4737e8..d9df6c449fd429cb1f432a2013a49046f324482e 100644 --- a/www/index.html +++ b/www/index.html @@ -27,10 +27,13 @@ </head> </head> <body ng-app="cesium" id="cesium" ng-strict-di="true" window-exit-unauth="true" + ng-class="{'nobackdrop': $root.tour, 'expert-mode': $root.settings.expertMode}"> <ion-nav-view> - <h3 style="text-align: center; padding-top: 25px; "><b>Cesium</b></h3> - <h4 style="text-align: center;">Chargement / Sobreprima / Loading...</h4> + <div class="loader"> + <h3 style="text-align: center; padding-top: 25px; "><b>Cesium</b></h3> + <h4 style="text-align: center;"><i class="icon ion-load-a"></i></h4> + </div> </ion-nav-view> <!-- build:js dist_js/vendor.js --> diff --git a/www/js/api/app.js b/www/js/api/app.js new file mode 100644 index 0000000000000000000000000000000000000000..255c378407f10b73a358ecc071a8f9a5ef11742f --- /dev/null +++ b/www/js/api/app.js @@ -0,0 +1,239 @@ +// Ionic Starter App + +// angular.module is a global place for creating, registering and retrieving Angular modules +// '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-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht.translate', 'ngApi', 'angular-cache', 'angular.screenmatch', + // removeIf(no-device) + 'ngCordova', + // endRemoveIf(no-device) + 'cesium.filters', 'cesium.config', 'cesium.platform', 'cesium.templates', 'cesium.translations', 'cesium.directives', + // API dependencies : + 'cesium.services', 'cesium.login.controllers', 'cesium.help.controllers' +]) + + .config(function($stateProvider, $urlRouterProvider) { + 'ngInject'; + $stateProvider + + .state('app', { + url: "/app", + abstract: true, + templateUrl: "templates/api/menu.html", + controller: 'ApiCtrl' + }) + + .state('app.home', { + url: "/home?result&service&cancel", + views: { + 'menuContent': { + templateUrl: "templates/api/home.html", + controller: 'ApiDocCtrl' + } + } + }) + + .state('api', { + url: "/v1", + abstract: true, + templateUrl: "templates/api/menu.html", + controller: 'ApiCtrl' + }) + + .state('api.transfer', { + url: "/payment/:pubkey?name&amount&udAmount&comment&redirect_url&cancel_url&demo", + views: { + 'menuContent': { + templateUrl: "templates/api/transfer.html", + controller: 'ApiTransferCtrl' + } + } + }); + + // if none of the above states are matched, use this as the fallback + $urlRouterProvider.otherwise('/app/home'); + }) + + .controller('ApiCtrl', function ($scope, $state, Modals){ + 'ngInject'; + + + $scope.showAboutModal = function(e) { + e.preventDefault(); // avoid to open link href + Modals.showAbout(); + }; + + $scope.showHome = function() { + $state.go('app.home') ; + }; + }) + + .controller('ApiDocCtrl', function ($scope, $rootScope){ + 'ngInject'; + + $scope.transferData = { + demo: true, + amount: 100, + comment: 'REF-0111', + name: 'mon-site.com', + pubkey: 'G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU', + redirect_url: $rootScope.rootPath + '#/app/home?result={comment}&service=payment', + cancel_url: $rootScope.rootPath + '#/app/home?cancel&service=payment' + }; + $scope.result = {}; + + $scope.enter = function(e, state) { + $scope.result = {}; + if (state.stateParams && state.stateParams.service) { + $scope.result.type = state.stateParams.service; + } + if (state.stateParams && state.stateParams.result) { + $scope.result.content = state.stateParams.result; + } + if (state.stateParams && state.stateParams.cancel) { + $scope.result.cancelled = true; + } + }; + $scope.$on('$ionicView.enter', $scope.enter); + + }) + + .controller('ApiTransferCtrl', function ($scope, $rootScope, $timeout, $controller, $state, $q, $translate, $filter, + BMA, UIUtils, csCurrency, csTx, csWallet){ + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('AuthCtrl', {$scope: $scope})); + + $scope.loading = true; + $scope.transferData = { + amount: undefined, + comment: undefined, + pubkey: undefined, + name: undefined, + redirect_url: undefined, + cancel_url: undefined + }; + + $scope.enter = function(e, state) { + if (state.stateParams && state.stateParams.amount) { + $scope.transferData.amount = parseFloat(state.stateParams.amount.replace(new RegExp('[.,]'), '.')).toFixed(2) * 100; + } + if (state.stateParams && state.stateParams.pubkey) { + $scope.transferData.pubkey = state.stateParams.pubkey; + } + if (state.stateParams && state.stateParams.name) { + $scope.transferData.name= state.stateParams.name; + } + if (state.stateParams && state.stateParams.comment) { + $scope.transferData.comment = state.stateParams.comment; + } + if (state.stateParams && state.stateParams.redirect_url) { + $scope.transferData.redirect_url = state.stateParams.redirect_url; + } + if (state.stateParams && state.stateParams.cancel_url) { + $scope.transferData.cancel_url = state.stateParams.cancel_url; + } + if (state.stateParams && state.stateParams.demo) { + $scope.demo = true; + } + }; + $scope.$on('$ionicView.enter', $scope.enter); + + function createDemoWallet() { + return { + start: function() { + return $q.when(); + }, + login: function() { + return $q.when({ + uid: 'Demo', + pubkey: 'fakeDemoPublicKey' + }); + }, + transfer: function() { + return $q.when(); + } + }; + } + + function onLogin(authData) { + if (!authData) return; + + var wallet = $scope.demo ? createDemoWallet() : csWallet.instance('api', BMA); + + UIUtils.loading.show(); + + wallet.start({skipRestore: true}) + .then(function() { + return wallet.login({auth: true, authData: authData}); + }) + .then(function(walletData) { + $scope.login = true; + + UIUtils.loading.hide(); + return $scope.askTransferConfirm(walletData); + }) + .then(function(confirm) { + if (!confirm) return; + // sent transfer + return UIUtils.loading.show() + .then(function(){ + var amount = parseInt($scope.transferData.amount); // remove 2 decimals on quantitative mode + return wallet.transfer($scope.transferData.pubkey, amount, $scope.transferData.comment, false /*always quantitative mode*/); + }) + .then(function() { + UIUtils.loading.hide(); + return true; // sent + }) + .catch(UIUtils.onError('API.TRANSFER.ERROR.TRANSFER_FAILED')); + }) + .then(function(sent) { + if (sent && $scope.transferData.redirect_url) { + return $timeout(function () { + // if iframe: send to parent + if (window.top && window.top.location) { + window.top.location.href = $scope.transferData.redirect_url; + } + else if (parent && parent.document && parent.document.location) { + parent.document.location.href = $scope.transferData.redirect_url; + } + else { + window.location.assign($scope.transferData.redirect_url); + } + }, 3000); + } + }); + } + + + $scope.askTransferConfirm = function(walletData) { + return $translate(['COMMON.UD', 'COMMON.EMPTY_PARENTHESIS']) + .then(function(translations) { + return $translate('CONFIRM.TRANSFER', { + from: walletData.isMember ? walletData.uid : $filter('formatPubkey')(walletData.pubkey), + to: $scope.transferData.name || $filter('formatPubkey')($scope.transferData.pubkey), + amount: $scope.transferData.amount / 100, + unit: $filter('abbreviate')($rootScope.currency.name), + comment: (!$scope.transferData.comment || $scope.transferData.comment.trim().length === 0) ? translations['COMMON.EMPTY_PARENTHESIS'] : $scope.transferData.comment + }); + }) + .then(UIUtils.alert.confirm); + }; + + /* -- methods need by Login controller -- */ + + $scope.setForm = function(form) { + $scope.form = form; + }; + $scope.closeModal = onLogin; + + }) + + .run(function(csPlatform) { + 'ngInject'; + + csPlatform.start(); + }) +; diff --git a/www/js/app.js b/www/js/app.js index 6b52789d4e34b48fb4c896995d8fd3f6929ea8af..283c61b7ca7ba7c839d8c96909b560f092e78cb8 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -12,80 +12,9 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht // removeIf(no-plugin) 'cesium.plugins', // endRemoveIf(no-plugin) - 'cesium.filters', 'cesium.config', 'cesium.platform', 'cesium.controllers', 'cesium.templates', 'cesium.translations' + 'cesium.filters', 'cesium.config', 'cesium.platform', 'cesium.controllers', 'cesium.templates', 'cesium.translations', 'cesium.components', 'cesium.directives' ]) - // Translation i18n - .config(function ($translateProvider, csConfig) { - 'ngInject'; - - $translateProvider - .uniformLanguageTag('bcp47') - .determinePreferredLanguage() - // Cela fait bugger les placeholder (pb d'affichage des accents en FR) - //.useSanitizeValueStrategy('sanitize') - .useSanitizeValueStrategy(null) - .fallbackLanguage([csConfig.fallbackLanguage ? csConfig.fallbackLanguage : 'en']) - .useLoaderCache(true); - }) - - .config(function($httpProvider, csConfig) { - 'ngInject'; - - // Set default timeout - $httpProvider.defaults.timeout = !!csConfig.TIMEOUT ? csConfig.TIMEOUT : 4000 /* default timeout */; - - //Enable cross domain calls - $httpProvider.defaults.useXDomain = true; - - //Remove the header used to identify ajax call that would prevent CORS from working - delete $httpProvider.defaults.headers.common['X-Requested-With']; - - // removeIf(no-device) - // Group http request response processing (better performance when many request) - $httpProvider.useApplyAsync(true); - // endRemoveIf(no-device) - }) - - .config(function($compileProvider, csConfig) { - 'ngInject'; - - $compileProvider.debugInfoEnabled(!!csConfig.DEBUG); - }) - - .config(function($animateProvider) { - 'ngInject'; - $animateProvider.classNameFilter( /\banimate-/ ); - }) - - // Configure cache (used by HTTP requests) default max age - .config(function (CacheFactoryProvider) { - angular.extend(CacheFactoryProvider.defaults, { maxAge: 60 * 1000 /*1min*/}); - }) - - // Configure screen size detection - .config(function(screenmatchConfigProvider) { - screenmatchConfigProvider.config.rules = 'bootstrap'; - }) - - .config(function($ionicConfigProvider) { - 'ngInject'; - // JS scrolling need for iOs (see http://blog.ionic.io/native-scrolling-in-ionic-a-tale-in-rhyme/) - var enableJsScrolling = ionic.Platform.isIOS(); - $ionicConfigProvider.scrolling.jsScrolling(enableJsScrolling); - - // Configure the view cache - $ionicConfigProvider.views.maxCache(5); - }) - - .config(function(IdleProvider, csConfig) { - 'ngInject'; - - IdleProvider.idle(csConfig.logoutIdle||10*60/*10min*/); - IdleProvider.timeout(csConfig.logoutTimeout||15); // display warning during 15s - }) - - // Override the automatic sync between location URL and state // (see watch event $locationChangeSuccess in the run() function bellow) .config(function ($urlRouterProvider) { @@ -94,219 +23,114 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht $urlRouterProvider.deferIntercept(); }) - .factory('$exceptionHandler', function() { + .run(function($rootScope, $translate, $state, $window, $urlRouter, ionicReady, + Device, UIUtils, $ionicConfig, PluginService, csPlatform, csWallet) { 'ngInject'; - return function(exception, cause) { - if (cause) console.error(exception, cause); - else console.error(exception); - }; - }) - - -.run(function($rootScope, $translate, $state, $window, $urlRouter, ionicReady, - Device, UIUtils, $ionicConfig, PluginService, csPlatform, csWallet, csSettings, csConfig, csCurrency) { - 'ngInject'; - - // Allow access to service data, from HTML templates - $rootScope.config = csConfig; - $rootScope.settings = csSettings.data; - $rootScope.currency = csCurrency.data; - $rootScope.walletData = csWallet.data; - $rootScope.device = Device; + // Allow access to service data, from HTML templates + $rootScope.walletData = csWallet.data; - // Compute the root path - var hashIndex = $window.location.href.indexOf('#'); - $rootScope.rootPath = (hashIndex != -1) ? $window.location.href.substr(0, hashIndex) : $window.location.href; - console.debug('[app] Root path is [' + $rootScope.rootPath + ']'); + // Must be done before any other $stateChangeStart listeners + csPlatform.disableChangeState(); - // removeIf(device) - // -- Automatic redirection to HTTPS - if ((csConfig.httpsMode === true || csConfig.httpsMode == 'true' ||csConfig.httpsMode === 'force') && - $window.location.protocol != 'https:') { + var preventStateChange = false; // usefull to avoid duplicate login, when a first page with auth $rootScope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { - var path = 'https' + $rootScope.rootPath.substr(4) + $state.href(next, nextParams); - if (csConfig.httpsModeDebug) { - console.debug('[app] [httpsMode] --- Should redirect to: ' + path); - // continue - } - else { - $window.location.href = path; - } - }); - } - // endRemoveIf(device) - - // Must be done before any other $stateChangeStart listeners - csPlatform.disableChangeState(); - - var preventStateChange = false; // usefull to avoid duplicate login, when a first page with auth - $rootScope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { - if (event.defaultPrevented) return; + if (event.defaultPrevented) return; - var skip = !next.data || $rootScope.tour || event.currentScope.tour; // disabled for help tour - if (skip) return; + var skip = !next.data || $rootScope.tour || event.currentScope.tour; // disabled for help tour + if (skip) return; - if (preventStateChange) { - event.preventDefault(); - return; - } - - var options; - - // removeIf(android) - // removeIf(ios) - // removeIf(firefoxos) - // -- Automatic redirection to large state (if define) (keep this code for platforms web and ubuntu build) - if (next.data.large && !UIUtils.screen.isSmall()) { - event.preventDefault(); - $state.go(next.data.large, nextParams); - return; - } - // endRemoveIf(firefoxos) - // endRemoveIf(ios) - // endRemoveIf(android) + if (preventStateChange) { + event.preventDefault(); + return; + } - // If state need auth - if (next.data.auth && !csWallet.isAuth()) { - event.preventDefault(); - options = next.data.minData ? {minData: true} : undefined; - preventStateChange = true; - return csWallet.auth(options) - .then(function() { - preventStateChange = false; - return $state.go(next.name, nextParams); - }) - .catch(function(err) { - preventStateChange = false; - // If cancel, redirect to home, if no current state - if (err == 'CANCELLED' && !$state.current.name) { - return $state.go('app.home'); - } - }); - } + var options; - // If state need login - else if (next.data.login && !csWallet.isLogin()) { - event.preventDefault(); - options = next.data.minData ? {minData: true} : undefined; - preventStateChange = true; - return csWallet.login(options) - .then(function() { - preventStateChange = false; - return $state.go(next.name, nextParams); - }) - .catch(function(err) { - preventStateChange = false; - // If cancel, redirect to home, if no current state - if (err == 'CANCELLED' && !$state.current.name) { - return $state.go('app.home'); - } - }); - } + // removeIf(android) + // removeIf(ios) + // removeIf(firefoxos) + // -- Automatic redirection to large state (if define) (keep this code for platforms web and ubuntu build) + if (next.data.large && !UIUtils.screen.isSmall()) { + event.preventDefault(); + $state.go(next.data.large, nextParams); + return; + } + // endRemoveIf(firefoxos) + // endRemoveIf(ios) + // endRemoveIf(android) - // If state need login or auth, make sure to load wallet data - else if (next.data.login || next.data.auth) { - options = next.data.minData ? {minData: true} : undefined; - if (!csWallet.isDataLoaded(options)) { + // If state need auth + if (next.data.auth && !csWallet.isAuth()) { event.preventDefault(); - return csWallet.loadData(options) + options = next.data.minData ? {minData: true} : undefined; + preventStateChange = true; + return csWallet.auth(options) .then(function() { preventStateChange = false; return $state.go(next.name, nextParams); + }) + .catch(function(err) { + preventStateChange = false; + // If cancel, redirect to home, if no current state + if (err == 'CANCELLED' && !$state.current.name) { + return $state.go('app.home'); + } }); } - } - }); - - // Leave the current page, if auth was required to access it - csWallet.api.data.on.unauth($rootScope, function() { - if ($state.current && $state.current.data && $state.current.data.auth) { - $state.go('app.home'); - } - }); - // Prevent $urlRouter's default handler from firing (don't sync ui router) - $rootScope.$on('$locationChangeSuccess', function(event, newUrl, oldUrl) { - if ($state.current.data && $state.current.data.silentLocationChange === true) { - // Skipping propagation, because same URL, and state configured with 'silentLocationChange' options - var sameUrl = oldUrl && (oldUrl.split('?')[0] === newUrl.split('?')[0]); - if (sameUrl) event.preventDefault(); - } - }); - // Configures $urlRouter's listener *after* the previous listener - $urlRouter.listen(); - - // Start plugins eager services - PluginService.start(); - - // We use 'ionicReady()' instead of '$ionicPlatform.ready()', because this one is callable many times - ionicReady().then(function() { - - // Keyboard - if (Device.keyboard.enable) { - // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard - // for form inputs) - Device.keyboard.hideKeyboardAccessoryBar(true); + // If state need login + else if (next.data.login && !csWallet.isLogin()) { + event.preventDefault(); + options = next.data.minData ? {minData: true} : undefined; + preventStateChange = true; + return csWallet.login(options) + .then(function() { + preventStateChange = false; + return $state.go(next.name, nextParams); + }) + .catch(function(err) { + preventStateChange = false; + // If cancel, redirect to home, if no current state + if (err == 'CANCELLED' && !$state.current.name) { + return $state.go('app.home'); + } + }); + } - // iOS: do not push header up when opening keyboard - // (see http://ionicframework.com/docs/api/page/keyboard/) - if (ionic.Platform.isIOS()) { - Device.keyboard.disableScroll(true); + // If state need login or auth, make sure to load wallet data + else if (next.data.login || next.data.auth) { + options = next.data.minData ? {minData: true} : undefined; + if (!csWallet.isDataLoaded(options)) { + event.preventDefault(); + return csWallet.loadData(options) + .then(function() { + preventStateChange = false; + return $state.go(next.name, nextParams); + }); + } } - } + }); - // Ionic Platform Grade is not A, disabling views transitions - if (ionic.Platform.grade.toLowerCase() != 'a') { - console.info('[app] Disabling UI effects, because plateform\'s grade is [' + ionic.Platform.grade + ']'); - UIUtils.setEffects(false); - } + // Leave the current page, if auth was required to access it + csWallet.api.data.on.unauth($rootScope, function() { + if ($state.current && $state.current.data && $state.current.data.auth) { + $state.go('app.home'); + } + }); - // Status bar style - if (window.StatusBar) { - // org.apache.cordova.statusbar required - StatusBar.styleDefault(); - } + // Prevent $urlRouter's default handler from firing (don't sync ui router) + $rootScope.$on('$locationChangeSuccess', function(event, newUrl, oldUrl) { + if ($state.current.data && $state.current.data.silentLocationChange === true) { + // Skipping propagation, because same URL, and state configured with 'silentLocationChange' options + var sameUrl = oldUrl && (oldUrl.split('?')[0] === newUrl.split('?')[0]); + if (sameUrl) event.preventDefault(); + } + }); + // Configures $urlRouter's listener *after* the previous listener + $urlRouter.listen(); - // Make sure platform is started - return csPlatform.ready(); - }); -}) + // Start plugins eager services + PluginService.start(); + }) ; - -// Workaround to add "".startsWith() if not present -if (typeof String.prototype.startsWith !== 'function') { - console.debug("Adding String.prototype.startsWith() -> was missing on this platform"); - String.prototype.startsWith = function(prefix) { - return this.indexOf(prefix) === 0; - }; -} - -// Workaround to add "".startsWith() if not present -if (typeof String.prototype.trim !== 'function') { - console.debug("Adding String.prototype.trim() -> was missing on this platform"); - // Make sure we trim BOM and NBSP - var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; - String.prototype.trim = function() { - return this.replace(rtrim, ''); - }; -} - -// Workaround to add Math.trunc() if not present - fix #144 -if (Math && typeof Math.trunc !== 'function') { - console.debug("Adding Math.trunc() -> was missing on this platform"); - Math.trunc = function(number) { - return (number - 0.5).toFixed(); - }; -} - -// Workaround to add "".format() if not present -if (typeof String.prototype.format !== 'function') { - console.debug("Adding String.prototype.format() -> was missing on this platform"); - String.prototype.format = function() { - var args = arguments; - return this.replace(/{(\d+)}/g, function(match, number) { - return typeof args[number] != 'undefined' ? args[number] : match; - }); - }; -} diff --git a/www/js/components.js b/www/js/components.js index 34ba027d79a9ba0411352e67e436d18094f133d7..2833ce11b83dd8c5401548c8ae65bb055e03db63 100644 --- a/www/js/components.js +++ b/www/js/components.js @@ -1,4 +1,4 @@ -angular.module('cesium') +angular.module('cesium.components', []) .component('csBadgeCertification', { bindings: { diff --git a/www/js/config.js b/www/js/config.js index 91fc3fc15cf9928696a135e506f86cdcb3a881ba..87eb4df867a4ea586a64414dcd70d22b68672c76 100644 --- a/www/js/config.js +++ b/www/js/config.js @@ -11,6 +11,7 @@ angular.module("cesium.config", []) .constant("csConfig", { "cacheTimeMs": 300000, "fallbackLanguage": "en", + "debug": true, "rememberMe": true, "showUDHistory": false, "timeout": 300000, @@ -70,4 +71,4 @@ angular.module("cesium.config", []) "newIssueUrl": "https://github.com/duniter/cesium/issues/new?labels=bug" }) -; \ No newline at end of file +; diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js index bd968685f443b9fb994608ec3677cb608916f3a2..26323640c74a0dce72ceb3bf64769045fddbf024 100644 --- a/www/js/controllers/app-controllers.js +++ b/www/js/controllers/app-controllers.js @@ -1,14 +1,4 @@ -angular.module('cesium.app.controllers', ['ngIdle', 'cesium.platform', 'cesium.services']) - - .config(function($httpProvider) { - 'ngInject'; - - //Enable cross domain calls - $httpProvider.defaults.useXDomain = true; - - //Remove the header used to identify ajax call that would prevent CORS from working - delete $httpProvider.defaults.headers.common['X-Requested-With']; - }) +angular.module('cesium.app.controllers', ['cesium.platform', 'cesium.services']) .config(function($stateProvider, $urlRouterProvider) { 'ngInject'; @@ -58,20 +48,10 @@ angular.module('cesium.app.controllers', ['ngIdle', 'cesium.platform', 'cesium.s .controller('PluginExtensionPointCtrl', PluginExtensionPointController) - .controller('EmptyModalCtrl', EmptyModalController) - .controller('AboutCtrl', AboutController) ; - -/** - * Useful for modal with no controller (see Modal service) - */ -function EmptyModalController($scope, parameters) { - -} - /** * Useful controller that could be reuse in plugin, using $scope.extensionPoint for condition rendered in templates */ @@ -423,12 +403,6 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } -function AboutController($scope, csConfig) { - 'ngInject'; - $scope.config = csConfig; -} - - function HomeController($scope, $state, $timeout, $ionicHistory, csPlatform, csCurrency) { 'ngInject'; diff --git a/www/js/controllers/login-controllers.js b/www/js/controllers/login-controllers.js index bb1bad1d9155c3b26e8ff5f7ba781ac7212e4f07..5184cbd4235bc3873262cd062d825f81fc56df29 100644 --- a/www/js/controllers/login-controllers.js +++ b/www/js/controllers/login-controllers.js @@ -3,6 +3,8 @@ angular.module('cesium.login.controllers', ['cesium.services']) .controller('LoginModalCtrl', LoginModalController) + .controller('AuthCtrl', AuthController) + ; function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, UIUtils, BMA, Modals, csSettings, Device, parameters) { @@ -417,3 +419,15 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, //$scope.form = {$valid:true}; }, 900);*/ } + + +function AuthController($scope, $controller){ + + // Initialize the super class and extend it. + angular.extend(this, $controller('LoginModalCtrl', {$scope: $scope, parameters: {auth: true}})); + + $scope.setForm = function(form) { + $scope.form = form; + }; + +} diff --git a/www/js/directives.js b/www/js/directives.js index 1fe82e0fe59078a369afa73be23e8850b303ad48..f7f9c58e1f6e3c5632c43ca5760a2d751ed4ca4b 100644 --- a/www/js/directives.js +++ b/www/js/directives.js @@ -1,4 +1,4 @@ -angular.module('cesium') +angular.module('cesium.directives', []) // Add new compare-to directive (need for form validation) .directive("compareTo", function() { diff --git a/www/js/platform.js b/www/js/platform.js index 2c9d9e1ef3328952987f647575058965584d6a45..e5db212f3824977fcbbaff1a33e6c473c4694663 100644 --- a/www/js/platform.js +++ b/www/js/platform.js @@ -1,5 +1,91 @@ -angular.module('cesium.platform', ['cesium.config', 'cesium.services']) +angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']) + + // Translation i18n + .config(function ($translateProvider, csConfig) { + 'ngInject'; + + $translateProvider + .uniformLanguageTag('bcp47') + .determinePreferredLanguage() + // Cela fait bugger les placeholder (pb d'affichage des accents en FR) + //.useSanitizeValueStrategy('sanitize') + .useSanitizeValueStrategy(null) + .fallbackLanguage([csConfig.fallbackLanguage ? csConfig.fallbackLanguage : 'en']) + .useLoaderCache(true); + }) + + .config(function($httpProvider, csConfig) { + 'ngInject'; + + // Set default timeout + $httpProvider.defaults.timeout = !!csConfig.timeout ? csConfig.timeout : 300000 /* default timeout */; + + //Enable cross domain calls + $httpProvider.defaults.useXDomain = true; + + //Remove the header used to identify ajax call that would prevent CORS from working + delete $httpProvider.defaults.headers.common['X-Requested-With']; + + // removeIf(no-device) + // Group http request response processing (better performance when many request) + $httpProvider.useApplyAsync(true); + // endRemoveIf(no-device) + }) + + + .config(function($compileProvider, csConfig) { + 'ngInject'; + + $compileProvider.debugInfoEnabled(!!csConfig.debug); + }) + + .config(function($animateProvider) { + 'ngInject'; + + $animateProvider.classNameFilter( /\banimate-/ ); + }) + + // Configure cache (used by HTTP requests) default max age + .config(function (CacheFactoryProvider, csConfig) { + 'ngInject'; + angular.extend(CacheFactoryProvider.defaults, { maxAge: csConfig.cacheTimeMs || 60 * 1000 /*1min*/}); + }) + + // Configure screen size detection + .config(function(screenmatchConfigProvider) { + 'ngInject'; + + screenmatchConfigProvider.config.rules = 'bootstrap'; + }) + + .config(function($ionicConfigProvider) { + 'ngInject'; + + // JS scrolling need for iOs (see http://blog.ionic.io/native-scrolling-in-ionic-a-tale-in-rhyme/) + var enableJsScrolling = ionic.Platform.isIOS(); + $ionicConfigProvider.scrolling.jsScrolling(enableJsScrolling); + + // Configure the view cache + $ionicConfigProvider.views.maxCache(5); + }) + + .config(function(IdleProvider, csConfig) { + 'ngInject'; + + IdleProvider.idle(csConfig.logoutIdle||10*60/*10min*/); + IdleProvider.timeout(csConfig.logoutTimeout||15); // display warning during 15s + }) + + .factory('$exceptionHandler', function() { + 'ngInject'; + + return function(exception, cause) { + if (cause) console.error(exception, cause); + else console.error(exception); + }; + }) + .factory('csPlatform', function (ionicReady, $rootScope, $q, $state, $translate, $timeout, UIUtils, BMA, Device, csHttp, csConfig, csSettings, csCurrency, csWallet) { @@ -153,10 +239,10 @@ angular.module('cesium.platform', ['cesium.config', 'cesium.services']) BMA.stop(); return $timeout(function() { - enableChangeState(); - started = false; - startPromise = null; - }, 500); + enableChangeState(); + started = false; + startPromise = null; + }, 500); } return { @@ -168,4 +254,108 @@ angular.module('cesium.platform', ['cesium.config', 'cesium.services']) stop: stop }; }) + + .run(function($rootScope, $translate, $state, $window, $urlRouter, ionicReady, + Device, UIUtils, $ionicConfig, PluginService, csPlatform, csWallet, csSettings, csConfig, csCurrency) { + 'ngInject'; + + // Allow access to service data, from HTML templates + $rootScope.config = csConfig; + $rootScope.settings = csSettings.data; + $rootScope.currency = csCurrency.data; + $rootScope.device = Device; + + // Compute the root path + var hashIndex = $window.location.href.indexOf('#'); + $rootScope.rootPath = (hashIndex != -1) ? $window.location.href.substr(0, hashIndex) : $window.location.href; + console.debug('[app] Root path is [' + $rootScope.rootPath + ']'); + + // removeIf(device) + // -- Automatic redirection to HTTPS + if ((csConfig.httpsMode === true || csConfig.httpsMode == 'true' ||csConfig.httpsMode === 'force') && + $window.location.protocol != 'https:') { + $rootScope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { + var path = 'https' + $rootScope.rootPath.substr(4) + $state.href(next, nextParams); + if (csConfig.httpsModeDebug) { + console.debug('[app] [httpsMode] --- Should redirect to: ' + path); + // continue + } + else { + $window.location.href = path; + } + }); + } + // endRemoveIf(device) + + // We use 'ionicReady()' instead of '$ionicPlatform.ready()', because this one is callable many times + ionicReady().then(function() { + + // Keyboard + if (Device.keyboard.enable) { + // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard + // for form inputs) + Device.keyboard.hideKeyboardAccessoryBar(true); + + // iOS: do not push header up when opening keyboard + // (see http://ionicframework.com/docs/api/page/keyboard/) + if (ionic.Platform.isIOS()) { + Device.keyboard.disableScroll(true); + } + } + + // Ionic Platform Grade is not A, disabling views transitions + if (ionic.Platform.grade.toLowerCase() != 'a') { + console.info('[app] Disabling UI effects, because plateform\'s grade is [' + ionic.Platform.grade + ']'); + UIUtils.setEffects(false); + } + + // Status bar style + if (window.StatusBar) { + // org.apache.cordova.statusbar required + StatusBar.styleDefault(); + } + + // Make sure platform is started + return csPlatform.ready(); + }); + }) +; + +// Workaround to add "".startsWith() if not present +if (typeof String.prototype.startsWith !== 'function') { + console.debug("Adding String.prototype.startsWith() -> was missing on this platform"); + String.prototype.startsWith = function(prefix) { + return this.indexOf(prefix) === 0; + }; +} + +// Workaround to add "".startsWith() if not present +if (typeof String.prototype.trim !== 'function') { + console.debug("Adding String.prototype.trim() -> was missing on this platform"); + // Make sure we trim BOM and NBSP + var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + String.prototype.trim = function() { + return this.replace(rtrim, ''); + }; +} + +// Workaround to add Math.trunc() if not present - fix #144 +if (Math && typeof Math.trunc !== 'function') { + console.debug("Adding Math.trunc() -> was missing on this platform"); + Math.trunc = function(number) { + return (number - 0.5).toFixed(); + }; +} + +// Workaround to add "".format() if not present +if (typeof String.prototype.format !== 'function') { + console.debug("Adding String.prototype.format() -> was missing on this platform"); + String.prototype.format = function() { + var args = arguments; + return this.replace(/{(\d+)}/g, function(match, number) { + return typeof args[number] != 'undefined' ? args[number] : match; + }); + }; +} + ; diff --git a/www/js/services/device-services.js b/www/js/services/device-services.js index da81f75ecf0faa214f1518ad5c095d6515656bfa..8bfe85dec541b8114753febb0b0410719df13ec8 100644 --- a/www/js/services/device-services.js +++ b/www/js/services/device-services.js @@ -85,8 +85,8 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti var deferred = $q.defer(); cordova.plugins.barcodeScanner.scan( function(result) { - //console.log('bar code result'); - //console.log(result); + console.log('bar code result'); + console.log(result); if (!result.cancelled) { deferred.resolve(result.text); // make sure to convert into String } @@ -94,7 +94,10 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti deferred.resolve(); } }, - function(err) {deferred.reject(err);}, + function(err) { + console.log('XXX -> ' + err); + deferred.reject(err); + }, n); return deferred.promise; } diff --git a/www/js/services/modal-services.js b/www/js/services/modal-services.js index 5f0a1e6d5bbbfef5695fde84decb017d73142cc8..86d684c372ed44719b6fe9d2fa2b13002341942e 100644 --- a/www/js/services/modal-services.js +++ b/www/js/services/modal-services.js @@ -1,5 +1,11 @@ angular.module('cesium.modal.services', []) +// Useful for modal with no controller +.controller('EmptyModalCtrl', function ($scope, parameters) { + 'ngInject'; + +}) + .factory('ModalUtils', function($ionicModal, $rootScope, $q, $injector, $controller, $timeout) { 'ngInject'; @@ -156,7 +162,7 @@ angular.module('cesium.modal.services', []) } function showAbout(parameters) { - return ModalUtils.show('templates/modal_about.html','AboutCtrl', + return ModalUtils.show('templates/modal_about.html','EmptyModalCtrl', parameters); } diff --git a/www/js/services/tx-services.js b/www/js/services/tx-services.js index 59ccff35a677dd615b0e9641386e47e260ffc807..502303b8fa17385fc32fc913af8deb6c510c93a8 100644 --- a/www/js/services/tx-services.js +++ b/www/js/services/tx-services.js @@ -30,7 +30,8 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', var sources = []; var lockedOutputs; var amount = tx.outputs.reduce(function(sum, output, noffset) { - var outputArray = output.split(':',3); + // FIXME duniter v1.4.13 + var outputArray = (typeof output == 'string') ? output.split(':',3) : [output.amount,output.base,output.conditions]; outputBase = parseInt(outputArray[1]); var outputAmount = powBase(parseInt(outputArray[0]), outputBase); var outputCondition = outputArray[2]; diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index 37c171b21729b98b5b455b09895a30932c6c9d72..b0d835508127e0bb58399a298e1162b288c82255 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -119,7 +119,8 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se var keepAuth = csSettings.data.keepAuthIdle > 0; var authData; - return Modals.showLogin(options) + return (options && options.authData && $q.when(options.authData) || + Modals.showLogin(options)) .then(function(res){ if (!res || !res.pubkey || (!needLogin && res.pubkey !== data.pubkey) || @@ -184,7 +185,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return keepAuth ? data : angular.merge({}, data, authData); }) .catch(function(err) { - if (err == 'RETRY') { + if (err == 'RETRY' && (!options || !options.authData)) { return $timeout(function(){ return login(options); }, 300); @@ -1653,7 +1654,10 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return $timeout(start, 200); } - function start() { + function start(options) { + options = options || {}; + options.skipRestore = angular.isDefined(options.skipRestore) ? options.skipRestore : false; + console.debug('[wallet] Starting...'); var now = new Date().getTime(); @@ -1661,21 +1665,19 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se csSettings.ready(), csCurrency.ready(), BMA.ready() - ]) + ]); - // Restore - .then(restore) + // Restore + if (!options.skipRestore) startPromise = startPromise.then(restore); - // Emit ready event - .then(function() { + // Emit ready event + startPromise.then(function() { addListeners(); console.debug('[wallet] Started in ' + (new Date().getTime() - now) + 'ms'); started = true; startPromise = null; - startLoadOptions = null; - }) .then(function(){ return data; diff --git a/www/plugins/es/js/services/registry-services.js b/www/plugins/es/js/services/registry-services.js index ff8294a0feaa98c2370b9b0258e20202c2f5ff06..8df998c0dbf5f74e5de0982b15723740d34875a4 100644 --- a/www/plugins/es/js/services/registry-services.js +++ b/www/plugins/es/js/services/registry-services.js @@ -17,7 +17,7 @@ angular.module('cesium.es.registry.services', ['ngResource', 'cesium.services', _internal: {}, }; - exports._internal.getCategories = esHttp.get('/registry/category/_search?sort=order&from=0&size=1000&_source=name,parent'); + exports._internal.getCategories = esHttp.get('/page/category/_search?sort=order&from=0&size=1000&_source=name,parent'); function getCategories() { if (exports._internal.categories && exports._internal.categories.length) { @@ -46,7 +46,7 @@ angular.module('cesium.es.registry.services', ['ngResource', 'cesium.services', }); } - exports._internal.getCategory = esHttp.get('/registry/category/:id'); + exports._internal.getCategory = esHttp.get('/page/category/:id'); function getCategory(params) { return exports._internal.getCategory(params) @@ -88,10 +88,10 @@ angular.module('cesium.es.registry.services', ['ngResource', 'cesium.services', return record; } - exports._internal.searchText = esHttp.get('/registry/record/_search?q=:search'); - exports._internal.search = esHttp.post('/registry/record/_search'); - exports._internal.get = esHttp.get('/registry/record/:id'); - exports._internal.getCommons = esHttp.get('/registry/record/:id?_source=' + fields.commons.join(',')); + exports._internal.searchText = esHttp.get('/page/record/_search?q=:search'); + exports._internal.search = esHttp.post('/page/record/_search'); + exports._internal.get = esHttp.get('/page/record/:id'); + exports._internal.getCommons = esHttp.get('/page/record/:id?_source=' + fields.commons.join(',')); function search(request) { request = request || {}; @@ -164,20 +164,20 @@ angular.module('cesium.es.registry.services', ['ngResource', 'cesium.services', exports.record = { search: search, load: loadData, - add: esHttp.record.post('/registry/record'), - update: esHttp.record.post('/registry/record/:id/_update'), + add: esHttp.record.post('/page/record'), + update: esHttp.record.post('/page/record/:id/_update'), remove: esHttp.record.remove('registry', 'record'), fields: { commons: fields.commons }, picture: { - all: esHttp.get('/registry/record/:id?_source=pictures') + all: esHttp.get('/page/record/:id?_source=pictures') }, comment: esComment.instance('registry') }; exports.currency = { - all: esHttp.get('/registry/currency/_search?_source=currencyName,peers.host,peers.port'), - get: esHttp.get('/registry/currency/:id/_source') + all: esHttp.get('/currency/record/_search?_source=currencyName,peers.host,peers.port'), + get: esHttp.get('/currency/record/:id/_source') }; return exports; } diff --git a/www/templates/api/doc.html b/www/templates/api/doc.html new file mode 100644 index 0000000000000000000000000000000000000000..373bb0cf6cb02264d19f57e40ec2e184bcd9c67f --- /dev/null +++ b/www/templates/api/doc.html @@ -0,0 +1,70 @@ + + + <!-- transfer --> + <h2 class="padding" translate>API.DOC.TRANSFER.TITLE</h2> + + + <div class="list padding no-padding-xs no-padding-top"> + + <div class="item item-divider no-border"> + <p translate>API.DOC.DESCRIPTION_DIVIDER</p> + </div> + + <div class="item item-text-wrap"> + <p translate>API.DOC.TRANSFER.DESCRIPTION</p> + </div> + + <div class="item item-divider no-border"> + <p translate>API.DOC.URL_DIVIDER</p> + </div> + + <div class="item item-text-wrap"> + <p class="gray text-right"> + {{$root.rootPath}}#/v1/payment/:pubkey?amount=<span class="text-italic" translate>API.DOC.TRANSFER.PARAM_AMOUNT</span> + </p> + </div> + + <div class="item item-divider no-border"> + <p translate>API.DOC.PARAMETERS_DIVIDER</p> + </div> + + <div class="item item-text-wrap"> + <p translate>API.DOC.AVAILABLE_PARAMETERS</p> + <div class="row"> + <div class="col col-20 text-italic">amount</div> + <div class="col" translate>API.DOC.TRANSFER.PARAM_AMOUNT_HELP</div> + </div> + <div class="row"> + <div class="col col-20 text-italic">comment</div> + <div class="col" translate>API.DOC.TRANSFER.PARAM_COMMENT_HELP</div> + </div> + <div class="row"> + <div class="col col-20 text-italic">name</div> + <div class="col" translate>API.DOC.TRANSFER.PARAM_NAME_HELP</div> + </div> + <div class="row"> + <div class="col col-20 text-italic">redirect_url</div> + <div class="col" translate>API.DOC.TRANSFER.PARAM_REDIRECT_URL_HELP</div> + </div> + <div class="row"> + <div class="col col-20 text-italic">cancel_url</div> + <div class="col" translate>API.DOC.TRANSFER.PARAM_CANCEL_URL_HELP</div> + </div> + </div> + <div class="item item-button-right"> + <h2> </h2> + <a ui-sref="api.transfer(transferData)" class="button button-raised button-positive" translate>API.DOC.BTN_DEMO</a> + </div> + + + <!-- demo result --> + <div class="item item-text-wrap" ng-if="result.type === 'payment' && !result.cancelled"> + <h2 class="text-right balanced" translate>API.DOC.SUCCEED</h2> + <h4 class="gray" translate>API.DOC.RESULT</h4> + <p class="balanced-100-bg padding dark"> {{result.content}}</p> + </div> + <div class="item item-text-wrap" ng-if="result.type === 'payment' && result.cancelled"> + <h2 class="text-right assertive" translate>API.DOC.CANCELLED</h2> + </div> + + </div> diff --git a/www/templates/api/home.html b/www/templates/api/home.html new file mode 100644 index 0000000000000000000000000000000000000000..15b4106a3ec2ab6c969b59c6bb972996df9ba525 --- /dev/null +++ b/www/templates/api/home.html @@ -0,0 +1,38 @@ +<ion-view class="circle-bg-dark"> + <ion-nav-title> + <span class="title visible-xs visible-sm" translate>API.HOME.TITLE</span> + </ion-nav-title> + + <ion-content class=" has-header no-padding-xs positive-900-bg "> + + <br class="hidden-xs"/> + + <div class="light text-center" > + <h4 class="hidden-xs" translate>API.HOME.MESSAGE</h4> + <h4 class="visible-xs" translate>API.HOME.MESSAGE_SHORT</h4> + </div> + + <br class="hidden-xs"/> + + <div class="row no-padding-xs"> + <div class="col col-20 hidden-xs hidden-sm"> </div> + <div class="col "> + + <div class="light-bg no-padding"> + <!-- include documentation --> + <ng-include src="'templates/api/doc.html'"></ng-include> + </div> + </div> + + <div class="col col-20 hidden-xs hidden-sm text-center" id="home" > + <div style="display: block; width: 100%;"> + <div class="logo"></div> + <small class="light padding-top">v{{$root.config.version}}</small> + </div> + </div> + </div> + + </ion-content> + +</ion-view> + diff --git a/www/templates/api/menu.html b/www/templates/api/menu.html new file mode 100644 index 0000000000000000000000000000000000000000..a4751ae51b9578bd1b42556c6c873fc2c20ac5d7 --- /dev/null +++ b/www/templates/api/menu.html @@ -0,0 +1,18 @@ +<ion-side-menus bind-notifier="{locale:$root.settings.locale.id}"> + <!-- HEADER --> + <ion-side-menu-content> + <ion-nav-bar class="bar-dark" title-align="left"> + <ion-nav-back-button class="no-text"> + </ion-nav-back-button> + + <ion-nav-buttons side="left"> + </ion-nav-buttons> + <ion-nav-buttons side="right" > + </ion-nav-buttons> + </ion-nav-bar> + <ion-nav-view name="menuContent"></ion-nav-view> + + </ion-side-menu-content> + + +</ion-side-menus> diff --git a/www/templates/api/transfer.html b/www/templates/api/transfer.html new file mode 100644 index 0000000000000000000000000000000000000000..01fc26567f15830a054bc17a7020f565c57864c1 --- /dev/null +++ b/www/templates/api/transfer.html @@ -0,0 +1,93 @@ + +<ion-nav-view class="circle-bg-dark"> + <ion-nav-title> + <h1 class="title" ng-bind-html="'API.TRANSFER.TITLE' | translate"> + </h1> + <span class="visible-xs visible-sm" translate>API.TRANSFER.TITLE</span> + </ion-nav-title> + + <ion-nav-buttons side="left"> + <button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL + </button> + </ion-nav-buttons> + + <ion-nav-buttons side="right"> + <button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doLogin()"> + </button> + </ion-nav-buttons> + + <ion-content class=" has-header no-padding-xs positive-900-bg text-center"> + + <br class="hidden-xs"/> + + <div class="row no-padding-xs"> + <div class="col col-20 hidden-xs hidden-sm"> + + </div> + <div class="col no-padding-xs"> + + <div class="light-bg"> + + <h2 class="padding-top"> + <span class="hidden-xs" translate>API.TRANSFER.TITLE</span> + <span class="visible-xs" translate>API.TRANSFER.TITLE_SHORT</span> + </h2> + + <ng-include src="'templates/login/form_login.html'"></ng-include> + + </div> + <br class="hidden-xs"/> + <br class="hidden-xs"/> + <div class="list padding no-padding-xs light-bg expert-mode"> + <div class="item"> + <p translate>API.TRANSFER.SUMMARY</p> + </div> + + <div class="item item-icon-left-padding item-tx no-border "> + <h2 translate>API.TRANSFER.AMOUNT</h2> + <div class="badge item-note badge-calm" ng-bind-html="transferData.amount|formatAmount:{useRelative: false, currency: $root.currency.name}"></div> + <div class="badge badge-secondary" ng-bind-html="transferData.amount|formatAmount:{useRelative: true, currency: $root.currency.name}"></div> + </div> + <div class="item item-icon-left-padding" ng-if="transferData.name"> + <h2 translate>API.TRANSFER.NAME</h2> + <div class="badge item-note"> + {{transferData.name}} + </div> + </div> + <div class="item item-icon-left-padding item-text-wrap"> + <h2 translate>API.TRANSFER.PUBKEY</h2> + <div class="badge"> + <br class="visible-xs"/> + {{transferData.pubkey}} + </div> + </div> + + <div class="item item-icon-left-padding"> + <h2 translate>API.TRANSFER.COMMENT</h2> + <div class="badge item-note"> + {{transferData.comment}} + </div> + </div> + </div> + </div> + <div class="col col-20 hidden-xs hidden-sm text-center" id="home" > + <div style="display: block; width: 100%;"> + <div class="logo text-center"></div> + <small class="light padding-top">v{{$root.config.version}}</small> + </div> + </div> + </div> + + <p class="visible-xs visible-sm light padding-top"> + {{'COMMON.APP_NAME'|translate}} + - <a href="#" ng-click="showAboutModal($event)">v{{$root.config.version}}</a> + </p> + + <p class="hidden-xs hidden-sm gray padding-top"> + {{'COMMON.APP_NAME'|translate}} v{{$root.config.version}} + - <a href="#" ng-click="showAboutModal($event)" title="{{'HOME.BTN_ABOUT'|translate}}">{{'HOME.BTN_ABOUT'|translate}}</a> + - <a ui-sref="app.home" target="_blank" title="{{'API.COMMON.LINK_DOC_HELP'|translate}}">{{'API.COMMON.LINK_DOC'|translate}}</a> + </p> + + </ion-content> +</ion-nav-view> diff --git a/www/templates/login/form_login.html b/www/templates/login/form_login.html new file mode 100644 index 0000000000000000000000000000000000000000..6c05dd7c25ae16d41753f0feb84f346c50d6064f --- /dev/null +++ b/www/templates/login/form_login.html @@ -0,0 +1,76 @@ + + <form name="loginForm" novalidate="" ng-submit="doLogin()" autocomplete="off"> + + <div class="list padding no-padding-xs" + ng-init="setForm(loginForm)" + ng-switch on="formData.method"> + + <div class="item hidden-xs no-padding" ng-if="showMethods"> + <div class="pull-right"> + <a class="button button-text button-small-padding icon-right ink" + ng-click="showMethodsPopover($event)"> + <i class="icon ion-wrench"></i> + {{'LOGIN.BTN_METHODS'| translate}} + </a> + <a class="button button-icon positive button-small-padding icon ion-ios-help-outline" + style="right: 8px;" + ng-click="showHelpModal('login-method')"> + </a> + </div> + </div> + + <!-- Form content, depending of the login method --> + <div ng-switch-when="SCRYPT_DEFAULT"> + <ng-include src="'templates/login/form_scrypt.html'"></ng-include> + </div> + <div ng-switch-when="SCRYPT_ADVANCED"> + <ng-include src="'templates/login/form_scrypt_advanced.html'"></ng-include> + </div> + <div ng-switch-when="PUBKEY"> + <ng-include src="'templates/login/form_pubkey.html'"></ng-include> + </div> + <div ng-switch-when="FILE"> + <ng-include src="'templates/login/form_file_import.html'"></ng-include> + </div> + <div ng-switch-default> + <ng-include src="'templates/login/form_scrypt.html'"></ng-include> + </div> + </div> + + <div class="padding hidden-xs text-right"> + <button class="button button-clear button-dark ink" + ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL + </button> + <button class="button button-positive ink" ng-class="{'button-assertive': isAuth, 'button-positive': !isAuth}" type="submit"> + {{isAuth ? 'AUTH.BTN_AUTH' : 'COMMON.BTN_LOGIN' | translate}} + </button> + </div> + + <div class="text-center no-padding visible-xs"> + <br/> + <a ng-click="showMethodsPopover($event)"> + <i class="ion-loop"></i> + <span translate>LOGIN.BTN_METHODS_DOTS</span> + </a> + <br/><br/> + </div> + + <!-- Register ? --> + <ng-if ng-if="!isAuth"> + <div class="text-center no-padding"> + {{'LOGIN.NO_ACCOUNT_QUESTION'|translate}} + <br class="visible-xs"/> + <a ng-click="showJoinModal()" translate> + LOGIN.CREATE_ACCOUNT + </a> + </div> + + <br class="visible-xs"/> + + <div class="text-center no-padding"> + <a ng-click="showAccountSecurityModal()" translate> + LOGIN.FORGOTTEN_ID + </a> + </div> + </ng-if> + </form> diff --git a/www/templates/login/modal_login.html b/www/templates/login/modal_login.html index f2258d6ed70d4ae43450d844699375c70a56ea87..20d59dd993450dde3a28c317383f3b602c7948a9 100644 --- a/www/templates/login/modal_login.html +++ b/www/templates/login/modal_login.html @@ -15,80 +15,6 @@ </ion-header-bar> <ion-content> - <form name="loginForm" novalidate="" ng-submit="doLogin()" autocomplete="off"> - - <div class="list padding no-padding-xs" - ng-init="setForm(loginForm)" - ng-switch on="formData.method"> - - <div class="item hidden-xs no-padding" ng-if="showMethods"> - <div class="pull-right"> - <a class="button button-text button-small-padding icon-right ink" - ng-click="showMethodsPopover($event)"> - <i class="icon ion-wrench"></i> - {{'LOGIN.BTN_METHODS'| translate}} - </a> - <a class="button button-icon positive button-small-padding icon ion-ios-help-outline" - style="right: 8px;" - ng-click="showHelpModal('login-method')"> - </a> - </div> - </div> - - <!-- Form content, depending of the login method --> - <div ng-switch-when="SCRYPT_DEFAULT"> - <ng-include src="'templates/login/form_scrypt.html'"></ng-include> - </div> - <div ng-switch-when="SCRYPT_ADVANCED"> - <ng-include src="'templates/login/form_scrypt_advanced.html'"></ng-include> - </div> - <div ng-switch-when="PUBKEY"> - <ng-include src="'templates/login/form_pubkey.html'"></ng-include> - </div> - <div ng-switch-when="FILE"> - <ng-include src="'templates/login/form_file_import.html'"></ng-include> - </div> - <div ng-switch-default> - <ng-include src="'templates/login/form_scrypt.html'"></ng-include> - </div> - </div> - - <div class="padding hidden-xs text-right"> - <button class="button button-clear button-dark ink" - ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL - </button> - <button class="button button-positive ink" ng-class="{'button-assertive': isAuth, 'button-positive': !isAuth}" type="submit"> - {{isAuth ? 'AUTH.BTN_AUTH' : 'COMMON.BTN_LOGIN' | translate}} - </button> - </div> - - <div class="text-center no-padding visible-xs"> - <br/> - <a ng-click="showMethodsPopover($event)"> - <i class="ion-loop"></i> - <span translate>LOGIN.BTN_METHODS_DOTS</span> - </a> - <br/><br/> - </div> - - <!-- Register ? --> - <ng-if ng-if="!isAuth"> - <div class="text-center no-padding"> - {{'LOGIN.NO_ACCOUNT_QUESTION'|translate}} - <br class="visible-xs"/> - <a ng-click="showJoinModal()" translate> - LOGIN.CREATE_ACCOUNT - </a> - </div> - - <br class="visible-xs"/> - - <div class="text-center no-padding"> - <a ng-click="showAccountSecurityModal()" translate> - LOGIN.FORGOTTEN_ID - </a> - </div> - </ng-if> - </form> + <ng-include src="'templates/login/form_login.html'"></ng-include> </ion-content> </ion-modal-view> diff --git a/www/templates/modal_about.html b/www/templates/modal_about.html index f915aac54586de7c7ea3c1070cf7edcbe073bc05..bc90dc6922adbd5cd70ca07083f0648f0ce6af48 100644 --- a/www/templates/modal_about.html +++ b/www/templates/modal_about.html @@ -10,8 +10,8 @@ <div class="list item-wrap-text"> <div class="item item-complex item-icon-left item-text-wrap"> <div class="item-content"> - <span>{{'COMMON.APP_NAME'|translate}} {{'COMMON.APP_VERSION'|translate:config}}</span> - <h3 ng-if="config.build" class="gray">{{'COMMON.APP_BUILD'|translate:config}}</h3> + <span>{{'COMMON.APP_NAME'|translate}} {{'COMMON.APP_VERSION'|translate:$root.config}}</span> + <h3 ng-if="$root.config.build" class="gray">{{'COMMON.APP_BUILD'|translate:$root.config}}</h3> <span translate>ABOUT.LICENSE</span> </div> </div> @@ -46,7 +46,7 @@ <h2>{{'ABOUT.DEV_WARNING'|translate}}</h2> <span translate>ABOUT.DEV_WARNING_MESSAGE</span> <br/> - <a href="{{config.newIssueUrl}}" + <a href="{{$root.config.newIssueUrl}}" target="_system" translate>ABOUT.REPORT_ISSUE</a> </div>