diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json index 7bb1658831d1635974523bd5833119bffb731ded..5bcced84b4933f72dc0863e9772b1345c599999b 100644 --- a/www/i18n/locale-en.json +++ b/www/i18n/locale-en.json @@ -121,7 +121,9 @@ "POPUP_NODE": { "TITLE" : "Duniter Node", "HELP" : "Set the address of the node to use:" - } + }, + "SHOW_NODE_LIST" : "Choose a node" + }, "CURRENCY": { "SELECT": { @@ -160,7 +162,10 @@ "PEERS": "Peers", "KNOWN_PEERS": "Known peers", "SIGNED_ON_BLOCK": "Signed on block", - "MIRROR": "mirror" + "MIRROR": "mirror", + "NODE_LIST" : "Node's list", + "MEMBERS" : "Member Nodes", + "ALL_NODES" : "All nodes" }, "WOT": { "SEARCH_HELP": "Search (member or public key)", diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json index d0f17a46a83d2b175600809df279b7aac1f71f2a..01bf470174b8536dee5cc71c11d057e52cf72f31 100644 --- a/www/i18n/locale-fr-FR.json +++ b/www/i18n/locale-fr-FR.json @@ -121,7 +121,8 @@ "POPUP_NODE": { "TITLE" : "Noeud Duniter", "HELP" : "Saisissez l'adresse du noeud que vous voulez utiliser :" - } + }, + "SHOW_NODE_LIST" : "Choisir un noeud" }, "CURRENCY": { "SELECT": { @@ -160,7 +161,10 @@ "PEERS": "Noeuds", "KNOWN_PEERS": "Noeuds connus", "SIGNED_ON_BLOCK": "Signé sur le bloc", - "MIRROR": "mirroir" + "MIRROR": "mirroir", + "NODE_LIST" : "Liste des noeuds", + "MEMBERS" : "Noeuds membres", + "ALL_NODES" : "Tous les noeuds" }, "WOT": { "SEARCH_HELP": "Recherche (pseudo ou clé publique)", diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js index a2649840eab92ba731a9c00e953f4a79ad68b89e..4aa30c686f11d25c99f2e1c7998dae395002ab5e 100644 --- a/www/js/controllers/network-controllers.js +++ b/www/js/controllers/network-controllers.js @@ -35,6 +35,8 @@ angular.module('cesium.network.controllers', ['cesium.services']) .controller('PeerCtrl', PeerController) +.controller('NetworkModalCtrl', NetworkModalController) + ; function NetworkViewController($scope, $q, $translate, $timeout, BMA, UIUtils, csSettings, csCurrency, csNetwork) { @@ -42,7 +44,6 @@ function NetworkViewController($scope, $q, $translate, $timeout, BMA, UIUtils, c $scope.formData = { useRelative: csSettings.data.useRelative }; - $scope.screen = UIUtils.screen; $scope.$on('$ionicParentView.enter', function(e, state) { @@ -53,7 +54,7 @@ function NetworkViewController($scope, $q, $translate, $timeout, BMA, UIUtils, c } }) - .catch(UIUtils.onError('ERROR.GET_CURRENCY_FAILED')); + .catch(UIUtils.onError('ERROR.GET_CURRENCY_FAILED')); }); $scope.$on('$ionicParentView.beforeLeave', function(){ @@ -85,11 +86,11 @@ function NetworkViewController($scope, $q, $translate, $timeout, BMA, UIUtils, c $scope.$on('$destroy', function(){ csNetwork.close(); }); - } + } // Show help tip $scope.showHelpTip(); - }; + }; $scope.refresh = function() { // Network @@ -115,3 +116,89 @@ function NetworkViewController($scope, $q, $translate, $timeout, BMA, UIUtils, c }); }; } + +function NetworkModalController($scope, $q, $translate, $timeout, $ionicPopover, BMA, + UIUtils, csSettings, csCurrency, csNetwork) { + $scope.loadingPeers = true; + $scope.formData = { + useRelative: csSettings.data.useRelative + }; + $scope.enableFilter = true; + $scope.display='members'; + $scope.screen = UIUtils.screen; + + csCurrency.all() + .then(function (currencies) { + if (currencies && currencies.length > 0) { + $scope.load(currencies[0]); + } + + }) + .catch(UIUtils.onError('ERROR.GET_CURRENCY_FAILED')); + + $scope.load = function(currency) { + $scope.node = !BMA.node.same(currency.peer.host, currency.peer.port) ? + BMA.instance(currency.peer.host, currency.peer.port) : BMA; + + if ($scope.loadingPeers){ + csNetwork.start($scope.node); + + // Catch event on new peers + var refreshing = false; + csNetwork.api.data.on.changed($scope, function(data){ + if (!refreshing) { + refreshing = true; + $timeout(function() { // Timeout avoid to quick updates + console.debug("Updating UI Peers"); + $scope.peers = data.peers; + // Update currency params + + $scope.loadingPeers = csNetwork.isBusy(); + refreshing = false; + }, 1100); + } + }); + $scope.$on('$destroy', function(){ + csNetwork.close(); + }); + } + }; + + $scope.refresh = function() { + // Network + $scope.loadingPeers = true; + csNetwork.loadPeers(); + }; + + $scope.changeDisplay = function(type){ + $scope.hideActionsPopover(); + $scope.display = type; + } + + /* -- show/hide popup -- */ + + $scope.showActionsPopover = function(event) { + if (!$scope.actionsPopover) { + $ionicPopover.fromTemplateUrl('templates/network/lookup_popover_actions.html', { + scope: $scope + }).then(function(popover) { + $scope.actionsPopover = popover; + //Cleanup the popover when we're done with it! + $scope.$on('$destroy', function() { + $scope.actionsPopover.remove(); + }); + $scope.actionsPopover.show(event); + }); + } + else { + $scope.actionsPopover.show(event); + } + }; + + $scope.hideActionsPopover = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + } + }; + +} diff --git a/www/js/controllers/settings-controllers.js b/www/js/controllers/settings-controllers.js index a653c3e60ccba3db2aae48b0957a4134e41b59c3..5777488bc0d22a96b12051f2b4dd7ff7e21e3c67 100644 --- a/www/js/controllers/settings-controllers.js +++ b/www/js/controllers/settings-controllers.js @@ -20,12 +20,14 @@ angular.module('cesium.settings.controllers', ['cesium.services', 'cesium.curren .controller('SettingsCtrl', SettingsController) ; -function SettingsController($scope, $q, $ionicPopup, $timeout, $translate, csHttp, UIUtils, BMA, csSettings, $ionicPopover) { +function SettingsController($scope, $q, $ionicPopup, $timeout, $translate, csHttp, + UIUtils, BMA, csSettings, $ionicPopover, ModalUtils) { 'ngInject'; $scope.formData = angular.copy(csSettings.data); $scope.popupData = {}; // need for the node popup $scope.loading = true; + $scope.nodePopup = {}; $scope.$on('$ionicView.enter', function() { $scope.load(); @@ -93,6 +95,30 @@ function SettingsController($scope, $q, $ionicPopup, $timeout, $translate, csHtt }); }; + $scope.showNodeList = function(){ + $ionicPopup._popupStack[0].responseDeferred.resolve(); + return ModalUtils.show('/templates/network/modal_network.html', 'NetworkModalCtrl') + .then(function(result){ + if (result){ + var parts = result.server.split(':'); + var newNode; + if(result.dns){ + newNode = { + host: result.dns, + port: parts[1] + }; + } + else{ + newNode = { + host: parts[0], + port: parts[1] + } + }; + $scope.changeNode(newNode); + } + }); + }; + // Show node popup $scope.showNodePopup = function(node) { return $q(function(resolve, reject) { @@ -100,7 +126,8 @@ function SettingsController($scope, $q, $ionicPopup, $timeout, $translate, csHtt if (!!$scope.popupForm) { $scope.popupForm.$setPristine(); } - $translate(['SETTINGS.POPUP_NODE.TITLE', 'SETTINGS.POPUP_NODE.HELP', 'COMMON.BTN_OK', 'COMMON.BTN_CANCEL']) + $translate(['SETTINGS.POPUP_NODE.TITLE', 'SETTINGS.POPUP_NODE.HELP', + 'COMMON.BTN_OK', 'COMMON.BTN_CANCEL']) .then(function (translations) { // Choose UID popup $ionicPopup.show({ diff --git a/www/js/services/network-services.js b/www/js/services/network-services.js index 0ed037e05030eeab8b65b8a18674c4b6e98912b9..137b3a35ee5619445679083588eae7a541a5939c 100644 --- a/www/js/services/network-services.js +++ b/www/js/services/network-services.js @@ -151,18 +151,9 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se return peer; }) .then(function(peer) { - // Exit, if offline, not expert mode, or too small device - if (!peer.online || !csSettings.data.expertMode || UIUtils.screen.isSmall()) return peer; + // Exit if offline + if (!peer.online) return peer; var jobs = []; - // Get Version - jobs.push(node.node.summary() - .then(function(res){ - peer.version = res && res.duniter && res.duniter.version; - }) - .catch(function() { - peer.version = null; // continue - })); - // Get hardship (only for a member peer) if (peer.uid) { jobs.push(node.blockchain.stats.hardship({pubkey: peer.pubkey}) @@ -173,6 +164,17 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se peer.level = null; // continue })); } + // Exit if not expert mode or too small device + if (!csSettings.data.expertMode || UIUtils.screen.isSmall()) return peer; + + // Get Version + jobs.push(node.node.summary() + .then(function(res){ + peer.version = res && res.duniter && res.duniter.version; + }) + .catch(function() { + peer.version = null; // continue + })); $q.all(jobs); return peer; diff --git a/www/templates/network/lookup_popover_actions.html b/www/templates/network/lookup_popover_actions.html new file mode 100644 index 0000000000000000000000000000000000000000..248014d196e986d7f01d0c5b15df8fe0dede7de3 --- /dev/null +++ b/www/templates/network/lookup_popover_actions.html @@ -0,0 +1,22 @@ +<ion-popover-view class="fit has-header visible-sm visible-xs"> + <ion-header-bar> + <h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1> + </ion-header-bar> + <ion-content scroll="false"> + <div class="list item-text-wrap"> + + <a class="item item-icon-left ink" + ng-click="changeDisplay('members')"> + <i class="icon ion-android-people"></i> + {{'PEER.MEMBERS' | translate}} + </a> + + <a class="item item-icon-left ink" + ng-click="changeDisplay('allNodes')"> + <i class="icon ion-ios-infinite"></i> + {{'PEER.ALL_NODES' | translate}} + </a> + + </div> + </ion-content> +</ion-popover-view> diff --git a/www/templates/network/modal_network.html b/www/templates/network/modal_network.html new file mode 100644 index 0000000000000000000000000000000000000000..bc18080bf8a67b81865f2647cd983608f8a40408 --- /dev/null +++ b/www/templates/network/modal_network.html @@ -0,0 +1,77 @@ +<ion-modal-view id="nodes" class="modal-full-height" cache-view="false"> + <ion-header-bar class="bar-positive"> + <button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button> + <h1 class="title" translate>PEER.NODE_LIST</h1> + <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" + ng-click="showActionsPopover($event)"> + </button> + </ion-header-bar> + + <ion-content scroll="true"> + <div class="list"> + <div id="helptip-currency-peers" + class="item item-divider item-icon-right visible-xs visible-sm" + ng-if="display=='allNodes'||!enableFilter"> + {{'PEER.ALL_NODES' | translate}} + <ion-spinner class="icon" icon="android" ng-if="loadingPeers"></ion-spinner> + </div> + + <div id="helptip-currency-peers" + class="item item-divider item-icon-right visible-xs visible-sm" + ng-if="display=='members'"> + {{'PEER.MEMBERS' | translate}} + <ion-spinner class="icon" icon="android" ng-if="loadingPeers"></ion-spinner> + <a class="icon ion-loop gray hidden-xs hidden-sm" ng-if="!loadingPeers" ng-click="refresh()"> + </a> + </div> + + <div id="helptip-currency-peers" + class="item item-divider item-icon-right hidden-xs hidden-sm"> + {{'PEER.PEERS' | translate}} + <ion-spinner class="icon" icon="android" ng-if="loadingPeers"></ion-spinner> + <a class="icon ion-loop gray " ng-if="!loadingPeers" ng-click="refresh()"> + </a> + </div> + + <div class="text-center hidden-xs hidden-sm" ng-if="enableFilter"> + <a class="button button-text button-small ink icon ion-android-people" + ng-class="{'button-text-positive': display=='members'}" + ng-click="changeDisplay('members')"> + {{'PEER.MEMBERS' | translate}} + </a> + + <a class="button button-text button-small ink icon ion-ios-infinite" + ng-class="{'button-text-positive': display=='allNodes'}" + ng-click="changeDisplay('allNodes')"> + {{'PEER.ALL_NODES' | translate}} + </a> + + </div> + <ng-click class="peer-item item item-icon-left" + ng-repeat="peer in peers track by peer.server" + id="helptip-currency-peer-{{$index}}" + ng-class="{ assertive: !peer.online, balanced: (peer.online && peer.hasMainConsensusBlock), energized: (peer.online && !peer.hasMainConsensusBlock)}" + ng-click="closeModal(peer)" ng-if="(!peer.level && display=='allNodes') || peer.level || !enableFilter"> + + <i class="icon ion-android-globe"></i> + <div class="row no-padding"> + <div class="col no-padding"> + <h3><i ng-class="{'ion-person': peer.uid, 'ion-key': !peer.uid}"></i> <span>{{peer.uid || peer.pubkey.substr(0,8)}}</span> <span class="gray">{{peer.dns && ' | ' + peer.dns}}</span></h3> + <h4>{{peer.server}}</h4> + </div> + <div class="col col-10 no-padding" ng-if="settings.expertMode"> + <h3 class="hidden-sm hidden-xs hidden-md"> + <span ng-if="peer.level"><i class="ion-lock-combination"></i> {{peer.level}}</span> + <span ng-if="!peer.level" translate>PEER.MIRROR</span> + </h3> + <h4 class="hidden-sm hidden-xs hidden-md gray">v{{peer.version}}</h4> + </div> + <div class="col col-20 no-padding"> + <span id="helptip-currency-peer-{{$index}}-block" + class="badge" ng-class="{ 'badge-balanced': peer.hasMainConsensusBlock, 'badge-energized': peer.hasConsensusBlock }">{{peer.currentNumber}}</span> + </div> + </div> + </ng-click> + </div> + </ion-content> +</ion-modal-view> diff --git a/www/templates/network/tabs/view_nodes.html b/www/templates/network/tabs/view_nodes.html index 24ef977b118a8f7d4eda125fb584be9f2bcada1c..e3cfd11f9651b2fa4fb7277e96c9b1ec8a4db857 100644 --- a/www/templates/network/tabs/view_nodes.html +++ b/www/templates/network/tabs/view_nodes.html @@ -14,7 +14,7 @@ <i class="icon ion-android-globe"></i> <div class="row no-padding"> <div class="col no-padding"> - <h3><i ng-class="{'ion-person': peer.uid, 'ion-key': !peer.uid}"></i> {{peer.uid || peer.pubkey.substr(0,8)}}</span> <span class="gray">{{peer.dns && ' | ' + peer.dns}}</h3> + <h3><i ng-class="{'ion-person': peer.uid, 'ion-key': !peer.uid}"></i> <span>{{peer.uid || peer.pubkey.substr(0,8)}}</span> <span class="gray">{{peer.dns && ' | ' + peer.dns}}</span></h3> <h4>{{peer.server}}</h4> </div> <div class="col col-10 no-padding" ng-if="settings.expertMode"> diff --git a/www/templates/settings/popup_node.html b/www/templates/settings/popup_node.html index c1232d3b3bac6dee65679f6bb607e1f52fa26d54..313129bf1c5da560c441cd1509373e3fa3b4d0e6 100644 --- a/www/templates/settings/popup_node.html +++ b/www/templates/settings/popup_node.html @@ -1,12 +1,17 @@ <form name="popupForm" ng-submit=""> <div class="list" ng-init="setPopupForm(popupForm)"> - <label class="item item-input" - ng-class="{'item-input-error': popupForm.$submitted && popupForm.newNode.$invalid}"> - <input name="newNode" type="text" placeholder="{{'SETTINGS.NODE_HELP' | translate}}" - ng-model="popupData.newNode" - ng-minlength="3" - required> - </label> + <label class="item item-input" + ng-class="{'item-input-error': popupForm.$submitted && popupForm.newNode.$invalid}"> + <input name="newNode" type="text" placeholder="{{'SETTINGS.NODE_HELP' | translate}}" + ng-model="popupData.newNode" + ng-minlength="3" + required> + </label> + <button class="button-clear button-small gray pull-right" + ng-mousedown="showNodeList()">{{'SETTINGS.SHOW_NODE_LIST' | translate}} + <i class="icon-right ion-chevron-right gray"></i> + </button> + <div class="form-errors" ng-if="popupForm.$submitted && popupForm.newNode.$error" ng-messages="popupForm.newNode.$error"> @@ -19,3 +24,5 @@ </div> </div> </form> + +