diff --git a/.travis.yml b/.travis.yml index d10da6c..3d871fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,8 @@ language: node_js -node_js: - - "8" -env: - global: - secure: Qdkmi13nqcXskABBhbuGZmRakh4orOW1dalkSCyUbzGuYf0OdYF8ttNVuJa0WSWI4KhNXhtz2p3I8dM95wL++LCVqXFmIvZtX8Nca36KlNxIPNXPjn0odayh+c4pgrhrbz8TDmDXl9IPuZmNz8HHtN7xmIn6YDcm13wA3gTmfwo= +sudo: required +dist: trusty +node_js: '8' before_install: npm install -g grunt-cli -install: npm install -before_script: grunt build +install: + - npm install + - npm run dist diff --git a/Dockerfile b/Dockerfile index 36d6e0c..787c414 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,10 @@ -FROM mhart/alpine-node:latest +FROM node -ADD . /eth-netstats -WORKDIR /eth-netstats - -RUN npm install && npm install -g grunt-cli && grunt +RUN git clone https://github.com/goerli/netstats-server /netstats-server +WORKDIR /netstats-server +RUN npm install +RUN npm install -g grunt-cli +RUN grunt EXPOSE 3000 CMD ["npm", "start"] diff --git a/Gruntfile.js b/Gruntfile.js index 8a703af..17b43b1 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -60,14 +60,14 @@ module.exports = function(grunt) { { expand: true, cwd: 'src/fonts/', - src: ['minimal-*.*'], + src: ['*.*'], dest: 'dist/fonts/', filter: 'isFile' }, { expand: true, cwd: 'src/images/', - src: ['*.ico'], + src: ['*.*'], dest: 'dist/', filter: 'isFile' }, diff --git a/README.md b/README.md index 2dfe31a..09c96c7 100644 --- a/README.md +++ b/README.md @@ -22,14 +22,14 @@ npm install sudo npm install -g grunt-cli ``` -##Build the resources +## Build the resources In order to build the static files you have to run grunt tasks which will generate dist directories containing the js and css files, fonts and images. ```bash grunt ``` -##Run +## Run ```bash WS_SECRET="asdf" npm start diff --git a/lib/node.js b/lib/node.js index 8e4f9ca..454fa54 100644 --- a/lib/node.js +++ b/lib/node.js @@ -102,6 +102,9 @@ Node.prototype.setInfo = function(data, callback) Node.prototype.setGeo = function(ip) { + if (ip.substr(0, 7) == "::ffff:") { + ip = ip.substr(7) + } this.info.ip = ip; this.geo = geoip.lookup(ip); } diff --git a/lib/utils/config.js b/lib/utils/config.js index 88768f9..13587f2 100644 --- a/lib/utils/config.js +++ b/lib/utils/config.js @@ -1,29 +1,6 @@ -var trusted = [ - '52.16.188.185', - '54.94.239.50', - '54.174.74.156', - '54.172.25.93', - '54.174.75.126', - '54.173.232.137', - '52.7.205.180', - '52.7.218.44', - '52.7.205.152', - '52.7.224.174', - '92.51.165.126', - '84.117.82.122', - '73.40.58.88', - '178.19.221.38', - '185.37.145.18', - '172.31.39.87', - '86.120.171.69', - '86.123.155.6', - '188.24.81.133', - '::ffff:127.0.0.1', -]; +var trusted = []; -var banned = [ - // '198.48.150.206' -]; +var banned = []; module.exports = { trusted: trusted, diff --git a/package.json b/package.json index a53eea5..bc29067 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "netstats-server", - "description": "POA Network Intelligence dashboard", + "description": "Görli Network Dashboard", "version": "0.1.0", "private": true, "engines": { diff --git a/src/css/style.css b/src/css/style.css index 3d28eda..eb02bc7 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -10,6 +10,41 @@ body { -moz-osx-font-smoothing: grayscale; } +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 200; + src: local('Source Sans Pro ExtraLight'), local('SourceSansPro-ExtraLight'), url(../fonts/SourceSansPro-ExtraLight.woff2) format('woff2'); +} + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 300; + src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(../fonts/SourceSansPro-Light.woff2) format('woff2'); +} + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 400; + src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(../fonts/SourceSansPro-Regular.woff2) format('woff2'); +} + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 600; + src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url(../fonts/SourceSansPro-SemiBold.woff2) format('woff2'); +} + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 700; + src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url(../fonts/SourceSansPro-Bold.woff2) format('woff2'); +} + table td { font-size: 14px; white-space: nowrap !important; @@ -60,7 +95,7 @@ table td { .text-gray .propagationBox { background: none !important; - border: 1px solid #f8f8f2; + border: 1px solid #777; } .bg-success, @@ -72,7 +107,7 @@ table td { } .text-gray { - color: #f8f8f2 !important; + color: #777 !important; } .text-orange { @@ -153,9 +188,9 @@ span.small-title span.small { } .big-info.chart .big-details { - display: block; - position: absolute; + display: table; top: 40px; + margin: 0 auto; } .big-info.chart { @@ -172,6 +207,8 @@ span.small-title span.small { width: 288px; padding-top: 6px; margin-left: -2px; + display: table; + margin: 0 auto; } .blocks-holder { @@ -185,7 +222,7 @@ span.small-title span.small { letter-spacing: -0.1px; text-transform: none; white-space: nowrap; - color: #f8f8f2; + color: #777; } .blocks-holder .block-count { @@ -460,7 +497,7 @@ svg .axis line { shape-rendering: crispEdges; } svg .axis text { - fill: #f8f8f2; + fill: #777; font-size: 10px; letter-spacing: 0px; font-family: "Source Sans Pro"; @@ -472,3 +509,50 @@ svg .axis text { svg .y.axis .tick:first-child text { opacity: 0; } + +@media (max-width: 768px) { + .container-fluid { + padding-left: 5px; + padding-right: 5px; + } + + .big-info .icon-full-width i { + width: 75px; + height: 67px; + font-size: 67px; + margin-left: -25px; + } + + .big-info .big-details-holder { + left: 75px; + } + + .big-info .big-details { + font-size: 35px; + } + + .blocks-holder div.small-title-miner { + font-family: inherit; + font-size: 11px; + letter-spacing: -.5px; + } + + .blocks-holder { + width: 100%; + } + + .big-info.chart i, .second-row .box i { + font-size: 18px; + margin-right: 0px; + } + + .second-row .box { + height: 100%; /* BUG XXX */ + } +} + +@media (max-width: 600px) { + .blocks-holder div.small-title-miner { + font-size: 10px; + } +} diff --git a/src/fonts/SourceSansPro-Bold.woff2 b/src/fonts/SourceSansPro-Bold.woff2 new file mode 100644 index 0000000..52b6d69 Binary files /dev/null and b/src/fonts/SourceSansPro-Bold.woff2 differ diff --git a/src/fonts/SourceSansPro-ExtraLight.woff2 b/src/fonts/SourceSansPro-ExtraLight.woff2 new file mode 100644 index 0000000..3605fb6 Binary files /dev/null and b/src/fonts/SourceSansPro-ExtraLight.woff2 differ diff --git a/src/fonts/SourceSansPro-Light.woff2 b/src/fonts/SourceSansPro-Light.woff2 new file mode 100644 index 0000000..bfb4050 Binary files /dev/null and b/src/fonts/SourceSansPro-Light.woff2 differ diff --git a/src/fonts/SourceSansPro-Regular.woff2 b/src/fonts/SourceSansPro-Regular.woff2 new file mode 100644 index 0000000..efa300c Binary files /dev/null and b/src/fonts/SourceSansPro-Regular.woff2 differ diff --git a/src/fonts/SourceSansPro-SemiBold.woff2 b/src/fonts/SourceSansPro-SemiBold.woff2 new file mode 100644 index 0000000..e379bed Binary files /dev/null and b/src/fonts/SourceSansPro-SemiBold.woff2 differ diff --git a/src/js/directives.js b/src/js/directives.js index 76c9e8a..a85cb5a 100644 --- a/src/js/directives.js +++ b/src/js/directives.js @@ -100,6 +100,24 @@ angular.module('netStatsApp.directives', []) { tElement.replaceWith('' + tAttrs.data + ""); + // register resize watcher + var timeout; + var width; + $(window).on('resize', function(e) { + if( $('body').width() < 600 ) + width = 4; + else if( $('body').width() < 1200 ) + width = 5; + else + width = 6; + + if(timeout) + clearTimeout(timeout); + timeout = setTimeout(function() { + $.fn.sparkline.defaults.bar.barWidth = width; + }, 200); + }); + return function(scope, element, attrs) { attrs.$observe("data", function (newValue) @@ -302,6 +320,12 @@ angular.module('netStatsApp.directives', []) var width = 280 - margin.left - margin.right, height = 63 - margin.top - margin.bottom; + // fix for mobile devices + if( $('body').width() < 600 ) + width = 200 - margin.left - margin.right; + else( $('body').width() < 1200 ) + width = 240 - margin.left - margin.right; + var TICKS = 40; var x = d3.scale.linear() @@ -342,10 +366,26 @@ angular.module('netStatsApp.directives', []) return '
' + (d.x/1000) + 's - ' + ((d.x + d.dx)/1000) + 's
Percent: ' + Math.round(d.y * 100) + '%' + '
Frequency: ' + d.frequency + '
Cumulative: ' + Math.round(d.cumpercent*100) + '%
'; }) - scope.init = function() + scope.init = function(width) { var data = scope.data; + var x = d3.scale.linear() + .domain([0, 10000]) + .rangeRound([0, width]) + .interpolate(d3.interpolateRound); + + var xAxis = d3.svg.axis() + .scale(x) + .orient("bottom") + .ticks(4, ",.1s") + .tickFormat(function(t){ return t/1000 + "s"}); + + var line = d3.svg.line() + .x(function(d) { return x(d.x + d.dx/2) - 1; }) + .y(function(d) { return y(d.y) - 2; }) + .interpolate('basis'); + // Adjust y axis y.domain([0, d3.max(data, function(d) { return d.y; })]); @@ -414,9 +454,24 @@ angular.module('netStatsApp.directives', []) scope.$watch('data', function() { if(scope.data.length > 0) { - scope.init(); + scope.init(width); } }, true); + + var timeout; + $(window).on('resize', function(e) { + var width = 280 - margin.left - margin.right; + if( $('body').width() < 768 ) + width = 200 - margin.left - margin.right; + + if(timeout) + clearTimeout(timeout); + + timeout = setTimeout(function() { + // redraw + scope.init(width); + }, 200); + }); } }; }]); \ No newline at end of file diff --git a/src/js/filters.js b/src/js/filters.js index 40be828..ce3e849 100644 --- a/src/js/filters.js +++ b/src/js/filters.js @@ -59,35 +59,17 @@ angular.module('netStatsApp.filters', []) }) .filter('hashrateFilter', ['$sce', '$filter', function($sce, filter) { return function(hashes, isMining) { - var result = 0; - var unit = 'K'; - if( !isMining ) return $sce.trustAsHtml(''); - if(hashes !== 0 && hashes < 1000) { - result = hashes; - unit = ''; - } - - if(hashes >= 1000 && hashes < Math.pow(1000, 2)) { - result = hashes / 1000; - unit = 'K'; - } - - if(hashes >= Math.pow(1000, 2) && hashes < Math.pow(1000, 3)) { - result = hashes / Math.pow(1000, 2); - unit = 'M'; - } - - if(hashes >= Math.pow(1000, 3) && hashes < Math.pow(1000, 4)) { - result = hashes / Math.pow(1000, 3); - unit = 'G'; - } + var result = hashes; + var units = ['', 'K', 'M', 'G', 'T', 'P', 'E']; + var unit = 'K'; - if(hashes >= Math.pow(1000, 4) && hashes < Math.pow(1000, 5)) { - result = hashes / Math.pow(1000, 4); - unit = 'T'; + for(var i = 1; result > 1000; i++) + { + result /= 1000; + unit = units[i]; } return $sce.trustAsHtml('' + filter('number')(result.toFixed(1)) + ' ' + unit + 'H/s'); @@ -95,32 +77,14 @@ angular.module('netStatsApp.filters', []) }]) .filter('totalDifficultyFilter', function() { return function(hashes) { - var result = 0; + var result = hashes; + var units = ['', 'K', 'M', 'G', 'T', 'P', 'E']; var unit = ''; - if(hashes !== 0 && hashes < 1000) { - result = hashes; - unit = ''; - } - - if(hashes >= 1000 && hashes < Math.pow(1000, 2)) { - result = hashes / 1000; - unit = 'K'; - } - - if(hashes >= Math.pow(1000, 2) && hashes < Math.pow(1000, 3)) { - result = hashes / Math.pow(1000, 2); - unit = 'M'; - } - - if(hashes >= Math.pow(1000, 3) && hashes < Math.pow(1000, 4)) { - result = hashes / Math.pow(1000, 3); - unit = 'G'; - } - - if(hashes >= Math.pow(1000, 4) && hashes < Math.pow(1000, 5)) { - result = hashes / Math.pow(1000, 4); - unit = 'T'; + for(var i = 1; result > 1000; i++) + { + result /= 1000; + unit = units[i]; } return result.toFixed(2) + ' ' + unit + 'H'; @@ -327,32 +291,14 @@ angular.module('netStatsApp.filters', []) if(hashes === null) hashes = 0; - var result = 0; + var result = hashes; + var units = ['', 'K', 'M', 'G', 'T', 'P']; var unit = 'K'; - if(hashes !== 0 && hashes < 1000) { - result = hashes; - unit = ''; - } - - if(hashes >= 1000 && hashes < Math.pow(1000, 2)) { - result = hashes / 1000; - unit = 'K'; - } - - if(hashes >= Math.pow(1000, 2) && hashes < Math.pow(1000, 3)) { - result = hashes / Math.pow(1000, 2); - unit = 'M'; - } - - if(hashes >= Math.pow(1000, 3) && hashes < Math.pow(1000, 4)) { - result = hashes / Math.pow(1000, 3); - unit = 'G'; - } - - if(hashes >= Math.pow(1000, 4) && hashes < Math.pow(1000, 5)) { - result = hashes / Math.pow(1000, 4); - unit = 'T'; + for(var i = 1; result > 1000; i++) + { + result /= 1000; + unit = units[i]; } if( !isMining ) diff --git a/src/js/script.js b/src/js/script.js index 1e71e2b..37fee5e 100644 --- a/src/js/script.js +++ b/src/js/script.js @@ -7,6 +7,11 @@ $.fn.sparkline.defaults.bar.height = 63; $.fn.sparkline.defaults.bar.barWidth = 6; + + if( $('body').width() < 600 ) + $.fn.sparkline.defaults.bar.barWidth = 4; + else if( $('body').width() < 1200 ) + $.fn.sparkline.defaults.bar.barWidth = 5; $.fn.sparkline.defaults.bar.barSpacing = 1; $.fn.sparkline.defaults.bar.tooltipClassname = 'jqstooltip'; $.fn.sparkline.defaults.bar.tooltipOffsetX = 0; @@ -26,12 +31,3 @@ moment.relativeTimeThreshold('M', 12); })(); - -(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ -(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), -m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) -})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - -// ga('create', 'UA-68390837-2', 'auto'); -ga('create', 'UA-80834434-1', 'auto'); -ga('send', 'pageview'); \ No newline at end of file diff --git a/src/views/layout.jade b/src/views/layout.jade index 4822caa..ccb7cfe 100644 --- a/src/views/layout.jade +++ b/src/views/layout.jade @@ -3,11 +3,12 @@ doctype html html(ng-app="netStatsApp") head meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0") - title Ethereum Network Status + title Görli Network Status style(type="text/css") [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; } - link(rel='stylesheet', href='//fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,600,700') link(rel='stylesheet', href='/css/netstats.min.css') + meta(name='robots', content='index,follow') + meta(name='googlebot', content='index,follow') + link(rel='shortcut icon', type="image/x-icon", href="/favicon.ico") body block content - - script(src="/js/netstats.min.js") \ No newline at end of file + script(src="/js/netstats.min.js")