angular.module('cesium.graph.network.controllers', ['chart.js', 'cesium.graph.services']) .config(function($stateProvider, PluginServiceProvider, csConfig) { 'ngInject'; var enable = csConfig.plugins && csConfig.plugins.es; if (enable) { PluginServiceProvider .extendState('app.network', { points: { 'blockchain-buttons': { templateUrl: "plugins/graph/templates/network/view_network_extend.html", controller: 'ESExtensionCtrl' } } }) .extendState('app.view_peer', { points: { 'general': { templateUrl: "plugins/graph/templates/network/view_peer_extend.html", controller: 'GpPeerViewExtendCtrl' } } }) .extendState('app.es_network', { points: { 'documents-buttons': { templateUrl: "plugins/graph/templates/network/view_es_network_extend.html", controller: 'ESExtensionCtrl' } } }) .extendState('app.view_es_peer', { points: { 'general': { templateUrl: "plugins/graph/templates/network/view_es_peer_extend.html", controller: 'ESExtensionCtrl' } } }) ; $stateProvider .state('app.view_peer_stats', { url: "/network/peer/:pubkey/stats", views: { 'menuContent': { templateUrl: "plugins/graph/templates/network/view_peer_stats.html", 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) { 'ngInject'; $scope.extensionPoint = PluginService.extensions.points.current.get(); $scope.enable = esSettings.isEnable(); $scope.loading = true; $scope.node = $scope.node || {}; esSettings.api.state.on.changed($scope, function(enable) { $scope.enable = enable; }); /** * Enter into the view * @param e * @param state */ $scope.enter = function(e, state) { if (!$scope.node.currency && state && state.stateParams && state.stateParams.currency) { // Currency parameter $scope.node.currency = state.stateParams.currency; } // Make sure there is currency, or load if not if (!$scope.node.currency) { return csCurrency.get() .then(function(currency) { $scope.node.currency = currency ? currency.name : null; return $scope.enter(e, state); }); } // Make sure there is pubkey, or wait for parent load to be finished if (!$scope.node.pubkey) { return $timeout(function () { return $scope.enter(e, state); }, 500); } // load return $scope.load(); }; $scope.$on('$csExtension.enter', $scope.enter); $scope.load = function() { if (!$scope.node.currency && !$scope.node.pubkey) return; console.info("[Graph] [peer] Loading blocks count for [{0}]".format($scope.node.pubkey.substr(0, 8))); return gpData.node.blockCount($scope.node.currency, $scope.node.pubkey) .then(function(count) { $scope.blockCount = count; $scope.loading = false; }); }; } 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) }); }); }; }