Mario Colque
11 years ago
10 changed files with 7 additions and 3502 deletions
@ -1,480 +0,0 @@ |
|||
'use strict'; |
|||
// Source: public/src/css/common.css |
|||
/* Sticky footer styles |
|||
-------------------------------------------------- */ |
|||
html, |
|||
body { |
|||
color: #373D42; |
|||
font-family: 'Ubuntu', sans-serif; |
|||
height: 100%; |
|||
/* The html and body elements cannot have any padding or margin. */ |
|||
} |
|||
|
|||
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { |
|||
color: #373D42; |
|||
font-family: 'Ubuntu', sans-serif; |
|||
} |
|||
|
|||
/* Wrapper for page content to push down footer */ |
|||
#wrap { |
|||
min-height: 100%; |
|||
height: auto; |
|||
/* Negative indent footer by its height */ |
|||
margin: 0 auto -51px; |
|||
/* Pad bottom by footer height */ |
|||
padding: 0 0 75px; |
|||
} |
|||
|
|||
.m10h { margin: 0 10px; } |
|||
.m20h { margin: 0 20px; } |
|||
.m5v { margin: 5px 0; } |
|||
.m20v { margin: 20px 0; } |
|||
.m10v { margin: 10px 0; } |
|||
.m50v { margin: 50px 0; } |
|||
.m10b { margin-bottom: 10px; } |
|||
|
|||
.vm { vertical-align: middle; } |
|||
|
|||
.navbar-default { |
|||
background-color: #8DC429; |
|||
border-bottom: 4px solid #64920F; |
|||
} |
|||
|
|||
.navbar-default .navbar-nav>li>a { |
|||
color: #F4FBE8; |
|||
font-family: 'Ubuntu', sans-serif; |
|||
} |
|||
|
|||
.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:focus, .navbar-default .navbar-nav>li>a:hover { |
|||
background-color: #fff; |
|||
-webkit-box-shadow: 0px 4px 0px 0px rgba(55,61,56,1); |
|||
-moz-box-shadow: 0px 4px 0px 0px rgba(55,61,56,1); |
|||
box-shadow: 0px 4px 0px 0px rgba(55,61,56,1); |
|||
color: #373D42; |
|||
} |
|||
|
|||
.navbar-form .form-group { |
|||
display: block; |
|||
} |
|||
|
|||
.navbar-form { |
|||
width: 35%; |
|||
} |
|||
|
|||
@media (max-width: 991px) { |
|||
.status { |
|||
margin: 0; |
|||
} |
|||
.navbar-form { |
|||
width: 25%; |
|||
} |
|||
} |
|||
|
|||
@media (max-width: 768px) { |
|||
.navbar-form { |
|||
width: auto; |
|||
} |
|||
} |
|||
|
|||
.nav-tabs.nav-justified>li>a:hover { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.insight { |
|||
font-family: 'Ubuntu', sans-serif; |
|||
font-size: 34px; |
|||
font-style: italic; |
|||
font-weight: 400; |
|||
} |
|||
|
|||
.navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus { |
|||
color: #fffffe; |
|||
} |
|||
|
|||
.navbar-default .navbar-brand { |
|||
color: #FFFFFF; |
|||
} |
|||
|
|||
.navbar-form .form-control { |
|||
background-color: #7CAD23; |
|||
border-radius: 3px; |
|||
-webkit-border-radius: 3px; |
|||
-moz-border-radius: 3px; |
|||
border: 0; |
|||
-webkit-box-shadow: 1px 1px 0px 0px rgba(255,255,255,0.41), inset 1px 1px 3px 0px rgba(0,0,0,0.10); |
|||
-moz-box-shadow: 1px 1px 0px 0px rgba(255,255,255,0.41), inset 1px 1px 3px 0px rgba(0,0,0,0.10); |
|||
box-shadow: 1px 1px 0px 0px rgba(255,255,255,0.41), inset 1px 1px 3px 0px rgba(0,0,0,0.10); |
|||
} |
|||
|
|||
#search { |
|||
color: #fff; |
|||
font-family: 'Ubuntu', sans-serif; |
|||
} |
|||
|
|||
#search::-webkit-input-placeholder { |
|||
color: #BCDF7E; |
|||
font-family: 'Ubuntu', sans-serif; |
|||
font-size: 14px; |
|||
font-style: italic; |
|||
font-weight: 100; |
|||
} |
|||
|
|||
#search::-moz-placeholder { |
|||
color: #BCDF7E; |
|||
font-family: 'Ubuntu', sans-serif; |
|||
font-size: 14px; |
|||
font-weight: 100; |
|||
} |
|||
|
|||
.status { |
|||
-moz-border-radius: 3px; |
|||
-webkit-border-radius: 3px; |
|||
background-color: #597338; |
|||
border-radius: 3px; |
|||
margin: 8px 0; |
|||
padding: 8px 10px; |
|||
font-size: 12px; |
|||
color: #eee; |
|||
text-align: center; |
|||
} |
|||
|
|||
.status .tooltip { |
|||
margin: 0; |
|||
} |
|||
|
|||
.col-gray { |
|||
-moz-border-radius: 5px; |
|||
-webkit-border-radius: 5px; |
|||
background-color: #F4F4F4; |
|||
border-radius: 5px; |
|||
padding: 14px; |
|||
} |
|||
|
|||
.col-gray-responsive { |
|||
width: auto; |
|||
} |
|||
|
|||
.col-gray-fixed { |
|||
position: fixed; |
|||
width: 250px; |
|||
} |
|||
|
|||
@media (max-width: 768px) { |
|||
.col-gray-fixed { |
|||
width:100%; |
|||
} |
|||
} |
|||
|
|||
@media (max-width: 995px) { |
|||
.col-gray-fixed { |
|||
position:static; |
|||
width: 100%; |
|||
} |
|||
} |
|||
|
|||
@media (min-width: 1200px) { |
|||
.col-gray-fixed { |
|||
width: 280px; |
|||
} |
|||
} |
|||
|
|||
.ellipsis { |
|||
display: block; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
white-space: nowrap; |
|||
} |
|||
|
|||
.line20 { |
|||
border: 1px solid #D4D4D4; |
|||
margin-bottom: 15px; |
|||
} |
|||
|
|||
.line10 { |
|||
border: 1px solid #EAEAEA; |
|||
margin: 10px 0; |
|||
} |
|||
|
|||
.block-id { |
|||
background-color: #373D42; |
|||
border: 3px solid #FFFFFF; |
|||
margin: 0 auto; |
|||
width: 165px; |
|||
color: #fff; |
|||
text-align: center; |
|||
font-size: 80px; |
|||
} |
|||
|
|||
.block-id span { |
|||
margin-top: 10px; |
|||
} |
|||
|
|||
.block-id h2 { |
|||
color: #FFFFFF; |
|||
font-weight: bold; |
|||
line-height: 30px; |
|||
font-size: 24px; |
|||
margin-top: 0; |
|||
margin-bottom: 10px; |
|||
} |
|||
|
|||
.icon-block { |
|||
color: #FFFFFF; |
|||
font-size: 35px; |
|||
margin-top: 10px; |
|||
} |
|||
|
|||
.icon-block h3 { |
|||
color: #fff; |
|||
} |
|||
|
|||
.block-tx { |
|||
-moz-border-radius: 2px; |
|||
-webkit-border-radius: 2px; |
|||
background-color: #F4F4F4; |
|||
border-radius: 2px; |
|||
margin: 20px 0 10px; |
|||
overflow: hidden; |
|||
padding: 15px; |
|||
border: 1px solid #ccc; |
|||
} |
|||
|
|||
.btn { |
|||
border-radius: 2px; |
|||
} |
|||
.btn-primary { |
|||
background-color: #8DC429; |
|||
border: 2px solid #76AF0F; |
|||
} |
|||
|
|||
.btn-primary:hover, .btn-primary:focus, .btn-primary:active, |
|||
.btn-primary.active, .open .dropdown-toggle.btn-primary, |
|||
.btn-success:hover, .btn-success:focus, .btn-success:active, |
|||
.btn-success.active, .open .dropdown-toggle.btn-success, |
|||
.btn-danger:hover, .btn-danger:focus, .btn-danger:active, |
|||
.btn-danger.active, .open .dropdown-toggle.btn-danger { |
|||
background-color: #fff; |
|||
border: 2px solid #ccc; |
|||
color: #373D42; |
|||
} |
|||
|
|||
.btn-default { |
|||
background-color: #E7E7E7; |
|||
border: 2px solid #DCDCDC; |
|||
} |
|||
|
|||
.btn-success { |
|||
background-color: #2FA4D7; |
|||
border: 2px solid #237FA7; |
|||
} |
|||
|
|||
.btn-danger { |
|||
background-color: #AC0015; |
|||
border: 2px solid #6C0000; |
|||
} |
|||
|
|||
.label { |
|||
padding: .7em 2em; |
|||
font-size: 13px; |
|||
text-transform: uppercase; |
|||
font-weight:100; |
|||
} |
|||
|
|||
.label-primary { |
|||
background-color: #8DC429; |
|||
} |
|||
|
|||
.label-default { |
|||
background-color: #ffffff; |
|||
color: #333; |
|||
} |
|||
|
|||
.label-success { |
|||
background-color: #2FA4D7; |
|||
} |
|||
|
|||
.label-danger { |
|||
background-color: #AC0015; |
|||
} |
|||
|
|||
.progress-bar-info { background-color: #8DC429; } |
|||
|
|||
/* Set the fixed height of the footer here */ |
|||
#footer { |
|||
background-color: #373D42; |
|||
border-top: 4px solid #656E76; |
|||
color: #fff; |
|||
height: 51px; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.currency a.active { |
|||
color: #000; |
|||
text-decoration: underline; |
|||
cursor: default; |
|||
} |
|||
|
|||
#footer a.insight { |
|||
font-size: 20px; |
|||
text-decoration: none; |
|||
color: #fff; |
|||
} |
|||
|
|||
#footer a.insight:hover { |
|||
color: #fffffe; |
|||
} |
|||
|
|||
#footer a.insight small { font-size: 11px; } |
|||
.line-footer { border-top: 2px dashed #ccc; } |
|||
|
|||
.line-bot { |
|||
border-bottom: 2px solid #EAEAEA; |
|||
padding: 0 0 10px 0; |
|||
} |
|||
.line-mid { padding: 15px 0;} |
|||
.line-top { |
|||
border-top: 1px solid #EAEAEA; |
|||
padding: 15px 0 0 0; |
|||
} |
|||
|
|||
/* Custom page CSS |
|||
-------------------------------------------------- */ |
|||
/* Not required for template or sticky footer method. */ |
|||
|
|||
#wrap > .container { padding: 60px 15px 0; } |
|||
|
|||
.container .text-muted a { color: #eee; } |
|||
|
|||
#footer > .container { padding: auto 15px; } |
|||
|
|||
.code { font-size: 80%; } |
|||
|
|||
.address { font-size: 11px; } |
|||
|
|||
.no_matching { |
|||
-moz-border-radius-bottomleft: 2px; |
|||
-moz-border-radius-bottomright: 2px; |
|||
-webkit-border-bottom-left-radius: 2px; |
|||
-webkit-border-bottom-right-radius: 2px; |
|||
background-color: #FFFFFF; |
|||
border-bottom-left-radius: 2px; |
|||
border-bottom-right-radius: 2px; |
|||
border-top: none; |
|||
border: 1px solid #64920F; |
|||
padding: 10px 20px; |
|||
position: absolute; |
|||
text-align: center; |
|||
top: 45px; |
|||
width: 300px; |
|||
} |
|||
|
|||
/*Animations*/ |
|||
.fader.ng-enter { |
|||
opacity: 0; |
|||
-webkit-transition: opacity 1s; |
|||
-moz-transition: opacity 1s; |
|||
-o-transition: opacity 1s; |
|||
transition: opacity 1s; |
|||
} |
|||
|
|||
.fader.ng-enter-active { opacity: 1; } |
|||
|
|||
.tx-bg { |
|||
background-color: #F4F4F4; |
|||
left: 0; |
|||
min-height: 340px; |
|||
position: absolute; |
|||
top: 0; |
|||
width: 100%; |
|||
z-index: -9999; |
|||
} |
|||
|
|||
.badge { |
|||
-moz-border-radius: 9px; |
|||
-webkit-border-radius: 9px; |
|||
background-color: #999999; |
|||
border-radius: 9px; |
|||
color: #ffffff; |
|||
font-size: 12.025px; |
|||
font-weight: bold; |
|||
padding: 1px 9px 2px; |
|||
white-space: nowrap; |
|||
} |
|||
|
|||
.badge:hover { |
|||
color: #ffffff; |
|||
text-decoration: none; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.badge-error { background-color: #b94a48; } |
|||
.badge-error:hover { background-color: #953b39; } |
|||
.badge-warning { background-color: #f89406; } |
|||
.badge-warning:hover { background-color: #c67605; } |
|||
.badge-success { background-color: #468847; } |
|||
.badge-success:hover { background-color: #356635; } |
|||
.badge-info { background-color: #3a87ad; } |
|||
.badge-info:hover { background-color: #2d6987; } |
|||
.badge-inverse { background-color: #333333; } |
|||
.badge-inverse:hover { background-color: #1a1a1a; } |
|||
|
|||
.status .t { |
|||
color: white; |
|||
} |
|||
|
|||
.status .text-danger { background: red; } |
|||
|
|||
.status .text-warning { |
|||
background: yellow; |
|||
color: black; |
|||
} |
|||
|
|||
.btn-copy, .btn-expand { |
|||
-moz-border-radius: 2px; |
|||
-webkit-border-radius: 2px; |
|||
background-color: #FFFFFF; |
|||
border-radius: 2px; |
|||
border: 2px solid #E4E4E4; |
|||
color: #9b9b9b; |
|||
display: inline-block; |
|||
height: 25px; |
|||
outline: none; |
|||
text-align: center; |
|||
width: 30px; |
|||
} |
|||
.btn-copy { margin-left: 5px; } |
|||
.btn-copy .tooltip { |
|||
display: inline-block; |
|||
margin-left: 10px; |
|||
margin-top: -2px; |
|||
opacity: 0; |
|||
} |
|||
.btn-copy.zeroclipboard-is-hover { color: #2a6496; } |
|||
.btn-copy.zeroclipboard-is-active .tooltip { opacity: 1; } |
|||
.btn-expand { margin-right: 5px; } |
|||
|
|||
@media (max-width: 991px) { |
|||
.btn-copy { |
|||
display: none; |
|||
} |
|||
} |
|||
|
|||
.txid { |
|||
line-height: 26px; |
|||
} |
|||
|
|||
.tx-id { |
|||
background-color: #373D42; |
|||
border: 3px solid #FFFFFF; |
|||
margin: 0 auto; |
|||
width: 165px; |
|||
color: #FFFFFF; |
|||
font-size: 80px; |
|||
text-align: center; |
|||
} |
|||
|
|||
.transaction-vin-vout .ellipsis { margin-bottom: 10px; } |
|||
.transaction-vin-vout .btc-value { margin-left: 15px; } |
|||
|
|||
.page-header { margin-top: 0; } |
|||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,929 +0,0 @@ |
|||
'use strict'; |
|||
// Source: public/src/js/app.js
|
|||
angular.module('insight',[ |
|||
'ngAnimate', |
|||
'ngResource', |
|||
'ngRoute', |
|||
'ui.bootstrap', |
|||
'ui.route', |
|||
'monospaced.qrcode', |
|||
'insight.system', |
|||
'insight.socket', |
|||
'insight.blocks', |
|||
'insight.transactions', |
|||
'insight.address', |
|||
'insight.search', |
|||
'insight.status', |
|||
'insight.connection', |
|||
'insight.currency' |
|||
]); |
|||
|
|||
angular.module('insight.system', []); |
|||
angular.module('insight.socket', []); |
|||
angular.module('insight.blocks', []); |
|||
angular.module('insight.transactions', []); |
|||
angular.module('insight.address', []); |
|||
angular.module('insight.search', []); |
|||
angular.module('insight.status', []); |
|||
angular.module('insight.connection', []); |
|||
angular.module('insight.currency', []); |
|||
|
|||
// Source: public/src/js/controllers/address.js
|
|||
angular.module('insight.address').controller('AddressController', |
|||
function($scope, $rootScope, $routeParams, $location, Global, Address, getSocket) { |
|||
$scope.global = Global; |
|||
|
|||
$scope.findOne = function() { |
|||
$rootScope.currentAddr = $routeParams.addrStr; |
|||
|
|||
Address.get({ |
|||
addrStr: $routeParams.addrStr |
|||
}, |
|||
function(address) { |
|||
$rootScope.titleDetail = address.addrStr.substring(0,7) + '...'; |
|||
$scope.address = address; |
|||
}, |
|||
function(e) { |
|||
if (e.status === 400) { |
|||
$rootScope.flashMessage = 'Invalid Address: ' + $routeParams.addrStr; |
|||
} |
|||
else if (e.status === 503) { |
|||
$rootScope.flashMessage = 'Backend Error. ' + e.data; |
|||
} |
|||
else { |
|||
$rootScope.flashMessage = 'Address Not Found'; |
|||
} |
|||
$location.path('/'); |
|||
}); |
|||
}; |
|||
|
|||
var socket = getSocket($scope); |
|||
socket.emit('subscribe', $routeParams.addrStr); |
|||
socket.on($routeParams.addrStr, function(tx) { |
|||
console.log('AddressTx event received ' + tx); |
|||
$rootScope.$broadcast('tx', tx); |
|||
}); |
|||
|
|||
$scope.params = $routeParams; |
|||
|
|||
}); |
|||
|
|||
// Source: public/src/js/controllers/blocks.js
|
|||
angular.module('insight.blocks').controller('BlocksController', |
|||
function($scope, $rootScope, $routeParams, $location, Global, Block, Blocks, BlockByHeight) { |
|||
$scope.global = Global; |
|||
$scope.loading = false; |
|||
|
|||
if ($routeParams.blockHeight) { |
|||
BlockByHeight.get({ |
|||
blockHeight: $routeParams.blockHeight |
|||
}, function(hash) { |
|||
$location.path('/block/' + hash.blockHash); |
|||
}, function() { |
|||
$rootScope.flashMessage = 'Bad Request'; |
|||
$location.path('/'); |
|||
}); |
|||
} |
|||
|
|||
|
|||
$scope.humanSince = function(time) { |
|||
var m = moment.unix(time).startOf('day'); |
|||
var b = moment().startOf('day'); |
|||
return m.max().from(b); |
|||
}; |
|||
|
|||
|
|||
$scope.list = function() { |
|||
$scope.loading = true; |
|||
|
|||
if ($routeParams.blockDate) { |
|||
$rootScope.titleDetail = 'on ' + $routeParams.blockDate; |
|||
} |
|||
|
|||
Blocks.get({ |
|||
blockDate: $routeParams.blockDate |
|||
}, function(res) { |
|||
$scope.loading = false; |
|||
$scope.blocks = res.blocks; |
|||
$scope.pagination = res.pagination; |
|||
}); |
|||
}; |
|||
|
|||
$scope.findOne = function() { |
|||
$scope.loading = true; |
|||
|
|||
Block.get({ |
|||
blockHash: $routeParams.blockHash |
|||
}, function(block) { |
|||
$rootScope.titleDetail = block.height; |
|||
$scope.loading = false; |
|||
$scope.block = block; |
|||
}, function(e) { |
|||
if (e.status === 400) { |
|||
$rootScope.flashMessage = 'Invalid Transaction ID: ' + $routeParams.txId; |
|||
} |
|||
else if (e.status === 503) { |
|||
$rootScope.flashMessage = 'Backend Error. ' + e.data; |
|||
} |
|||
else { |
|||
$rootScope.flashMessage = 'Block Not Found'; |
|||
} |
|||
$location.path('/'); |
|||
}); |
|||
}; |
|||
|
|||
$scope.params = $routeParams; |
|||
|
|||
}); |
|||
|
|||
// Source: public/src/js/controllers/connection.js
|
|||
angular.module('insight.connection').controller('ConnectionController', |
|||
function($scope, $window, Status, Sync, getSocket) { |
|||
|
|||
// Set initial values
|
|||
$scope.apiOnline = true; |
|||
$scope.serverOnline = true; |
|||
$scope.clienteOnline = true; |
|||
|
|||
var socket = getSocket($scope); |
|||
|
|||
// Check for the node server connection
|
|||
socket.on('disconnect', function() { |
|||
$scope.serverOnline = false; |
|||
}); |
|||
|
|||
socket.on('connect', function() { |
|||
$scope.serverOnline = true; |
|||
}); |
|||
|
|||
// Check for the api connection
|
|||
$scope.getConnStatus = function() { |
|||
Sync.get({}, |
|||
function(sync) { |
|||
$scope.apiOnline = (sync.status !== 'aborted' && sync.status !== 'error'); |
|||
}, |
|||
function() { |
|||
$scope.apiOnline = false; |
|||
}); |
|||
}; |
|||
|
|||
socket.emit('subscribe', 'sync'); |
|||
socket.on('status', function(sync) { |
|||
$scope.apiOnline = (sync.status !== 'aborted' && sync.status !== 'error'); |
|||
}); |
|||
|
|||
// Check for the client conneciton
|
|||
$window.addEventListener('offline', function() { |
|||
$scope.$apply(function() { |
|||
$scope.clienteOnline = false; |
|||
}); |
|||
}, true); |
|||
|
|||
$window.addEventListener('online', function () { |
|||
$scope.$apply(function() { |
|||
$scope.clienteOnline = true; |
|||
}); |
|||
}, true); |
|||
|
|||
}); |
|||
|
|||
// Source: public/src/js/controllers/currency.js
|
|||
angular.module('insight.currency').controller('CurrencyController', |
|||
function($scope, $rootScope, Currency) { |
|||
|
|||
var _roundFloat = function(x, n) { |
|||
if(!parseInt(n, 10) || !parseFloat(x)) n = 0; |
|||
|
|||
return Math.round(x * Math.pow(10, n)) / Math.pow(10, n); |
|||
}; |
|||
|
|||
$rootScope.currency.getConvertion = function(value) { |
|||
if (typeof value !== 'undefined' && value !== null) { |
|||
var response; |
|||
|
|||
if (this.symbol === 'USD') { |
|||
response = _roundFloat((value * this.factor), 2); |
|||
} else if (this.symbol === 'mBTC') { |
|||
this.factor = 1000; |
|||
response = _roundFloat((value * this.factor), 5); |
|||
} else { |
|||
this.factor = 1; |
|||
response = value; |
|||
} |
|||
|
|||
return response + ' ' + this.symbol; |
|||
} |
|||
|
|||
return 'value error'; |
|||
}; |
|||
|
|||
$scope.setCurrency = function(currency) { |
|||
$rootScope.currency.symbol = currency; |
|||
|
|||
if (currency === 'USD') { |
|||
Currency.get({}, function(res) { |
|||
$rootScope.currency.factor = $rootScope.currency.bitstamp = res.data.bitstamp; |
|||
}); |
|||
} else if (currency === 'mBTC') { |
|||
$rootScope.currency.factor = 1000; |
|||
} else { |
|||
$rootScope.currency.factor = 1; |
|||
} |
|||
}; |
|||
|
|||
// Get initial value
|
|||
Currency.get({}, function(res) { |
|||
$rootScope.currency.bitstamp = res.data.bitstamp; |
|||
}); |
|||
|
|||
}); |
|||
|
|||
// Source: public/src/js/controllers/footer.js
|
|||
angular.module('insight.system').controller('FooterController', |
|||
function($scope, Version) { |
|||
|
|||
var _getVersion = function() { |
|||
Version.get({}, |
|||
function(res) { |
|||
$scope.version = res.version; |
|||
}); |
|||
}; |
|||
|
|||
$scope.version = _getVersion(); |
|||
|
|||
}); |
|||
|
|||
// Source: public/src/js/controllers/header.js
|
|||
angular.module('insight.system').controller('HeaderController', |
|||
function($scope, $rootScope, getSocket, Global, Block) { |
|||
$scope.global = Global; |
|||
|
|||
$rootScope.currency = { |
|||
factor: 1, |
|||
bitstamp: 0, |
|||
symbol: 'BTC' |
|||
}; |
|||
|
|||
$scope.menu = [ |
|||
{ |
|||
'title': 'Blocks', |
|||
'link': 'blocks' |
|||
}, |
|||
{ |
|||
'title': 'Status', |
|||
'link': 'status' |
|||
} |
|||
]; |
|||
|
|||
var socket = getSocket($scope); |
|||
socket.emit('subscribe', 'inv'); |
|||
|
|||
var _getBlock = function(hash) { |
|||
Block.get({ |
|||
blockHash: hash |
|||
}, function(res) { |
|||
$scope.totalBlocks = res.height; |
|||
}); |
|||
}; |
|||
|
|||
socket.on('block', function(block) { |
|||
var blockHash = block.toString(); |
|||
console.log('Updated Blocks Height!'); |
|||
_getBlock(blockHash); |
|||
}); |
|||
|
|||
$rootScope.isCollapsed = true; |
|||
}); |
|||
|
|||
// Source: public/src/js/controllers/index.js
|
|||
var TRANSACTION_DISPLAYED = 5; |
|||
var BLOCKS_DISPLAYED = 5; |
|||
|
|||
angular.module('insight.system').controller('IndexController', |
|||
function($scope, $rootScope, Global, getSocket, Blocks, Transaction) { |
|||
$scope.global = Global; |
|||
|
|||
var _getBlocks = function() { |
|||
Blocks.get({ |
|||
limit: BLOCKS_DISPLAYED |
|||
}, function(res) { |
|||
$scope.blocks = res.blocks; |
|||
$scope.blocksLength = res.lenght; |
|||
}); |
|||
}; |
|||
|
|||
var _getTransaction = function(txid, cb) { |
|||
Transaction.get({ |
|||
txId: txid |
|||
}, function(res) { |
|||
cb(res); |
|||
}); |
|||
}; |
|||
|
|||
var socket = getSocket($scope); |
|||
socket.emit('subscribe', 'inv'); |
|||
|
|||
//show errors
|
|||
$scope.flashMessage = $rootScope.flashMessage || null; |
|||
|
|||
socket.on('tx', function(tx) { |
|||
console.log('Transaction received! ' + JSON.stringify(tx)); |
|||
|
|||
var txStr = tx.toString(); |
|||
_getTransaction(txStr, function(res) { |
|||
$scope.txs.unshift(res); |
|||
if (parseInt($scope.txs.length, 10) >= parseInt(TRANSACTION_DISPLAYED, 10)) { |
|||
$scope.txs = $scope.txs.splice(0, TRANSACTION_DISPLAYED); |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
socket.on('block', function(block) { |
|||
var blockHash = block.toString(); |
|||
console.log('Block received! ' + JSON.stringify(blockHash)); |
|||
_getBlocks(); |
|||
}); |
|||
|
|||
$scope.humanSince = function(time) { |
|||
var m = moment.unix(time); |
|||
return m.max().fromNow(); |
|||
}; |
|||
|
|||
$scope.index = function() { |
|||
_getBlocks(); |
|||
}; |
|||
|
|||
$scope.txs = []; |
|||
$scope.blocks = []; |
|||
}); |
|||
|
|||
// Source: public/src/js/controllers/search.js
|
|||
angular.module('insight.search').controller('SearchController', |
|||
function($scope, $routeParams, $location, $timeout, Global, Block, Transaction, Address, BlockByHeight) { |
|||
$scope.global = Global; |
|||
|
|||
var _badQuery = function() { |
|||
$scope.badQuery = true; |
|||
|
|||
$timeout(function() { |
|||
$scope.badQuery = false; |
|||
}, 2000); |
|||
}; |
|||
|
|||
$scope.search = function() { |
|||
var q = $scope.q; |
|||
$scope.badQuery = false; |
|||
|
|||
Block.get({ |
|||
blockHash: q |
|||
}, function() { |
|||
$scope.q = ''; |
|||
$location.path('block/' + q); |
|||
}, function () { //block not found, search on TX
|
|||
Transaction.get({ |
|||
txId: q |
|||
}, function() { |
|||
$scope.q = ''; |
|||
$location.path('tx/' + q); |
|||
}, function () { //tx not found, search on Address
|
|||
Address.get({ |
|||
addrStr: q |
|||
}, function() { |
|||
$scope.q = ''; |
|||
$location.path('address/' + q); |
|||
}, function () { // block by height not found
|
|||
if (isFinite(q)) { // ensure that q is a finite number. A logical height value.
|
|||
BlockByHeight.get({ |
|||
blockHeight: q |
|||
}, function(hash) { |
|||
$scope.q = ''; |
|||
$location.path('/block/' + hash.blockHash); |
|||
}, function() { //not found, fail :(
|
|||
_badQuery(); |
|||
}); |
|||
} |
|||
else { |
|||
_badQuery(); |
|||
} |
|||
}); |
|||
}); |
|||
}); |
|||
}; |
|||
|
|||
}); |
|||
|
|||
// Source: public/src/js/controllers/status.js
|
|||
angular.module('insight.status').controller('StatusController', |
|||
function($scope, $routeParams, $location, Global, Status, Sync, getSocket) { |
|||
$scope.global = Global; |
|||
|
|||
$scope.getStatus = function(q) { |
|||
Status.get({ |
|||
q: 'get' + q |
|||
}, |
|||
function(d) { |
|||
$scope.loaded = 1; |
|||
angular.extend($scope, d); |
|||
}, |
|||
function(e) { |
|||
$scope.error = 'API ERROR: ' + e.data; |
|||
}); |
|||
}; |
|||
|
|||
var _onSyncUpdate = function(sync) { |
|||
$scope.sync = sync; |
|||
}; |
|||
|
|||
$scope.getSync = function() { |
|||
Sync.get({}, |
|||
function(sync) { |
|||
_onSyncUpdate(sync); |
|||
}, |
|||
function(e) { |
|||
var err = 'Could not get sync information' + e.toString(); |
|||
$scope.sync = { error: err }; |
|||
}); |
|||
}; |
|||
|
|||
var socket = getSocket($scope); |
|||
socket.emit('subscribe', 'sync'); |
|||
socket.on('status', function(sync) { |
|||
_onSyncUpdate(sync); |
|||
}); |
|||
}); |
|||
|
|||
|
|||
// Source: public/src/js/controllers/transactions.js
|
|||
angular.module('insight.transactions').controller('transactionsController', |
|||
function($scope, $rootScope, $routeParams, $location, Global, Transaction, TransactionsByBlock, TransactionsByAddress) { |
|||
$scope.global = Global; |
|||
$scope.loading = false; |
|||
$scope.loadedBy = null; |
|||
|
|||
var pageNum = 0; |
|||
var pagesTotal = 1; |
|||
var COIN = 100000000; |
|||
|
|||
var _aggregateItems = function(items) { |
|||
if (!items) return []; |
|||
|
|||
var l = items.length; |
|||
|
|||
var ret = []; |
|||
var tmp = {}; |
|||
var u = 0; |
|||
|
|||
// TODO multiple output address
|
|||
//
|
|||
for(var i=0; i < l; i++) { |
|||
|
|||
var notAddr = false; |
|||
|
|||
// non standard input
|
|||
if (items[i].scriptSig && !items[i].addr) { |
|||
items[i].addr = 'Unparsed address [' + u++ + ']'; |
|||
items[i].notAddr = true; |
|||
notAddr = true; |
|||
} |
|||
|
|||
// non standard output
|
|||
if (items[i].scriptPubKey && !items[i].scriptPubKey.addresses) { |
|||
items[i].scriptPubKey.addresses = ['Unparsed address [' + u++ + ']']; |
|||
items[i].notAddr = true; |
|||
notAddr = true; |
|||
} |
|||
|
|||
// multiple addr at output
|
|||
if (items[i].scriptPubKey && items[i].scriptPubKey.addresses.length > 1) { |
|||
items[i].addr = items[i].scriptPubKey.addresses.join(','); |
|||
ret.push(items[i]); |
|||
continue; |
|||
} |
|||
|
|||
var addr = items[i].addr || (items[i].scriptPubKey && items[i].scriptPubKey.addresses[0]); |
|||
|
|||
if (!tmp[addr]) { |
|||
tmp[addr] = {}; |
|||
tmp[addr].valueSat = 0; |
|||
tmp[addr].count = 0; |
|||
tmp[addr].addr = addr; |
|||
tmp[addr].items = []; |
|||
} |
|||
|
|||
tmp[addr].valueSat += items[i].value * COIN; |
|||
tmp[addr].value = items[i].value; |
|||
tmp[addr].items.push(items[i]); |
|||
tmp[addr].notAddr = notAddr; |
|||
tmp[addr].count++; |
|||
} |
|||
|
|||
angular.forEach(tmp, function(v) { |
|||
ret.push(v); |
|||
}); |
|||
|
|||
return ret; |
|||
}; |
|||
|
|||
var _processTX = function(tx) { |
|||
tx.vinSimple = _aggregateItems(tx.vin); |
|||
tx.voutSimple = _aggregateItems(tx.vout); |
|||
}; |
|||
|
|||
var _paginate = function(data) { |
|||
$scope.loading = false; |
|||
|
|||
pagesTotal = data.pagesTotal; |
|||
pageNum += 1; |
|||
|
|||
data.txs.forEach(function(tx) { |
|||
_processTX(tx); |
|||
$scope.txs.push(tx); |
|||
}); |
|||
}; |
|||
|
|||
var _byBlock = function() { |
|||
TransactionsByBlock.get({ |
|||
block: $routeParams.blockHash, |
|||
pageNum: pageNum |
|||
}, function(data) { |
|||
_paginate(data); |
|||
}); |
|||
}; |
|||
|
|||
var _byAddress = function () { |
|||
TransactionsByAddress.get({ |
|||
address: $routeParams.addrStr, |
|||
pageNum: pageNum |
|||
}, function(data) { |
|||
_paginate(data); |
|||
}); |
|||
}; |
|||
|
|||
var _findTx = function(txid) { |
|||
Transaction.get({ |
|||
txId: txid |
|||
}, function(tx) { |
|||
$rootScope.titleDetail = tx.txid.substring(0,7) + '...'; |
|||
$scope.tx = tx; |
|||
_processTX(tx); |
|||
$scope.txs.unshift(tx); |
|||
}, function(e) { |
|||
if (e.status === 400) { |
|||
$rootScope.flashMessage = 'Invalid Transaction ID: ' + $routeParams.txId; |
|||
} |
|||
else if (e.status === 503) { |
|||
$rootScope.flashMessage = 'Backend Error. ' + e.data; |
|||
} |
|||
else { |
|||
$rootScope.flashMessage = 'Transaction Not Found'; |
|||
} |
|||
|
|||
$location.path('/'); |
|||
}); |
|||
}; |
|||
|
|||
$scope.findThis = function() { |
|||
_findTx($routeParams.txId); |
|||
}; |
|||
|
|||
//Initial load
|
|||
$scope.load = function(from) { |
|||
$scope.loadedBy = from; |
|||
$scope.loadMore(); |
|||
}; |
|||
|
|||
//Load more transactions for pagination
|
|||
$scope.loadMore = function() { |
|||
if (pageNum < pagesTotal && !$scope.loading) { |
|||
$scope.loading = true; |
|||
|
|||
if ($scope.loadedBy === 'address') { |
|||
_byAddress(); |
|||
} |
|||
else { |
|||
_byBlock(); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
//Init without txs
|
|||
$scope.txs = []; |
|||
|
|||
$scope.$on('tx', function(event, txid) { |
|||
_findTx(txid); |
|||
}); |
|||
|
|||
}); |
|||
|
|||
// Source: public/src/js/services/address.js
|
|||
angular.module('insight.address').factory('Address', |
|||
function($resource) { |
|||
return $resource('/api/addr/:addrStr', { |
|||
addrStr: '@addStr' |
|||
}, { |
|||
get: { |
|||
method: 'GET', |
|||
interceptor: { |
|||
response: function (res) { |
|||
return res.data; |
|||
}, |
|||
responseError: function (res) { |
|||
if (res.status === 404) { |
|||
return res; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
|
|||
// Source: public/src/js/services/blocks.js
|
|||
angular.module('insight.blocks') |
|||
.factory('Block', |
|||
function($resource) { |
|||
return $resource('/api/block/:blockHash', { |
|||
blockHash: '@blockHash' |
|||
}, { |
|||
get: { |
|||
method: 'GET', |
|||
interceptor: { |
|||
response: function (res) { |
|||
return res.data; |
|||
}, |
|||
responseError: function (res) { |
|||
if (res.status === 404) { |
|||
return res; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
}) |
|||
.factory('Blocks', |
|||
function($resource) { |
|||
return $resource('/api/blocks'); |
|||
}) |
|||
.factory('BlockByHeight', |
|||
function($resource) { |
|||
return $resource('/api/block-index/:blockHeight'); |
|||
}); |
|||
|
|||
// Source: public/src/js/services/currency.js
|
|||
angular.module('insight.currency').factory('Currency', |
|||
function($resource) { |
|||
return $resource('/api/currency'); |
|||
}); |
|||
|
|||
// Source: public/src/js/services/global.js
|
|||
//Global service for global variables
|
|||
angular.module('insight.system') |
|||
.factory('Global',[ |
|||
function() { |
|||
} |
|||
]) |
|||
.factory('Version', |
|||
function($resource) { |
|||
return $resource('/api/version'); |
|||
}); |
|||
|
|||
// Source: public/src/js/services/socket.js
|
|||
var ScopedSocket = function(socket, $rootScope) { |
|||
this.socket = socket; |
|||
this.$rootScope = $rootScope; |
|||
this.listeners = []; |
|||
}; |
|||
|
|||
ScopedSocket.prototype.removeAllListeners = function() { |
|||
for (var i = 0; i < this.listeners.length; i++) { |
|||
var details = this.listeners[i]; |
|||
this.socket.removeListener(details.event, details.fn); |
|||
} |
|||
this.listeners = []; |
|||
}; |
|||
|
|||
ScopedSocket.prototype.on = function(event, callback) { |
|||
var socket = this.socket; |
|||
var $rootScope = this.$rootScope; |
|||
|
|||
var wrapped_callback = function() { |
|||
var args = arguments; |
|||
$rootScope.$apply(function() { |
|||
callback.apply(socket, args); |
|||
}); |
|||
}; |
|||
socket.on(event, wrapped_callback); |
|||
|
|||
this.listeners.push({ |
|||
event: event, |
|||
fn: wrapped_callback |
|||
}); |
|||
}; |
|||
|
|||
ScopedSocket.prototype.emit = function(event, data, callback) { |
|||
var socket = this.socket; |
|||
var $rootScope = this.$rootScope; |
|||
|
|||
socket.emit(event, data, function() { |
|||
var args = arguments; |
|||
$rootScope.$apply(function() { |
|||
if (callback) { |
|||
callback.apply(socket, args); |
|||
} |
|||
}); |
|||
}); |
|||
}; |
|||
|
|||
angular.module('insight.socket').factory('getSocket', |
|||
function($rootScope) { |
|||
var socket = io.connect(); |
|||
return function(scope) { |
|||
var scopedSocket = new ScopedSocket(socket, $rootScope); |
|||
scope.$on('$routeChangeStart', function() { |
|||
}); |
|||
scope.$on('$destroy', function() { |
|||
scopedSocket.removeAllListeners(); |
|||
}); |
|||
return scopedSocket; |
|||
}; |
|||
}); |
|||
|
|||
// Source: public/src/js/services/status.js
|
|||
angular.module('insight.status') |
|||
.factory('Status', |
|||
function($resource) { |
|||
return $resource('/api/status', { |
|||
q: '@q' |
|||
}); |
|||
}) |
|||
.factory('Sync', |
|||
function($resource) { |
|||
return $resource('/api/sync'); |
|||
}); |
|||
|
|||
// Source: public/src/js/services/transactions.js
|
|||
angular.module('insight.transactions') |
|||
.factory('Transaction', |
|||
function($resource) { |
|||
return $resource('/api/tx/:txId', { |
|||
txId: '@txId' |
|||
}, { |
|||
get: { |
|||
method: 'GET', |
|||
interceptor: { |
|||
response: function (res) { |
|||
return res.data; |
|||
}, |
|||
responseError: function (res) { |
|||
if (res.status === 404) { |
|||
return res; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
}) |
|||
.factory('TransactionsByBlock', |
|||
function($resource) { |
|||
return $resource('/api/txs', { |
|||
block: '@block' |
|||
}); |
|||
}) |
|||
.factory('TransactionsByAddress', |
|||
function($resource) { |
|||
return $resource('/api/txs', { |
|||
address: '@address' |
|||
}); |
|||
}) |
|||
.factory('Transactions', |
|||
function($resource) { |
|||
return $resource('/api/txs'); |
|||
}); |
|||
|
|||
// Source: public/src/js/directives.js
|
|||
var ZeroClipboard = window.ZeroClipboard; |
|||
|
|||
angular.module('insight') |
|||
.directive('whenScrolled', function($window) { |
|||
return { |
|||
restric: 'A', |
|||
link: function(scope, elm, attr) { |
|||
var pageHeight, clientHeight, scrollPos; |
|||
$window = angular.element($window); |
|||
|
|||
var handler = function() { |
|||
pageHeight = window.document.documentElement.scrollHeight; |
|||
clientHeight = window.document.documentElement.clientHeight; |
|||
scrollPos = window.pageYOffset; |
|||
|
|||
if (pageHeight - (scrollPos + clientHeight) === 0) { |
|||
scope.$apply(attr.whenScrolled); |
|||
} |
|||
}; |
|||
|
|||
$window.on('scroll', handler); |
|||
|
|||
scope.$on('$destroy', function() { |
|||
return $window.off('scroll', handler); |
|||
}); |
|||
} |
|||
}; |
|||
}) |
|||
.directive('clipCopy', function() { |
|||
ZeroClipboard.config({ |
|||
moviePath: '/lib/zeroclipboard/ZeroClipboard.swf', |
|||
trustedDomains: ['*'], |
|||
allowScriptAccess: 'always', |
|||
forceHandCursor: true |
|||
}); |
|||
|
|||
return { |
|||
restric: 'A', |
|||
scope: { clipCopy: '=clipCopy' }, |
|||
template: '<span class="glyphicon glyphicon-paperclip"></span><div class="tooltip fade right in"><div class="tooltip-arrow"></div><div class="tooltip-inner">Copied!</div></div>', |
|||
link: function(scope, elm) { |
|||
var clip = new ZeroClipboard(elm); |
|||
|
|||
clip.on('load', function(client) { |
|||
var onMousedown = function(client) { |
|||
client.setText(scope.clipCopy); |
|||
}; |
|||
|
|||
client.on('mousedown', onMousedown); |
|||
client.on('noflash wrongflash', function() { |
|||
return elm.remove(); |
|||
}); |
|||
|
|||
scope.$on('$destroy', function() { |
|||
client.off('mousedown', onMousedown); |
|||
}); |
|||
}); |
|||
} |
|||
}; |
|||
}); |
|||
|
|||
// Source: public/src/js/filters.js
|
|||
|
|||
// Source: public/src/js/config.js
|
|||
//Setting up route
|
|||
angular.module('insight').config(function($routeProvider) { |
|||
$routeProvider. |
|||
when('/block/:blockHash', { |
|||
templateUrl: '/views/block.html', |
|||
title: 'Bitcoin Block ' |
|||
}). |
|||
when('/block-index/:blockHeight', { |
|||
controller: 'BlocksController', |
|||
templateUrl: '/views/redirect.html' |
|||
}). |
|||
when('/tx/:txId', { |
|||
templateUrl: '/views/transaction.html', |
|||
title: 'Bitcoin Transaction ' |
|||
}). |
|||
when('/', { |
|||
templateUrl: '/views/index.html', |
|||
title: 'Home' |
|||
}). |
|||
when('/blocks', { |
|||
templateUrl: '/views/block_list.html', |
|||
title: 'Bitcoin Blocks solved Today' |
|||
}). |
|||
when('/blocks-date/:blockDate', { |
|||
templateUrl: '/views/block_list.html', |
|||
title: 'Bitcoin Blocks solved ' |
|||
}). |
|||
when('/address/:addrStr', { |
|||
templateUrl: '/views/address.html', |
|||
title: 'Bitcoin Address ' |
|||
}). |
|||
when('/status', { |
|||
templateUrl: '/views/status.html', |
|||
title: 'Status' |
|||
}) |
|||
.otherwise({ |
|||
templateUrl: '/views/404.html', |
|||
title: 'Error' |
|||
}); |
|||
}); |
|||
|
|||
//Setting HTML5 Location Mode
|
|||
angular.module('insight') |
|||
.config(function($locationProvider) { |
|||
$locationProvider.html5Mode(true); |
|||
$locationProvider.hashPrefix('!'); |
|||
}) |
|||
.run(function($rootScope, $route) { |
|||
$rootScope.$on('$routeChangeSuccess', function() { |
|||
//Change page title, based on Route information
|
|||
$rootScope.titleDetail = ''; |
|||
$rootScope.title = $route.current.title; |
|||
$rootScope.isCollapsed = true; |
|||
$rootScope.currentAddr = null; |
|||
}); |
|||
}); |
|||
|
|||
// Source: public/src/js/init.js
|
|||
angular.element(document).ready(function() { |
|||
// Init the app
|
|||
// angular.bootstrap(document, ['insight']);
|
|||
}); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue