15 |
16 |
17 | This script run client-side (in your browser). For maximum security download the script and run it locally and
18 | offline in a modern web browser.
19 |
20 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/website/pages/stats.html:
--------------------------------------------------------------------------------
1 |
30 |
31 |
37 |
38 | {{ for(var pool in it.stats.pools) { }}
39 |
40 |
41 |
{{=it.stats.pools[pool].name}}
42 |
43 |
44 |
45 |
46 | Address
47 | Shares
48 | Invalid shares
49 | Efficiency
50 | Hashrate
51 |
52 |
53 | {{ for(var worker in it.stats.pools[pool].workers) { }}
54 | {{var workerstat = it.stats.pools[pool].workers[worker];}}
55 |
56 | {{=worker}}
57 | {{=Math.floor(workerstat.shares)}}
58 | {{=Math.floor(workerstat.invalidshares)}}
59 | {{? workerstat.shares > 0}} {{=Math.floor(10000 * workerstat.shares / (workerstat.shares + workerstat.invalidshares)) / 100}}% {{??}} 0% {{?}}
60 | {{=workerstat.hashrateString}}
61 |
62 | {{ } }}
63 |
64 |
65 |
66 | {{ } }}
67 |
--------------------------------------------------------------------------------
/website/static/admin.js:
--------------------------------------------------------------------------------
1 | var docCookies = {
2 | getItem: function (sKey) {
3 | return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
4 | },
5 | setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
6 | if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
7 | var sExpires = "";
8 | if (vEnd) {
9 | switch (vEnd.constructor) {
10 | case Number:
11 | sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
12 | break;
13 | case String:
14 | sExpires = "; expires=" + vEnd;
15 | break;
16 | case Date:
17 | sExpires = "; expires=" + vEnd.toUTCString();
18 | break;
19 | }
20 | }
21 | document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
22 | return true;
23 | },
24 | removeItem: function (sKey, sPath, sDomain) {
25 | if (!sKey || !this.hasItem(sKey)) { return false; }
26 | document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + ( sDomain ? "; domain=" + sDomain : "") + ( sPath ? "; path=" + sPath : "");
27 | return true;
28 | },
29 | hasItem: function (sKey) {
30 | return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
31 | }
32 | };
33 |
34 | var password = docCookies.getItem('password');
35 |
36 |
37 | function showLogin(){
38 | $('#adminCenter').hide();
39 | $('#passwordForm').show();
40 | }
41 |
42 | function showAdminCenter(){
43 | $('#passwordForm').hide();
44 | $('#adminCenter').show();
45 | }
46 |
47 | function tryLogin(){
48 | apiRequest('pools', {}, function(response){
49 | showAdminCenter();
50 | displayMenu(response.result)
51 | });
52 | }
53 |
54 | function displayMenu(pools){
55 | $('#poolList').after(Object.keys(pools).map(function(poolName){
56 | return '';
57 | }).join(''));
58 | }
59 |
60 | function apiRequest(func, data, callback){
61 | var httpRequest = new XMLHttpRequest();
62 | httpRequest.onreadystatechange = function(){
63 | if (httpRequest.readyState === 4 && httpRequest.responseText){
64 | if (httpRequest.status === 401){
65 | docCookies.removeItem('password');
66 | $('#password').val('');
67 | showLogin();
68 | alert('Incorrect Password');
69 | }
70 | else{
71 | var response = JSON.parse(httpRequest.responseText);
72 | callback(response);
73 | }
74 | }
75 | };
76 | httpRequest.open('POST', '/api/admin/' + func);
77 | data.password = password;
78 | httpRequest.setRequestHeader('Content-Type', 'application/json');
79 | httpRequest.send(JSON.stringify(data));
80 | }
81 |
82 | if (password){
83 | tryLogin();
84 | }
85 | else{
86 | showLogin();
87 | }
88 |
89 | $('#passwordForm').submit(function(event){
90 | event.preventDefault();
91 | password = $('#password').val();
92 | if (password){
93 | if ($('#remember').is(':checked'))
94 | docCookies.setItem('password', password, Infinity);
95 | else
96 | docCookies.setItem('password', password);
97 | tryLogin();
98 | }
99 | return false;
100 | });
101 |
--------------------------------------------------------------------------------
/website/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zone117x/node-open-mining-portal/b1b4daaa76d1ca98b29be056c710222518e7ac72/website/static/favicon.png
--------------------------------------------------------------------------------
/website/static/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/website/static/main.js:
--------------------------------------------------------------------------------
1 | $(function(){
2 |
3 | var hotSwap = function(page, pushSate){
4 | if (pushSate) history.pushState(null, null, '/' + page);
5 | $('.pure-menu-selected').removeClass('pure-menu-selected');
6 | $('a[href="/' + page + '"]').parent().addClass('pure-menu-selected');
7 | $.get("/get_page", {id: page}, function(data){
8 | $('main').html(data);
9 | }, 'html')
10 | };
11 |
12 | $('.hot-swapper').click(function(event){
13 | if (event.which !== 1) return;
14 | var pageId = $(this).attr('href').slice(1);
15 | hotSwap(pageId, true);
16 | event.preventDefault();
17 | return false;
18 | });
19 |
20 | window.addEventListener('load', function() {
21 | setTimeout(function() {
22 | window.addEventListener("popstate", function(e) {
23 | hotSwap(location.pathname.slice(1));
24 | });
25 | }, 0);
26 | });
27 |
28 | window.statsSource = new EventSource("/api/live_stats");
29 |
30 | });
31 |
--------------------------------------------------------------------------------
/website/static/nvd3.css:
--------------------------------------------------------------------------------
1 | .chartWrap{margin:0;padding:0;overflow:hidden}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nvtooltip{position:absolute;background-color:rgba(255,255,255,1);padding:1px;border:1px solid rgba(0,0,0,.2);z-index:10000;font-family:Arial;font-size:13px;text-align:left;pointer-events:none;white-space:nowrap;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 250ms linear;-moz-transition:opacity 250ms linear;-webkit-transition:opacity 250ms linear;transition-delay:250ms;-moz-transition-delay:250ms;-webkit-transition-delay:250ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{margin:0;padding:4px 14px;line-height:18px;font-weight:400;background-color:rgba(247,247,247,.75);text-align:center;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.nvtooltip p{margin:0;padding:5px 14px;text-align:center}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key{font-weight:400}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{width:8px;height:8px;vertical-align:middle}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{position:absolute;pointer-events:none}svg{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:block;width:100%;height:100%}svg text{font:400 12px Arial}svg .title{font:700 14px Arial}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125;shape-rendering:crispEdges}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .disabled circle{fill-opacity:0}.nvd3 .nv-axis{pointer-events:none}.nvd3 .nv-axis path{fill:none;stroke:#000;stroke-opacity:.75;shape-rendering:crispEdges}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{fill:none;stroke:#e5e5e5;shape-rendering:crispEdges}.nvd3 .nv-axis .zero line,.nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-bars .negative rect{zfill:brown}.nvd3 .nv-bars rect{zfill:#4682b4;fill-opacity:.75;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:rgba(0,0,0,0)}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect,.nvd3 .nv-discretebar .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:rgba(0,0,0,0)}.nvd3.nv-pie path{stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{stroke:#fff;stroke-width:1px;stroke-opacity:1}.nvd3.nv-pie .hover path{fill-opacity:.7}.nvd3.nv-pie .nv-label{pointer-events:none}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups path.nv-line{fill:none;stroke-width:1.5px}.nvd3 .nv-groups path.nv-line.nv-thin-line{stroke-width:1px}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3 .nv-line.hover path{stroke-width:6px}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-scatter .nv-groups .nv-point.hover,.nvd3 .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}.nvd3 .nv-distribution{pointer-events:none}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:4px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3.nv-historicalStockChart .nv-axis .nv-axislabel{font-weight:700}.nvd3.nv-historicalStockChart .nv-dragTarget{fill-opacity:0;stroke:none;cursor:move}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}.nvd3.nv-indentedtree .name{margin-left:5px}.nvd3.nv-indentedtree .clickable{color:#08C;cursor:pointer}.nvd3.nv-indentedtree span.clickable:hover{color:#005580;text-decoration:underline}.nvd3.nv-indentedtree .nv-childrenCount{display:inline-block;margin-left:5px}.nvd3.nv-indentedtree .nv-treeicon{cursor:pointer}.nvd3.nv-indentedtree .nv-treeicon.nv-folded{cursor:pointer}.nvd3 .background path{fill:none;stroke:#ccc;stroke-opacity:.4;shape-rendering:crispEdges}.nvd3 .foreground path{fill:none;stroke:#4682b4;stroke-opacity:.7}.nvd3 .brush .extent{fill-opacity:.3;stroke:#fff;shape-rendering:crispEdges}.nvd3 .axis line,.axis path{fill:none;stroke:#000;shape-rendering:crispEdges}.nvd3 .axis text{text-shadow:0 1px 0 #fff}.nvd3 .nv-interactiveGuideLine{pointer-events:none}.nvd3 line.nv-guideline{stroke:#ccc}
--------------------------------------------------------------------------------
/website/static/stats.js:
--------------------------------------------------------------------------------
1 | var poolWorkerData;
2 | var poolHashrateData;
3 | var poolBlockData;
4 |
5 | var poolWorkerChart;
6 | var poolHashrateChart;
7 | var poolBlockChart;
8 |
9 | var statData;
10 | var poolKeys;
11 |
12 | function buildChartData(){
13 |
14 | var pools = {};
15 |
16 | poolKeys = [];
17 | for (var i = 0; i < statData.length; i++){
18 | for (var pool in statData[i].pools){
19 | if (poolKeys.indexOf(pool) === -1)
20 | poolKeys.push(pool);
21 | }
22 | }
23 |
24 |
25 | for (var i = 0; i < statData.length; i++){
26 |
27 | var time = statData[i].time * 1000;
28 |
29 | for (var f = 0; f < poolKeys.length; f++){
30 | var pName = poolKeys[f];
31 | var a = pools[pName] = (pools[pName] || {
32 | hashrate: [],
33 | workers: [],
34 | blocks: []
35 | });
36 | if (pName in statData[i].pools){
37 | a.hashrate.push([time, statData[i].pools[pName].hashrate]);
38 | a.workers.push([time, statData[i].pools[pName].workerCount]);
39 | a.blocks.push([time, statData[i].pools[pName].blocks.pending])
40 | }
41 | else{
42 | a.hashrate.push([time, 0]);
43 | a.workers.push([time, 0]);
44 | a.blocks.push([time, 0])
45 | }
46 |
47 | }
48 |
49 | }
50 |
51 | poolWorkerData = [];
52 | poolHashrateData = [];
53 | poolBlockData = [];
54 |
55 | for (var pool in pools){
56 | poolWorkerData.push({
57 | key: pool,
58 | values: pools[pool].workers
59 | });
60 | poolHashrateData.push({
61 | key: pool,
62 | values: pools[pool].hashrate
63 | });
64 | poolBlockData.push({
65 | key: pool,
66 | values: pools[pool].blocks
67 | })
68 | }
69 | }
70 |
71 | function getReadableHashRateString(hashrate){
72 | var i = -1;
73 | var byteUnits = [ ' KH', ' MH', ' GH', ' TH', ' PH' ];
74 | do {
75 | hashrate = hashrate / 1024;
76 | i++;
77 | } while (hashrate > 1024);
78 | return Math.round(hashrate) + byteUnits[i];
79 | }
80 |
81 | function timeOfDayFormat(timestamp){
82 | var dStr = d3.time.format('%I:%M %p')(new Date(timestamp));
83 | if (dStr.indexOf('0') === 0) dStr = dStr.slice(1);
84 | return dStr;
85 | }
86 |
87 | function displayCharts(){
88 |
89 | nv.addGraph(function() {
90 | poolWorkerChart = nv.models.stackedAreaChart()
91 | .margin({left: 40, right: 40})
92 | .x(function(d){ return d[0] })
93 | .y(function(d){ return d[1] })
94 | .useInteractiveGuideline(true)
95 | .clipEdge(true);
96 |
97 | poolWorkerChart.xAxis.tickFormat(timeOfDayFormat);
98 |
99 | poolWorkerChart.yAxis.tickFormat(d3.format('d'));
100 |
101 | d3.select('#poolWorkers').datum(poolWorkerData).call(poolWorkerChart);
102 |
103 | return poolWorkerChart;
104 | });
105 |
106 |
107 | nv.addGraph(function() {
108 | poolHashrateChart = nv.models.lineChart()
109 | .margin({left: 60, right: 40})
110 | .x(function(d){ return d[0] })
111 | .y(function(d){ return d[1] })
112 | .useInteractiveGuideline(true);
113 |
114 | poolHashrateChart.xAxis.tickFormat(timeOfDayFormat);
115 |
116 | poolHashrateChart.yAxis.tickFormat(function(d){
117 | return getReadableHashRateString(d);
118 | });
119 |
120 | d3.select('#poolHashrate').datum(poolHashrateData).call(poolHashrateChart);
121 |
122 | return poolHashrateChart;
123 | });
124 |
125 |
126 | nv.addGraph(function() {
127 | poolBlockChart = nv.models.multiBarChart()
128 | .x(function(d){ return d[0] })
129 | .y(function(d){ return d[1] });
130 |
131 | poolBlockChart.xAxis.tickFormat(timeOfDayFormat);
132 |
133 | poolBlockChart.yAxis.tickFormat(d3.format('d'));
134 |
135 | d3.select('#poolBlocks').datum(poolBlockData).call(poolBlockChart);
136 |
137 | return poolBlockChart;
138 | });
139 | }
140 |
141 | function TriggerChartUpdates(){
142 | poolWorkerChart.update();
143 | poolHashrateChart.update();
144 | poolBlockChart.update();
145 | }
146 |
147 | nv.utils.windowResize(TriggerChartUpdates);
148 |
149 | $.getJSON('/api/pool_stats', function(data){
150 | statData = data;
151 | buildChartData();
152 | displayCharts();
153 | });
154 |
155 | statsSource.addEventListener('message', function(e){
156 | var stats = JSON.parse(e.data);
157 | statData.push(stats);
158 |
159 |
160 | var newPoolAdded = (function(){
161 | for (var p in stats.pools){
162 | if (poolKeys.indexOf(p) === -1)
163 | return true;
164 | }
165 | return false;
166 | })();
167 |
168 | if (newPoolAdded || Object.keys(stats.pools).length > poolKeys.length){
169 | buildChartData();
170 | displayCharts();
171 | }
172 | else {
173 | var time = stats.time * 1000;
174 | for (var f = 0; f < poolKeys.length; f++) {
175 | var pool = poolKeys[f];
176 | for (var i = 0; i < poolWorkerData.length; i++) {
177 | if (poolWorkerData[i].key === pool) {
178 | poolWorkerData[i].values.shift();
179 | poolWorkerData[i].values.push([time, pool in stats.pools ? stats.pools[pool].workerCount : 0]);
180 | break;
181 | }
182 | }
183 | for (var i = 0; i < poolHashrateData.length; i++) {
184 | if (poolHashrateData[i].key === pool) {
185 | poolHashrateData[i].values.shift();
186 | poolHashrateData[i].values.push([time, pool in stats.pools ? stats.pools[pool].hashrate : 0]);
187 | break;
188 | }
189 | }
190 | for (var i = 0; i < poolBlockData.length; i++) {
191 | if (poolBlockData[i].key === pool) {
192 | poolBlockData[i].values.shift();
193 | poolBlockData[i].values.push([time, pool in stats.pools ? stats.pools[pool].blocks.pending : 0]);
194 | break;
195 | }
196 | }
197 | }
198 | TriggerChartUpdates();
199 | }
200 |
201 |
202 | });
--------------------------------------------------------------------------------
/website/static/style.css:
--------------------------------------------------------------------------------
1 | html, button, input, select, textarea, .pure-g [class *= "pure-u"], .pure-g-r [class *= "pure-u"]{
2 | font-family: 'Open Sans', sans-serif;
3 | }
4 |
5 | html{
6 | background: #2d2d2d;
7 | overflow-y: scroll;
8 | }
9 |
10 | body{
11 | display: flex;
12 | flex-direction: column;
13 | max-width: 1160px;
14 | margin: 0 auto;
15 | }
16 |
17 | header > .home-menu{
18 | background: inherit !important;
19 | height: 54px;
20 | display: flex;
21 | }
22 |
23 | header > .home-menu > a.pure-menu-heading, header > .home-menu > ul, header > .home-menu > ul > li{
24 | display: flex !important;
25 | align-items: center;
26 | justify-content: center;
27 | line-height: normal !important;
28 | }
29 |
30 | header > .home-menu > a.pure-menu-heading{
31 | color: white;
32 | font-size: 1.5em;
33 | }
34 |
35 | header > .home-menu > ul > li > a{
36 | color: #ced4d9;
37 | }
38 |
39 | header > .home-menu > ul > li > a:hover, header > .home-menu > ul > li > a:focus{
40 | background: inherit !important;
41 | }
42 |
43 | header > .home-menu > ul > li > a:hover, header > .home-menu > ul > li.pure-menu-selected > a{
44 | color: white;
45 | }
46 |
47 | main{
48 | background-color: #ebf4fa;
49 | position: relative;
50 | }
51 |
52 | footer{
53 | text-align: center;
54 | color: #b3b3b3;
55 | text-decoration: none;
56 | font-size: 0.8em;
57 | padding: 15px;
58 | line-height: 24px;
59 | }
60 |
61 | footer a{
62 | color: #fff;
63 | text-decoration: none;
64 | }
65 |
66 | footer iframe{
67 | vertical-align: middle;
68 | }
--------------------------------------------------------------------------------