diff --git a/www/js/entities/peer.js b/www/js/entities/peer.js index 6672ba834b6a773841df4ab1c56084b8e21b7f84..91e7b6d131d4cf95804d9e4de425e49b5c8e672a 100644 --- a/www/js/entities/peer.js +++ b/www/js/entities/peer.js @@ -176,5 +176,5 @@ Peer.prototype.isBma = function() { }; Peer.prototype.hasBma = function() { - return this.hasEndpoint('(BASIC_MERKLE_API|BMAS|BMATOR)'); + return this.hasEndpoint('(BASIC_MERKLED_API|BMAS|BMATOR)'); }; diff --git a/www/plugins/es/js/controllers/document-controllers.js b/www/plugins/es/js/controllers/document-controllers.js index 3920f72075bc1fc20a0cf33c7705e3804e903cc5..54dc059ed6c40a367df0a8bd89e0f43fc16de512 100644 --- a/www/plugins/es/js/controllers/document-controllers.js +++ b/www/plugins/es/js/controllers/document-controllers.js @@ -6,7 +6,7 @@ angular.module('cesium.es.document.controllers', ['cesium.es.services']) $stateProvider .state('app.document_search', { - url: "/data/search/:index/:type?q", + url: "/data/search/:index/:type?q&sort", views: { 'menuContent': { templateUrl: "plugins/es/templates/document/lookup.html", @@ -47,8 +47,10 @@ function ESDocumentLookupController($scope, $ionicPopover, $location, $timeout, $scope.helptipPrefix = 'helptip-document'; $scope.compactMode = angular.isDefined($scope.compactMode) ? $scope.compactMode : true; $scope._source = $scope._source || ["issuer", "hash", "time", "creationTime", "title", "message", "recipient", - // Movement field: - "medianTime", "amount", "currency", "reference" + // Movement fields: + "medianTime", "amount", "currency", "reference", + // Pending fields: + "pubkey", "uid", "blockNumber" ]; $scope.showHeaders = angular.isDefined($scope.showHeaders) ? $scope.showHeaders : true; @@ -62,6 +64,14 @@ function ESDocumentLookupController($scope, $ionicPopover, $location, $timeout, $scope.entered = true; $scope.search.index = state.stateParams && state.stateParams.index || $scope.search.index; $scope.search.type = state.stateParams && state.stateParams.type || $scope.search.type; + $scope.search.text = state.stateParams && state.stateParams.q || $scope.search.text; + $scope.search.sort = state.stateParams && state.stateParams.sort || $scope.search.sort; + $scope.search.last = !$scope.search.text; + $scope.load(); + } + + // Reload only if params changed (.e.g if comes from a graph click) + else if (state.stateParams && state.stateParams.q && $scope.search.text !== state.stateParams.q) { $scope.search.text = state.stateParams && state.stateParams.q || $scope.search.text; $scope.search.last = !$scope.search.text; $scope.load(); diff --git a/www/plugins/graph/css/style.css b/www/plugins/graph/css/style.css index 0d97c8161095b32e210b86648283f901df7acfd3..7c0f14cff7bfd74150718ffb3911c95133796d76 100644 --- a/www/plugins/graph/css/style.css +++ b/www/plugins/graph/css/style.css @@ -3,7 +3,11 @@ Graph currency popover **********/ -.popover-graph-currency { +.popover-graph-range { height: 300px !important; max-width: 250px !important; } +.popover-graph-period { + height: 420px !important; + max-width: 250px !important; +} diff --git a/www/plugins/graph/i18n/locale-en-GB.json b/www/plugins/graph/i18n/locale-en-GB.json index d972514c8080e7603fe3884326ace68294ed5346..8a8bdfc7dd7ffcfad6bdc1c0a79621585d9af350 100644 --- a/www/plugins/graph/i18n/locale-en-GB.json +++ b/www/plugins/graph/i18n/locale-en-GB.json @@ -15,6 +15,15 @@ "HOUR": "Group by <b>hour</b>", "DAY": "Group by <b>day</b>", "MONTH": "Group by <b>month</b>" + }, + "MAX_AGE": { + "DAY": "For 24h", + "WEEK": "For a week", + "MONTH": "For a month", + "QUARTER": "For 3 months", + "SEMESTER": "For 6 months", + "YEAR": "For a year", + "FOREVER": "Forever" } }, "ACCOUNT": { @@ -49,7 +58,11 @@ "MONETARY_MASS_SHARE_LABEL": "Average per member", "UD_TITLE": "Evolution of the universal dividend", "MEMBERS_COUNT_TITLE": "Evolution of the number of members", - "MEMBERS_COUNT_LABEL": "Number of members" + "MEMBERS_COUNT_LABEL": "Number of members", + "MEMBERS_DELTA_TITLE": "variation in the number of members", + "IS_MEMBER_DELTA_LABEL": "Validated memberships", + "WAS_MEMBER_DELTA_LABEL": "Membership losses", + "PENDING_DELTA_LABEL": "Membership requests" }, "PEER": { "VIEW": { @@ -86,6 +99,24 @@ "TITLE": "Other documents", "HISTORY_DELETE": "Deletion of documents" } + }, + "SYNCHRO": { + "TITLE": "Synchronization statistics", + "COUNT": { + "TITLE": "Synchronized volume", + "INSERTS": "Insertions", + "UPDATES": "Updates", + "DELETES": "Deletions" + }, + "PEER": { + "TITLE": "Requested peers", + "ES_USER_API": "Peers with with user data", + "ES_SUBSCRIPTION_API": "Peers with subscription" + }, + "PERFORMANCE": { + "TITLE": "Execution performance", + "DURATION": "Execution time (ms)" + } } } } diff --git a/www/plugins/graph/i18n/locale-en.json b/www/plugins/graph/i18n/locale-en.json index d972514c8080e7603fe3884326ace68294ed5346..8a8bdfc7dd7ffcfad6bdc1c0a79621585d9af350 100644 --- a/www/plugins/graph/i18n/locale-en.json +++ b/www/plugins/graph/i18n/locale-en.json @@ -15,6 +15,15 @@ "HOUR": "Group by <b>hour</b>", "DAY": "Group by <b>day</b>", "MONTH": "Group by <b>month</b>" + }, + "MAX_AGE": { + "DAY": "For 24h", + "WEEK": "For a week", + "MONTH": "For a month", + "QUARTER": "For 3 months", + "SEMESTER": "For 6 months", + "YEAR": "For a year", + "FOREVER": "Forever" } }, "ACCOUNT": { @@ -49,7 +58,11 @@ "MONETARY_MASS_SHARE_LABEL": "Average per member", "UD_TITLE": "Evolution of the universal dividend", "MEMBERS_COUNT_TITLE": "Evolution of the number of members", - "MEMBERS_COUNT_LABEL": "Number of members" + "MEMBERS_COUNT_LABEL": "Number of members", + "MEMBERS_DELTA_TITLE": "variation in the number of members", + "IS_MEMBER_DELTA_LABEL": "Validated memberships", + "WAS_MEMBER_DELTA_LABEL": "Membership losses", + "PENDING_DELTA_LABEL": "Membership requests" }, "PEER": { "VIEW": { @@ -86,6 +99,24 @@ "TITLE": "Other documents", "HISTORY_DELETE": "Deletion of documents" } + }, + "SYNCHRO": { + "TITLE": "Synchronization statistics", + "COUNT": { + "TITLE": "Synchronized volume", + "INSERTS": "Insertions", + "UPDATES": "Updates", + "DELETES": "Deletions" + }, + "PEER": { + "TITLE": "Requested peers", + "ES_USER_API": "Peers with with user data", + "ES_SUBSCRIPTION_API": "Peers with subscription" + }, + "PERFORMANCE": { + "TITLE": "Execution performance", + "DURATION": "Execution time (ms)" + } } } } diff --git a/www/plugins/graph/i18n/locale-fr-FR.json b/www/plugins/graph/i18n/locale-fr-FR.json index b79de1bc79dd358fc8327b1b489a1434964095e0..47289779bc85625bc5c5d9ddd37a346bebc23f11 100644 --- a/www/plugins/graph/i18n/locale-fr-FR.json +++ b/www/plugins/graph/i18n/locale-fr-FR.json @@ -15,6 +15,15 @@ "HOUR": "Heure", "DAY": "Jour", "MONTH": "Mois" + }, + "MAX_AGE": { + "DAY": "Depuis 24h", + "WEEK": "Depuis une semaine", + "MONTH": "Depuis un mois", + "QUARTER": "Depuis 3 mois", + "SEMESTER": "Depuis 6 mois", + "YEAR": "Depuis un an", + "FOREVER": "Depuis toujours" } }, "ACCOUNT": { @@ -50,7 +59,6 @@ "TX_COUNT_TITLE": "Nombre de transactions écrites", "TX_COUNT_LABEL": "Nombre de transactions", "TX_AVG_BY_BLOCK": "Nombre moyen de transactions / bloc" - }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolution de la masse monétaire", @@ -58,7 +66,11 @@ "MONETARY_MASS_SHARE_LABEL": "Moyenne par membre", "UD_TITLE": "Evolution du dividende universel", "MEMBERS_COUNT_TITLE": "Evolution du nombre de membres", - "MEMBERS_COUNT_LABEL": "Nombre de membres" + "MEMBERS_COUNT_LABEL": "Nombre de membres", + "MEMBERS_DELTA_TITLE": "Variation du nombre de membres", + "IS_MEMBER_DELTA_LABEL": "Prises en compte d'adhésion", + "WAS_MEMBER_DELTA_LABEL": "Pertes d'adhésion", + "PENDING_DELTA_LABEL": "Demandes d'adhésion" }, "PEER": { "VIEW": { @@ -106,13 +118,18 @@ }, "PEER": { "TITLE": "Noeuds requêtés", - "ES_USER_API": "Noeuds données utilisateurs", - "ES_SUBSCRIPTION_API": "Noeuds services en ligne" + "ES_USER_API": "Noeuds avec données utilisateurs", + "ES_SUBSCRIPTION_API": "Noeuds avec services en ligne" }, "PERFORMANCE": { "TITLE": "Performances d'exécution", "DURATION": "Temps d'exécution (ms)" } + }, + "NETWORK": { + "TITLE": "Statistiques réseau", + "ENDPOINT_COUNT_TITLE": "Nombre de points d'accès", + "ENDPOINT_DELTA_TITLE": "Variation du nombre de points d'accès" } } } diff --git a/www/plugins/graph/js/controllers/blockchain-controllers.js b/www/plugins/graph/js/controllers/blockchain-controllers.js index d15f2650fc34bdef7a0a78be61c4d6d198d1470c..4488543b42b3368d4b09dbc0f6e0fd92b387608c 100644 --- a/www/plugins/graph/js/controllers/blockchain-controllers.js +++ b/www/plugins/graph/js/controllers/blockchain-controllers.js @@ -86,12 +86,11 @@ function GpBlockchainTxCountController($scope, $controller, $q, $state, $filter, if (!result || !result.times) return; // no data $scope.times = result.times; - var formatInteger = $filter('formatInteger'); var formatAmount = $filter('formatDecimal'); $scope.currencySymbol = $filter('currencySymbolNoHtml')($scope.formData.currency, $scope.formData.useRelative); // Data - if ($scope.formData.rangeDuration != 'hour') { + if ($scope.formData.rangeDuration !== 'hour') { $scope.data = [ result.amount, result.count @@ -207,13 +206,18 @@ function GpBlockchainIssuersController($scope, $controller, $q, $state, $transla // Initialize the super class and extend it. angular.extend(this, $controller('GpCurrencyAbstractCtrl', {$scope: $scope})); + // Change defaults + $scope.formData.maxAge = 'day'; + $scope.computeStartTimeByAge(); + $scope.load = function() { + return $q.all([ $translate([ 'GRAPH.BLOCKCHAIN.BLOCKS_ISSUERS_TITLE', 'GRAPH.BLOCKCHAIN.BLOCKS_ISSUERS_LABEL' ]), - gpData.blockchain.countByIssuer($scope.formData.currency) + gpData.blockchain.countByIssuer($scope.formData.currency, {startTime: $scope.formData.startTime}) ]) .then(function(result) { var translations = result[0]; diff --git a/www/plugins/graph/js/controllers/common-controllers.js b/www/plugins/graph/js/controllers/common-controllers.js index 042f35b185e4df76e82c9b9a86849fb80693ba20..2d6a0e1fdd0f18758182f603804acdd748bf47af 100644 --- a/www/plugins/graph/js/controllers/common-controllers.js +++ b/www/plugins/graph/js/controllers/common-controllers.js @@ -12,13 +12,12 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist useRelative: csSettings.data.useRelative, timePct: 100, rangeDuration: 'day', + maxAge: undefined, // forever firstBlockTime: 0, scale: 'linear', hide: [], beginAtZero: true }; - $scope.formData.useRelative = false; /*angular.isDefined($scope.formData.useRelative) ? - $scope.formData.useRelative : csSettings.data.useRelative;*/ $scope.scale = 'linear'; $scope.height = undefined; $scope.width = undefined; @@ -32,6 +31,21 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist $scope.enter = function (e, state) { if ($scope.loading) { + // Make sure there is currency, or load it not + if (!$scope.formData.currency) { + return csCurrency.get() + .then(function (currency) { + $scope.formData.currency = currency ? currency.name : null; + $scope.formData.firstBlockTime = currency ? _truncDate(currency.firstBlockTime) : 0; + if (!$scope.formData.firstBlockTime){ + console.warn('[graph] currency.firstBlockTime not loaded ! Should have been loaded by currrency service!'); + } + $scope.formData.currencyAge = _truncDate(moment().utc().unix()) - $scope.formData.firstBlockTime; + + return $scope.enter(e, state); // Loop + }); + } + if (state && state.stateParams) { // remember state, to be able to refresh location $scope.stateName = state && state.stateName; @@ -63,21 +77,6 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist // Should be override by subclasses $scope.init(e, state); - // Make sure there is currency, or load it not - if (!$scope.formData.currency) { - return csCurrency.get() - .then(function (currency) { - $scope.formData.currency = currency ? currency.name : null; - $scope.formData.firstBlockTime = currency ? _truncDate(currency.firstBlockTime) : 0; - if (!$scope.formData.firstBlockTime){ - console.warn('[graph] currency.firstBlockTime not loaded ! Should have been loaded by currrency service!'); - } - $scope.formData.currencyAge = _truncDate(moment().utc().unix()) - $scope.formData.firstBlockTime; - - return $scope.enter(e, state); - }); - } - $scope.load() // Should be override by subclasses .then(function () { // Update scale @@ -103,9 +102,9 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist $scope.stateParams = $scope.stateParams || {}; $scope.stateParams.t = ($scope.formData.timePct >= 0 && $scope.formData.timePct < 100) ? $scope.formData.timePct : undefined; - $scope.stateParams.stepUnit = $scope.formData.rangeDuration != 'day' ? $scope.formData.rangeDuration : undefined; + $scope.stateParams.stepUnit = $scope.formData.rangeDuration !== 'day' ? $scope.formData.rangeDuration : undefined; $scope.stateParams.hide = $scope.formData.hide && $scope.formData.hide.length ? $scope.formData.hide.join(',') : undefined; - $scope.stateParams.scale = $scope.formData.scale != 'linear' ?$scope.formData.scale : undefined; + $scope.stateParams.scale = $scope.formData.scale !== 'linear' ?$scope.formData.scale : undefined; $state.go($scope.stateName, $scope.stateParams, { reload: false, @@ -123,7 +122,7 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist // When parent view execute a refresh action $scope.$on('csView.action.refresh', function(event, context) { - if (!context || context == 'currency') { + if (!context || context === 'currency') { return $scope.load(); } }); @@ -152,7 +151,7 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist _.forEach($scope.options.scales.yAxes, function(yAxe, index) { yAxe.type = scale; yAxe.ticks = yAxe.ticks || {}; - if (scale == 'linear') { + if (scale === 'linear') { yAxe.ticks.beginAtZero = angular.isDefined($scope.formData.beginAtZero) ? $scope.formData.beginAtZero : true; delete yAxe.ticks.min; yAxe.ticks.callback = function(value) { @@ -176,7 +175,7 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist $scope.setRangeDuration = function(rangeDuration) { $scope.hideActionsPopover(); - if ($scope.formData && rangeDuration == $scope.formData.rangeDuration) return; + if ($scope.formData && rangeDuration === $scope.formData.rangeDuration) return; $scope.formData.rangeDuration = rangeDuration; @@ -192,6 +191,55 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist $scope.updateLocation(); }; + $scope.setMaxAge = function(maxAge) { + $scope.hideActionsPopover(); + if ($scope.formData && maxAge === $scope.formData.maxAge) return; + + $scope.formData.maxAge = maxAge; + + // Restore default values + delete $scope.formData.startTime; + delete $scope.formData.endTime; + delete $scope.formData.rangeDurationSec; + + $scope.computeStartTimeByAge(); // Compute formData.startTime + + // Reload data + $scope.load(); + // Update location + $scope.updateLocation(); + }; + + $scope.computeStartTimeByAge = function() { + if (!$scope.formData.maxAge) { + delete $scope.formData.startTime; // Forever + } + else { + var ageInSecond = 60 * 60; // one hour + switch ($scope.formData.maxAge) { + case 'day': + ageInSecond *= 24; + break; + case 'week': + ageInSecond *= 24 * 7; + break; + case 'month': + ageInSecond *= 24 * 365.25/12; + break; + case 'quarter': + ageInSecond *= 24 * 365.25/4; + break; + case 'semester': + ageInSecond *= 24 * 365.25/2; + break; + case 'year': + ageInSecond *= 24 * 365.25; + break; + } + $scope.formData.startTime = moment.utc().unix() - ageInSecond; + } + } + $scope.updateHiddenDataset = function(datasetOverride) { datasetOverride = datasetOverride || $scope.datasetOverride || {}; @@ -208,7 +256,7 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist var yAxisDatasetCount = _.filter(datasetOverride, function(dataset) { return dataset.yAxisID === yAxisID; }).length; - if (yAxisDatasetCount == 1) { + if (yAxisDatasetCount === 1) { yAxe.display = false; } } @@ -314,9 +362,10 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist /* -- Popover -- */ - $scope.showActionsPopover = function(event) { + $scope.showActionsPopover = function(event, options) { + var templateUrl = options && options.templateUrl || 'plugins/graph/templates/common/popover_range_actions.html'; UIUtils.popover.show(event, { - templateUrl: 'plugins/graph/templates/common/popover_range_actions.html', + templateUrl: templateUrl, scope: $scope, autoremove: true, afterShow: function(popover) { @@ -325,6 +374,11 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist }); }; + $scope.showPeriodPopover = function(event) { + return $scope.showActionsPopover(event, {templateUrl: 'plugins/graph/templates/common/popover_period_actions.html'}); + }; + + $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); diff --git a/www/plugins/graph/js/controllers/currency-controllers.js b/www/plugins/graph/js/controllers/currency-controllers.js index caaaadff7eeed90683e59b7c178c84350eeb370d..4311f863cea4fde19e64b27111ec16b6e9a64444 100644 --- a/www/plugins/graph/js/controllers/currency-controllers.js +++ b/www/plugins/graph/js/controllers/currency-controllers.js @@ -39,7 +39,7 @@ angular.module('cesium.graph.currency.controllers', ['chart.js', 'cesium.graph.s } }) .state('app.currency_stats_lg', { - url: "/currency/stats/lg?hide&scale", + url: "/currency/stats/lg?hide&scale&stepUnit&t", views: { 'menuContent': { templateUrl: "plugins/graph/templates/currency/view_stats_lg.html" @@ -86,6 +86,8 @@ angular.module('cesium.graph.currency.controllers', ['chart.js', 'cesium.graph.s .controller('GpCurrencyDUCtrl', GpCurrencyDUController) .controller('GpCurrencyMembersCountCtrl', GpCurrencyMembersCountController) + + .controller('GpCurrencyPendingCountCtrl', GpCurrencyPendingCountController) ; function GpCurrencyViewExtendController($scope, PluginService, UIUtils, esSettings) { @@ -134,7 +136,9 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran return $q.all([ $translate(['GRAPH.CURRENCY.MONETARY_MASS_TITLE', 'GRAPH.CURRENCY.MONETARY_MASS_LABEL', - 'GRAPH.CURRENCY.MONETARY_MASS_SHARE_LABEL']), + 'GRAPH.CURRENCY.MONETARY_MASS_SHARE_LABEL', + 'COMMON.DATE_SHORT_PATTERN', + 'COMMON.DATE_MONTH_YEAR_PATTERN']), gpData.blockchain.withDividend($scope.formData.currency, { from: from, size: size @@ -146,56 +150,51 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran if (!result || !result.times) return; $scope.times = result.times; - // Choose a date formatter, depending on the blocks period + // Compute the date pattern, depending on the blocks period var blocksPeriod = result.times[result.times.length-1] - result.times[0]; - var formatDate; - if (blocksPeriod < 31557600/* less than 1 year */) { - formatDate = $filter('medianDateShort'); - } - else { - formatDate = $filter('formatDateMonth'); //see #683 - } + var datePattern = (blocksPeriod < 31557600/* less than 1 year */) ? + translations['COMMON.DATE_SHORT_PATTERN'] : translations['COMMON.DATE_MONTH_YEAR_PATTERN']; var formatAmount = $filter('formatDecimal'); $scope.currencySymbol = $filter('currencySymbolNoHtml')($scope.formData.currency, $scope.formData.useRelative); // Data: relative var data = []; - if($scope.formData.useRelative) { + if ($scope.formData.useRelative) { // M/N data.push( - result.blocks.reduce(function(res, block) { - return res.concat(truncAmount(block.monetaryMass / block.dividend / block.membersCount)); - }, [])); + _.map(result.blocks, function(block) { + return truncAmount(block.monetaryMass / block.dividend / block.membersCount); + })); // Mass data.push( - result.blocks.reduce(function(res, block) { - return res.concat(truncAmount(block.monetaryMass / block.dividend)); - }, [])); + _.map(result.blocks, function(block) { + return truncAmount(block.monetaryMass / block.dividend); + })); } // Data: quantitative else { // M/N data.push( - result.blocks.reduce(function(res, block) { - return res.concat(truncAmount(block.monetaryMass / block.membersCount / 100)); - }, [])); + _.map(result.blocks, function(block) { + return truncAmount(block.monetaryMass / block.membersCount / 100); + })); // Mass data.push( - result.blocks.reduce(function(res, block) { - return res.concat(block.monetaryMass / 100); - }, [])); + _.map(result.blocks, function(block) { + return block.monetaryMass / 100; + })); } $scope.data = data; // Labels - $scope.labels = result.times.reduce(function(res, time) { - return res.concat(formatDate(time)); - }, []); + $scope.labels = _.map(result.times, function(time) { + return moment.unix(time).local().format(datePattern); + }); // Colors $scope.colors = gpColor.scale.fix(result.times.length); @@ -327,7 +326,9 @@ function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gp return $q.all([ $translate([ 'GRAPH.CURRENCY.UD_TITLE', - 'COMMON.UNIVERSAL_DIVIDEND']), + 'COMMON.UNIVERSAL_DIVIDEND', + 'COMMON.DATE_SHORT_PATTERN', + 'COMMON.DATE_MONTH_YEAR_PATTERN']), gpData.blockchain.withDividend($scope.formData.currency, { from: from, size: size @@ -341,28 +342,23 @@ function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gp // Choose a date formatter, depending on the blocks period var blocksPeriod = result.times[result.times.length-1] - result.times[0]; - var dateFilter; - if (blocksPeriod < 31557600/* less than 1 year */) { - dateFilter = $filter('medianDateShort'); - } - else { - dateFilter = $filter('formatDateMonth'); - } + var datePattern = (blocksPeriod < 31557600/* less than 1 year */) ? + translations['COMMON.DATE_SHORT_PATTERN'] : translations['COMMON.DATE_MONTH_YEAR_PATTERN']; var formatAmount = $filter('formatDecimal'); $scope.currencySymbol = $filter('currencySymbolNoHtml')($scope.formData.currency, false); // Data $scope.data = [ - result.blocks.reduce(function(res, block) { - return res.concat(block.dividend / 100); - }, []) + _.map(result.blocks, function(block) { + return block.dividend / 100; + }) ]; // Labels - $scope.labels = result.times.reduce(function(res, time) { - return res.concat(dateFilter(time)); - }, []); + $scope.labels = _.map(result.times, function(time) { + return moment.unix(time).local().format(datePattern); + }); // Colors $scope.colors = result.blocks.reduce(function(res) { @@ -453,7 +449,11 @@ function GpCurrencyMembersCountController($scope, $controller, $q, $state, $tran size = size || 10000; return $q.all([ - $translate(['GRAPH.CURRENCY.MEMBERS_COUNT_TITLE', 'GRAPH.CURRENCY.MEMBERS_COUNT_LABEL']), + $translate(['GRAPH.CURRENCY.MEMBERS_COUNT_TITLE', + 'GRAPH.CURRENCY.MEMBERS_COUNT_LABEL', + 'COMMON.DATE_SHORT_PATTERN', + 'COMMON.DATE_MONTH_YEAR_PATTERN' + ]), gpData.blockchain.withDividend($scope.formData.currency, { from: from, size: size, @@ -469,18 +469,18 @@ function GpCurrencyMembersCountController($scope, $controller, $q, $state, $tran // Choose a date formatter, depending on the blocks period var blocksPeriod = result.times[result.blocks.length-1] - result.times[0]; - var dateFilter; - if (blocksPeriod < 31557600/* less than 1 year*/) { - dateFilter = $filter('medianDateShort'); - } - else { - dateFilter = $filter('formatDateMonth'); - } + var datePattern = (blocksPeriod < 31557600/* less than 1 year */) ? + translations['COMMON.DATE_SHORT_PATTERN'] : translations['COMMON.DATE_MONTH_YEAR_PATTERN']; - // Format time - $scope.labels = result.times.reduce(function(res, time) { - return res.concat(dateFilter(time)); - }, []); + // Data + $scope.data = [ + _.pluck(result.blocks, 'membersCount') + ]; + + // Labels + $scope.labels = _.map(result.times, function(time) { + return moment.unix(time).local().format(datePattern); + }); // Members count graph: ------------------------- $scope.options = { @@ -512,12 +512,6 @@ function GpCurrencyMembersCountController($scope, $controller, $q, $state, $tran pointHoverRadius: 3 }]; - // Data - $scope.data = [ - result.blocks.reduce(function(res, block) { - return res.concat(block.membersCount); - }, []) - ]; // Colors $scope.colors = gpColor.scale.fix(result.blocks.length); @@ -539,3 +533,123 @@ function GpCurrencyMembersCountController($scope, $controller, $q, $state, $tran } + + +function GpCurrencyPendingCountController($scope, $controller, $q, $state, $translate, gpColor, esHttp) { + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('GpDocStatsCtrl', {$scope: $scope})); + + $scope.chartIdPrefix = 'currency-chart-pending-'; + + $scope.init = function(e, state) { + var currency = $scope.formData.currency; + if (!currency) throw Error('Missing formData.currency!'); + + $scope.formData.index = currency; + $scope.formData.types = ['member', 'pending']; + + $scope.charts = [ + + // Pending delta + { + id: currency + '_member_delta', + title: 'GRAPH.CURRENCY.MEMBERS_DELTA_TITLE', + series: [ + { + key: currency + '_is_member_delta', + label: 'GRAPH.CURRENCY.IS_MEMBER_DELTA_LABEL', + type: 'bar', + yAxisID: 'y-axis-delta', + color: gpColor.rgba.calm(), + pointHoverBackgroundColor: gpColor.rgba.calm(), + }, + { + key: currency + '_was_member_delta', + label: 'GRAPH.CURRENCY.WAS_MEMBER_DELTA_LABEL', + type: 'bar', + yAxisID: 'y-axis-delta', + color: gpColor.rgba.assertive(0.7), + pointHoverBackgroundColor: gpColor.rgba.assertive(), + }, + { + key: currency + '_pending_delta', + label: 'GRAPH.CURRENCY.PENDING_DELTA_LABEL', + type: 'line', + yAxisID: 'y-axis-delta', + color: gpColor.rgba.gray(0.5), + pointHoverBackgroundColor: gpColor.rgba.gray() + } + ] + }]; + + $scope.formData.queryNames = $scope.charts.reduce(function(res, chart){ + return chart.series.reduce(function(res, serie) { + var queryName = serie.key.replace(/_delta$/, ''); + return res.concat(queryName); + }, res); + }, []); + }; + + var inheritedLoad = $scope.load; + $scope.load = function() { + + // Call inherited load + return inheritedLoad() + .then(function() { + var chart = $scope.charts[0]; + + // Compute wasMember serie, using the is_member + if (chart.data[1]) { + chart.data[1] = _.map(chart.data[0], function(value) { + return value < 0 ? value : undefined; + }); + } + chart.data[0] = _.map(chart.data[0], function(value) { + return value >= 0 ? value : undefined; + }); + + $scope.chart = chart; + }); + }; + + $scope.onChartClick = function(data, e, item) { + if (!item) return; + + var from = $scope.times[item._index]; + var to = moment.unix(from).utc().add(1, $scope.formData.rangeDuration).unix(); + + var blockRequest = esHttp.get('/{0}/block/_search?pretty'.format($scope.formData.currency)); + // Get block min/max + return $q.all([ + // Get first (min) block + blockRequest({ + q: 'time:>={0} AND time:<={1}'.format(from, to), + sort: 'number:asc', + size: 1, + _source: ['number'] + }), + + // Get last (max) block + blockRequest({ + q: 'time:>={0} AND time:<={1}'.format(from, to), + sort: 'number:desc', + size: 1, + _source: ['number'] + }) + ]) + .then(function(res) { + var minBlockHit = res[0] && res[0].hits && res[0].hits.hits && res[0].hits.hits[0]; + var maxBlockHit = res[1] && res[1].hits && res[1].hits.hits && res[1].hits.hits[0]; + var minBlockNumber = minBlockHit ? minBlockHit._source.number : undefined; + var maxBlockNumber = maxBlockHit ? maxBlockHit._source.number : undefined; + return $state.go('app.document_search', { + index: $scope.formData.currency, + type: 'pending', + q: 'blockNumber:>={0} AND blockNumber:<{1}'.format(minBlockNumber, maxBlockNumber) + }); + }) + + }; +} diff --git a/www/plugins/graph/js/controllers/docstats-controllers.js b/www/plugins/graph/js/controllers/docstats-controllers.js index 7fe42911d7aab991b0239853586744f84d7dd2b0..a9f43470f32f2fee7fdcace287c0d7799b139252 100644 --- a/www/plugins/graph/js/controllers/docstats-controllers.js +++ b/www/plugins/graph/js/controllers/docstats-controllers.js @@ -262,6 +262,9 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol }; $scope.load = function(updateTimePct) { + updateTimePct = angular.isDefined(updateTimePct) ? updateTimePct : true; + + console.debug("[graph] Loading docstats data..."); return $q.all([ // Get i18n keys (chart title, series labels, date patterns) diff --git a/www/plugins/graph/js/controllers/network-controllers.js b/www/plugins/graph/js/controllers/network-controllers.js index 93cef43c1bf80d13b6d0731d9be60f6088736303..94152b139ecdaaf37661d23d24b6b66201277310 100644 --- a/www/plugins/graph/js/controllers/network-controllers.js +++ b/www/plugins/graph/js/controllers/network-controllers.js @@ -54,12 +54,25 @@ angular.module('cesium.graph.network.controllers', ['chart.js', 'cesium.graph.se controller: 'GpBlockchainTxCountCtrl' } } + }) + + .state('app.network_stats', { + url: "/network/stats?stepUnit&t&hide&scale", + views: { + 'menuContent': { + templateUrl: "plugins/graph/templates/network/view_stats.html", + controller: 'GpNetworkStatsCtrl' + } + } }); } }) .controller('GpPeerViewExtendCtrl', GpPeerViewExtendController) + .controller('GpNetworkStatsCtrl', GpNetworkStatsController) + + ; function GpPeerViewExtendController($scope, $timeout, PluginService, esSettings, csCurrency, gpData) { @@ -117,3 +130,133 @@ function GpPeerViewExtendController($scope, $timeout, PluginService, esSettings, }); }; } + + +function GpNetworkStatsController($scope, $controller, $q, $state, $translate, gpColor, esHttp) { + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('GpDocStatsCtrl', {$scope: $scope})); + + $scope.chartIdPrefix = 'network-chart-stats-'; + $scope.apis = [ + { + name: 'BASIC_MERKLED_API', + color: gpColor.rgba.calm() + }, + { + name: 'BMAS', + color: gpColor.rgba.calm() + }, + { + name: 'BMATOR', + color: gpColor.rgba.calm() + }, + { + name: 'WS2P', + color: gpColor.rgba.balanced() + }, + { + name: 'GVA', + color: gpColor.rgba.energized() + }, + { + name: 'GVASUB', + color: gpColor.rgba.energized() + } + ]; + + var inheritedInit = $scope.init; + $scope.init = function(e, state) { + var currency = $scope.formData.currency; + if (!currency) throw Error('Missing formData.currency!'); + + inheritedInit(e, state); + + if (state && state.stateParams) { + + } + + $scope.formData.index = currency; + $scope.formData.types = ['peer']; + + $scope.charts = [ + + // Count by api + { + id: currency + '_peer', + title: 'GRAPH.NETWORK.ENDPOINT_COUNT_TITLE', + series: _.map($scope.apis, function (api) { + return { + key: currency + '_peer_' + api.name.toLowerCase(), + label: api.name, + color: api.color, + pointHoverBackgroundColor: api.color, + }; + }) + }, + + // Delta by api + { + id: currency + '_peer_delta', + title: 'GRAPH.NETWORK.ENDPOINT_DELTA_TITLE', + series: _.map($scope.apis, function (api) { + return { + key: currency + '_peer_' + api.name.toLowerCase() + '_delta', + label: api.name, + type: 'line', + yAxisID: 'y-axis-delta', + color: api.color, + pointHoverBackgroundColor: api.color, + }; + }) + } + ]; + + $scope.formData.queryNames = $scope.charts.reduce(function(res, chart){ + return chart.series.reduce(function(res, serie) { + var queryName = serie.key.replace(/_delta$/, ''); + return res.concat(queryName); + }, res); + }, []); + }; + + $scope.onChartClick = function(data, e, item) { + if (!item) return; + + var from = $scope.times[item._index]; + var to = moment.unix(from).utc().add(1, $scope.formData.rangeDuration).unix(); + + var blockRequest = esHttp.get('/{0}/block/_search?pretty'.format($scope.formData.currency)); + // Get block min/max + return $q.all([ + // Get first (min) block + blockRequest({ + q: 'time:>={0} AND time:<={1}'.format(from, to), + sort: 'number:asc', + size: 1, + _source: ['number'] + }), + + // Get last (max) block + blockRequest({ + q: 'time:>={0} AND time:<={1}'.format(from, to), + sort: 'number:desc', + size: 1, + _source: ['number'] + }) + ]) + .then(function(res) { + var minBlockHit = res[0] && res[0].hits && res[0].hits.hits && res[0].hits.hits[0]; + var maxBlockHit = res[1] && res[1].hits && res[1].hits.hits && res[1].hits.hits[0]; + var minBlockNumber = minBlockHit ? minBlockHit._source.number : undefined; + var maxBlockNumber = maxBlockHit ? maxBlockHit._source.number : undefined; + return $state.go('app.document_search', { + index: $scope.formData.currency, + type: 'peer', + q: 'blockNumber:>={0} AND blockNumber:<{1}'.format(minBlockNumber, maxBlockNumber) + }); + }) + + }; +} diff --git a/www/plugins/graph/js/services/data-services.js b/www/plugins/graph/js/services/data-services.js index 8c9ba109c32ab893aa1369939654c8709f4729b5..84be0b0c186e3179389b66713bc41d64206dc0dc 100644 --- a/www/plugins/graph/js/services/data-services.js +++ b/www/plugins/graph/js/services/data-services.js @@ -58,13 +58,13 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es. } function _initRangeOptions(options) { - options = options || {}; + options = angular.copy(options); options.maxRangeSize = options.maxRangeSize || 30; options.defaultTotalRangeCount = options.defaultTotalRangeCount || options.maxRangeSize*2; options.rangeDuration = options.rangeDuration || 'day'; - options.endTime = options.endTime || moment().utc().add(1, options.rangeDuration).unix(); - options.startTime = options.startTime || + options.endTime = angular.isDefined(options.endTime) ? options.endTime : moment().utc().add(1, options.rangeDuration).unix(); + options.startTime = angular.isDefined(options.startTime) ? options.startTime : moment.unix(options.endTime).utc().subtract(options.defaultTotalRangeCount, options.rangeDuration).unix(); // Make to sure startTime is never before the currency starts - fix #483 if (options.firstBlockTime && options.startTime < options.firstBlockTime) { @@ -73,12 +73,48 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es. return options; } + function _getManyRanges(options) { + + var from = moment.unix(options.startTime).utc().startOf(options.rangeDuration); + var to = moment.unix(options.endTime).utc().startOf(options.rangeDuration); + var result = []; + var ranges = []; + while (from.isBefore(to)) { + + ranges.push({ + from: from.unix(), + to: from.add(1, options.rangeDuration).unix() + }); + + // Flush if max range count, or just before loop condition end (fix #483) + var flush = (ranges.length === options.maxRangeSize) || !from.isBefore(to); + if (flush) { + result.push(ranges); + ranges = []; + } + } + + if (ranges.length) { + result.push(ranges); + } + + return result; + } + /** * Graph: "blocks count by issuer" * @param currency * @returns {*} */ - exports.blockchain.countByIssuer = function(currency) { + exports.blockchain.countByIssuer = function(currency, options) { + options = options || {}; + + var filters = []; + if (options.startTime > 0) { + // Round to hour, to be able to use cache + var startTime = Math.floor(options.startTime / 60 / 60 ) * 60 * 60; + filters.push({range: {time: {gte: startTime}}}); + } var request = { size: 0, @@ -92,7 +128,17 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es. } }; - return exports.raw.block.search(request, {currency: currency}) + if (filters.length) { + request.query = {bool: {}}; + request.query.bool.filter = filters; + } + + var params = { + currency: currency, + request_cache: angular.isDefined(options.cache) ? options.cache : true // enable by default + }; + + return exports.raw.block.search(request, params) .then(function(res) { var aggs = res.aggregations; if (!aggs.blocksByIssuer || !aggs.blocksByIssuer.buckets || !aggs.blocksByIssuer.buckets.length) return; @@ -695,7 +741,6 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es. options = _initRangeOptions(options); - var searchRequest = exports.raw.docstat.search; if (options.server) { var serverParts = options.server.split(':'); var host = serverParts[0]; @@ -703,96 +748,123 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es. searchRequest = rawLightInstance(host, port, options.useSsl).docstat.search; } - var jobs = []; - - var from = moment.unix(options.startTime).utc().startOf(options.rangeDuration); - var to = moment.unix(options.endTime).utc().startOf(options.rangeDuration); - var ranges = []; - - var processSearchResult = function (res) { - var aggs = res.aggregations; - return (aggs.range && aggs.range.buckets || []).reduce(function (res, agg) { - var item = { - from: agg.from, - to: agg.to - }; - _.forEach(agg.index && agg.index.buckets || [], function (agg) { - var index = agg.key; - _.forEach(agg.type && agg.type.buckets || [], function (agg) { - var key = (index + '_' + agg.key); - item[key] = agg.max.value; - if (!indices[key]) indices[key] = true; - }); - }); - return res.concat(item); - }, []); + var filters = []; + if (options.index) { + console.debug('[graph] filter on index:', options.index); + filters.push({term : { index: options.index}}); + } + if (options.types) { + console.debug('[graph] filter on types:', options.types); + filters.push({terms : { type: options.types}}); + } + var request = { + size: 0, + aggs: { + range: { + range: { + field: "time", + ranges: [] // Will be replace + } + } + } }; - while(from.isBefore(to)) { - ranges.push({ - from: from.unix(), - to: from.add(1, options.rangeDuration).unix() - }); - - // Flush if max range count, or just before loop condition end (fix #483) - var flush = (ranges.length === options.maxRangeSize) || !from.isBefore(to); - if (flush) { - var request = { - size: 0, + if (options.queryNames) { + console.debug('[graph] filter on queryNames:', options.queryNames); + filters.push({terms : { queryName: options.queryNames }}); + request.aggs.range.aggs = { + queryName: { + terms: { + field: "queryName", + size: 0 + }, aggs: { - range: { - range: { - field: "time", - ranges: ranges + max: { + max: { + field: "count" + } + } + } + } + }; + } + else { + request.aggs.range.aggs = { + index: { + terms: { + field: "index", + size: 0 + }, + aggs: { + type: { + terms: { + field: "type", + size: 0 }, aggs: { - index : { - terms: { - field: "index", - size: 0 - }, - aggs: { - type: { - terms: { - field: "type", - size: 0 - }, - aggs: { - max: { - max: { - field : "count" - } - } - } - } + max: { + max: { + field: "count" } } } } } + } + }; + } - }; + // Add filter on request + if (filters.length > 0) { + request.query = request.query || {}; + request.query.bool = request.query.bool || {}; + request.query.bool.filter = filters; + } - // prepare next loop - ranges = []; - var indices = {}; - var params = { - request_cache: angular.isDefined(options.cache) ? options.cache : true // enable by default - }; + var params = { + request_cache: angular.isDefined(options.cache) ? options.cache : true // enable by default + }; - if (jobs.length === 10) { - console.error('Too many parallel jobs!'); - from = moment.unix(options.endTime).utc(); // stop while + var indices = {}; + var processSearchResult = function (res) { + var aggs = res.aggregations; + return _.map(aggs.range && aggs.range.buckets || [], function (agg) { + var item = { from: agg.from, to: agg.to }; + if (agg.queryName) { + _.forEach(agg.queryName && agg.queryName.buckets || [], function (agg) { + var key = agg.key; + item[key] = agg.max.value; + if (!indices[key]) indices[key] = true; + }); } - else { - jobs.push( - searchRequest(request, params) - .then(processSearchResult) - ); + else{ + _.forEach(agg.index && agg.index.buckets || [], function (agg) { + var key = agg.key; + if (agg.max) { + item[key] = agg.max.value; + if (!indices[key]) indices[key] = true; + } else { + _.forEach(agg.type && agg.type.buckets || [], function (agg) { + var typeKey = key + '_' + agg.key; + item[typeKey] = agg.max.value; + if (!indices[typeKey]) indices[typeKey] = true; + }); + } + }); } - } - } // loop + return item; + }); + }; + + var jobs = _.map(_getManyRanges(options), function(ranges) { + var req = angular.copy(request); + req.aggs.range.range.ranges = ranges; + + // Execute request + return exports.raw.docstat.search(req, params) + .then(processSearchResult); + }); return $q.all(jobs) .then(function(res) { diff --git a/www/plugins/graph/templates/blockchain/graph_block_issuers.html b/www/plugins/graph/templates/blockchain/graph_block_issuers.html index c97178f57a54362cd3abb6ccf35b1a5ecb0d8e53..13811de9e74e4faf67c90070a6ce19a400011c0e 100644 --- a/www/plugins/graph/templates/blockchain/graph_block_issuers.html +++ b/www/plugins/graph/templates/blockchain/graph_block_issuers.html @@ -3,6 +3,16 @@ <!-- bar --> <div class="col col-75"> + <!-- graphs button bar --> + <div class="button-bar-inline " + style="top: 33px; margin-top:-33px; position: relative;"> + <button + class="button button-stable button-clear no-padding-xs no-padding-sm pull-right" + ng-click="showPeriodPopover($event)"> + <i class="icon ion-navicon-round"></i> + </button> + </div> + <canvas id="bar" class="chart-bar" height="{{height}}" width="{{width}}" chart-data="data" diff --git a/www/plugins/graph/templates/blockchain/view_stats.html b/www/plugins/graph/templates/blockchain/view_stats.html index a3393e1be780428d30d246e3e26bf7382bc0e873..3f979b725584510862ae66376f75745220ab997e 100644 --- a/www/plugins/graph/templates/blockchain/view_stats.html +++ b/www/plugins/graph/templates/blockchain/view_stats.html @@ -35,7 +35,10 @@ <!-- Blocks issuer --> <ng-controller ng-controller="GpBlockchainIssuersCtrl"> - <div class="item item-divider" ng-if="!loading" translate>GRAPH.BLOCKCHAIN.BLOCKS_ISSUERS_DIVIDER</div> + <div class="item item-divider" ng-if="!loading"> + <span translate>GRAPH.BLOCKCHAIN.BLOCKS_ISSUERS_DIVIDER</span> + <span ng-if="formData.maxAge">({{'GRAPH.COMMON.MAX_AGE.' + formData.maxAge | uppercase | translate | lowercase }})</span> + </div> <div class="item no-padding-xs no-padding-sm" ng-if="!loading" diff --git a/www/plugins/graph/templates/common/popover_period_actions.html b/www/plugins/graph/templates/common/popover_period_actions.html new file mode 100644 index 0000000000000000000000000000000000000000..3496b64f89272c191635e676bf55416769e84e14 --- /dev/null +++ b/www/plugins/graph/templates/common/popover_period_actions.html @@ -0,0 +1,47 @@ +<ion-popover-view class="has-header popover-graph-period"> + <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"> + + <!-- each durations --> + <a class="item item-icon-left ink" + ng-click="setMaxAge('day')"> + <i class="icon ion-ios-checkmark-empty" ng-show="formData.maxAge==='day'"></i> + <span translate>GRAPH.COMMON.MAX_AGE.DAY</span> + </a> + <a class="item item-icon-left ink" + ng-click="setMaxAge('week')"> + <i class="icon ion-ios-checkmark-empty" ng-show="formData.maxAge==='week'"></i> + <span translate>GRAPH.COMMON.MAX_AGE.WEEK</span> + </a> + <a class="item item-icon-left ink" + ng-click="setMaxAge('month')"> + <i class="icon ion-ios-checkmark-empty" ng-show="formData.maxAge==='month'"></i> + <span translate>GRAPH.COMMON.MAX_AGE.MONTH</span> + </a> + <a class="item item-icon-left ink" + ng-click="setMaxAge('quarter')"> + <i class="icon ion-ios-checkmark-empty" ng-show="formData.maxAge==='quarter'"></i> + <span translate>GRAPH.COMMON.MAX_AGE.QUARTER</span> + </a> + <a class="item item-icon-left ink" + ng-click="setMaxAge('semester')"> + <i class="icon ion-ios-checkmark-empty" ng-show="formData.maxAge==='semester'"></i> + <span translate>GRAPH.COMMON.MAX_AGE.SEMESTER</span> + </a> + <a class="item item-icon-left ink" + ng-click="setMaxAge('year')"> + <i class="icon ion-ios-checkmark-empty" ng-show="formData.maxAge==='year'"></i> + <span translate>GRAPH.COMMON.MAX_AGE.YEAR</span> + </a> + <a class="item item-icon-left ink" + ng-click="setMaxAge()"> + <i class="icon ion-ios-checkmark-empty" ng-show="!formData.maxAge"></i> + <span translate>GRAPH.COMMON.MAX_AGE.FOREVER</span> + </a> + + </div> + </ion-content> +</ion-popover-view> diff --git a/www/plugins/graph/templates/common/popover_range_actions.html b/www/plugins/graph/templates/common/popover_range_actions.html index cf8893b84273e2c61fda7be7293a90257aad453d..5b977aaa4a498551260a556a3ff1c9561c2722df 100644 --- a/www/plugins/graph/templates/common/popover_range_actions.html +++ b/www/plugins/graph/templates/common/popover_range_actions.html @@ -1,4 +1,4 @@ -<ion-popover-view class="has-header popover-graph-currency"> +<ion-popover-view class="has-header popover-graph-range"> <ion-header-bar> <h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1> </ion-header-bar> @@ -8,7 +8,7 @@ <!-- scale --> <a class="item item-icon-left ink" ng-click="toggleScale()"> - <i class="icon ion-ios-checkmark-empty" ng-show="formData.scale=='logarithmic'"></i> + <i class="icon ion-ios-checkmark-empty" ng-show="formData.scale==='logarithmic'"></i> <span ng-bind-html="'GRAPH.COMMON.LOGARITHMIC_SCALE' | translate"></span> </a> @@ -20,21 +20,21 @@ <!-- duration: hour --> <a class="item item-icon-left ink" ng-click="setRangeDuration('hour')"> - <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration=='hour'"></i> + <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration==='hour'"></i> <span ng-bind-html="'GRAPH.COMMON.RANGE_DURATION.HOUR' | translate"></span> </a> <!-- duration: day --> <a class="item item-icon-left ink" ng-click="setRangeDuration('day')"> - <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration=='day'"></i> + <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration==='day'"></i> <span ng-bind-html="'GRAPH.COMMON.RANGE_DURATION.DAY' | translate"></span> </a> <!-- duration: month --> <a class="item item-icon-left ink" ng-click="setRangeDuration('month')"> - <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration=='month'"></i> + <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration==='month'"></i> <span ng-bind-html="'GRAPH.COMMON.RANGE_DURATION.MONTH' | translate"></span> </a> diff --git a/www/plugins/graph/templates/currency/tabs/tab_network_stats.html b/www/plugins/graph/templates/currency/tabs/tab_network_stats.html index ec8f5c0d6f3b465e2fbf0bd14c0bf32ead818287..184d0bc9f8245cd9c2cff816e5464c4d3f2242ee 100644 --- a/www/plugins/graph/templates/currency/tabs/tab_network_stats.html +++ b/www/plugins/graph/templates/currency/tabs/tab_network_stats.html @@ -3,8 +3,8 @@ <div class="list"> <div class="item" - ng-include="::'plugins/graph/templates/blockchain/graph_block_issuers.html'" - ng-controller="GpBlockchainIssuersCtrl" + ng-controller="GpBlockchainIssuersCtrl" + ng-include="::'plugins/graph/templates/blockchain/graph_block_issuers.html'" ng-init="setSize(500,700,true)"> </div> </div> diff --git a/www/plugins/graph/templates/currency/tabs/tab_wot_stats.html b/www/plugins/graph/templates/currency/tabs/tab_wot_stats.html index 336648d439f068b50e7f1c945fe53bd218147c89..d9c3f0aa94543a2a987df3e8d6fcfa1d41639d1b 100644 --- a/www/plugins/graph/templates/currency/tabs/tab_wot_stats.html +++ b/www/plugins/graph/templates/currency/tabs/tab_wot_stats.html @@ -5,10 +5,19 @@ </div> <div class="list no-padding"> - <div class="item no-padding-top" - ng-include="::'plugins/graph/templates/currency/graph_members_count.html'" - ng-init="setSize(600,700,false)"> - </div> + <ng-controller ng-controller="GpCurrencyMembersCountCtrl" > + <div class="item no-padding-top" + ng-include="::'plugins/graph/templates/currency/graph_members_count.html'" + ng-init="setSize(600,700,false)"> + </div> + </ng-controller> + + <ng-controller ng-controller="GpCurrencyPendingCountCtrl" > + <div class="item" + ng-include="::'plugins/graph/templates/docstats/graph.html'" + ng-init="setSize(600,700,false)"> + </div> + </ng-controller> </div> </ion-content> </ion-view> diff --git a/www/plugins/graph/templates/currency/view_currency_extend.html b/www/plugins/graph/templates/currency/view_currency_extend.html index 556ed85c2a02b2d7c1894c38c66277b4b1901747..51c1ce92a9d46f43c5765d10510ae30d4ba79a30 100644 --- a/www/plugins/graph/templates/currency/view_currency_extend.html +++ b/www/plugins/graph/templates/currency/view_currency_extend.html @@ -1,5 +1,5 @@ -<!-- section actual parameters --> +<!-- section parameters --> <ng-if ng-if=":state:enable && extensionPoint === 'parameters-actual'" > <ng-if ng-if="!smallscreen"> @@ -50,7 +50,7 @@ </div> </ng-if> -<!-- section Wot --> +<!-- section Network --> <ng-if ng-if=":state:enable && extensionPoint === 'network-actual'" > <div class="item padding-left padding-right no-padding-xs no-padding-sm" diff --git a/www/plugins/graph/templates/currency/view_stats_lg.html b/www/plugins/graph/templates/currency/view_stats_lg.html index bf1c64ca43743e54fd8cf82f92e65c73d4927e34..af97abeba0b89221ca9e0e4a908eb050cdfd3e0a 100644 --- a/www/plugins/graph/templates/currency/view_stats_lg.html +++ b/www/plugins/graph/templates/currency/view_stats_lg.html @@ -45,12 +45,21 @@ <!-- Member count --> <ng-controller ng-controller="GpCurrencyMembersCountCtrl" > - <div class="item no-padding-xs" - ng-if="!loading" - ng-include="::'plugins/graph/templates/currency/graph_members_count.html'" - ng-init="setSize(250, 1000)"> - </div> + <div class="item no-padding-xs" + ng-if="!loading" + ng-include="::'plugins/graph/templates/currency/graph_members_count.html'" + ng-init="setSize(250, 1000)"> + </div> + </ng-controller> + <!-- Pending count --> + <ng-controller ng-controller="GpCurrencyPendingCountCtrl" > + <div class="item no-padding-xs" + ng-if="chart" + ng-include="::'plugins/graph/templates/docstats/graph.html'" + ng-init="setSize(250, 1000)"> + </div> + </ng-controller> </div> diff --git a/www/plugins/graph/templates/network/view_peer_stats.html b/www/plugins/graph/templates/network/view_peer_stats.html index 92845974ddb9056bf62dfb981e58bff8cb0d0453..b68d2654c4094514527c55114dd111b47f20a9bc 100644 --- a/www/plugins/graph/templates/network/view_peer_stats.html +++ b/www/plugins/graph/templates/network/view_peer_stats.html @@ -12,7 +12,6 @@ <div class="list" ng-if="!loading"> - <!-- - - - - TX divider - - - - --> <div class="item item-divider hidden-xs hidden-sm" translate> GRAPH.BLOCKCHAIN.TX_DIVIDER </div> diff --git a/www/plugins/graph/templates/network/view_stats.html b/www/plugins/graph/templates/network/view_stats.html new file mode 100644 index 0000000000000000000000000000000000000000..ab547029d33855bd0231b9ed5420300ba92807f1 --- /dev/null +++ b/www/plugins/graph/templates/network/view_stats.html @@ -0,0 +1,26 @@ +<ion-view left-buttons="leftButtons" + cache-view="false"> + <ion-nav-title> + {{'GRAPH.NETWORK.TITLE' | translate}} + </ion-nav-title> + + <ion-content scroll="true" class="no-padding" > + + <div class="center padding" ng-if="loading"> + <ion-spinner icon="android"></ion-spinner> + </div> + + <div class="list" ng-show="!loading"> + + <!-- charts --> + <div class="item no-padding-xs" + ng-repeat="chart in charts" + ng-include="::'plugins/graph/templates/docstats/graph.html'" + ng-init="setSize(250, 1000)"> + </div> + + </div> + + </ion-content> + +</ion-view>