333 lines
No EOL
12 KiB
HTML
333 lines
No EOL
12 KiB
HTML
<!DOCTYPE html>
|
|
<html lang=\"en\">
|
|
<head>
|
|
<meta charset=\"utf-8\">
|
|
<title>XMRigCC Dashboard</title>
|
|
|
|
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css">
|
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
|
|
|
<style>
|
|
.left{text-align:left;}
|
|
.right{text-align:right;}
|
|
.center{text-align:center;}
|
|
.toolbar { float: right; padding-left: 10pt;}
|
|
.online { color: green}
|
|
.offline { color: red}
|
|
</style>
|
|
|
|
<script type="text/javascript" language="javascript" src="//code.jquery.com/jquery-1.12.4.js"></script>
|
|
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
|
|
<script type="text/javascript" language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-timeago/1.6.1/jquery.timeago.min.js"></script>
|
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
|
<script src="https://use.fontawesome.com/6b3cdfc597.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
$.fn.dataTable.ext.search.push(
|
|
function( settings, data, dataIndex ) {
|
|
var hide = document.getElementById("hideOffline").checked;
|
|
|
|
var lastStatus = settings.aoData[dataIndex]._aData.client_status.last_status_update * 1000;
|
|
var threshold = new Date().getTime() - 60 * 1000;
|
|
|
|
if (lastStatus > threshold || !hide) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
);
|
|
|
|
$(document).ready(function() {
|
|
var table = $('#clientStatusList').DataTable({
|
|
dom: '<"toolbar">frtip',
|
|
processing : true,
|
|
bPaginate : false,
|
|
ajax : {
|
|
url : "/admin/getClientStatusList",
|
|
dataSrc : 'client_status_list'
|
|
},
|
|
columns: [
|
|
{ data: "client_status.client_id", render: clientInfo},
|
|
{ data: "client_status.current_pool"},
|
|
{ data: "client_status.current_status"},
|
|
{ data: "client_status.current_algo_name"},
|
|
{ data: "client_status.hashrate_short", render: round, className: "right"},
|
|
{ data: "client_status.hashrate_medium", render: round, className: "right"},
|
|
{ data: "client_status.hashrate_long", render: round, className: "right"},
|
|
{ data: "client_status.hashrate_highest", render: round, className: "right"},
|
|
{ data: "client_status.hashes_total", className: "right"},
|
|
{ data: "client_status.avg_time", className: "right"},
|
|
{ data: "client_status.shares_good", className: "right"},
|
|
{ data: "client_status.shares_total", className: "right"},
|
|
{ data: "client_status.last_status_update", render: laststatus},
|
|
{
|
|
targets: -1,
|
|
data: null,
|
|
defaultContent:
|
|
"<td><button type='button' id='START' class='btn btn-xs btn-success' data-toggle='tooltip' title='Start'><i class='fa fa-play'></i></button></td>" +
|
|
"<td><button type='button' id='STOP' class='btn btn-xs btn-warning' data-toggle='tooltip' title='Stop'><i class='fa fa-pause'></i></button></td>" +
|
|
"<td><button type='button' id='RESTART' class='btn btn-xs' data-toggle='tooltip' title='Restart'><i class='fa fa-repeat'></i></button></td>" +
|
|
"<td><button type='button' id='UPDATE_CONFIG' class='btn btn-xs btn-info' data-toggle='tooltip' title='Update Config'><i class='fa fa-refresh'></i></button></td>" +
|
|
"<td><button type='button' id='EDIT' class='btn btn-xs btn-primary' data-toggle='tooltip' title='Edit Client Config'><i class='fa fa-cog'></i></button></td>" +
|
|
"<td><button type='button' id='SHUTDOWN' class='btn btn-xs btn-danger' data-toggle='tooltip' title='Stutdown Client'><i class='fa fa-power-off'></i></button></td>",
|
|
className: "center"
|
|
}
|
|
],
|
|
order: [ 0, 'asc' ],
|
|
|
|
"footerCallback": function ( row, data, start, end, display ) {
|
|
var api = this.api();
|
|
|
|
sumHashrateShort = round(api
|
|
.column(4)
|
|
.data()
|
|
.reduce( function (a, b) {
|
|
return a + b;
|
|
}, 0 ));
|
|
|
|
sumHashrateMedium = round(api
|
|
.column(5)
|
|
.data()
|
|
.reduce( function (a, b) {
|
|
return a + b;
|
|
}, 0 ));
|
|
|
|
sumHashrateLong = round(api
|
|
.column(6)
|
|
.data()
|
|
.reduce( function (a, b) {
|
|
return a + b;
|
|
}, 0 ));
|
|
|
|
sumHashrateHighest = round(api
|
|
.column(7)
|
|
.data()
|
|
.reduce( function (a, b) {
|
|
return a + b;
|
|
}, 0 ));
|
|
|
|
sumHashesTotal = api
|
|
.column(8)
|
|
.data()
|
|
.reduce( function (a, b) {
|
|
return a + b;
|
|
}, 0 );
|
|
|
|
avgTimeTotal = round(api
|
|
.column(9)
|
|
.data()
|
|
.reduce( function (a, b) {
|
|
return a + b;
|
|
}, 0 )/end);
|
|
|
|
sumSharesGood = api
|
|
.column(10)
|
|
.data()
|
|
.reduce( function (a, b) {
|
|
return a + b;
|
|
}, 0 );
|
|
|
|
sumSharedTotal = api
|
|
.column(11)
|
|
.data()
|
|
.reduce( function (a, b) {
|
|
return a + b;
|
|
}, 0 );
|
|
|
|
// Update footer
|
|
$(api.column(4).footer()).html(sumHashrateShort);
|
|
$(api.column(5).footer()).html(sumHashrateMedium);
|
|
$(api.column(6).footer()).html(sumHashrateLong);
|
|
$(api.column(7).footer()).html(sumHashrateHighest);
|
|
$(api.column(8).footer()).html(sumHashesTotal);
|
|
$(api.column(9).footer()).html(avgTimeTotal);
|
|
$(api.column(10).footer()).html(sumSharesGood);
|
|
$(api.column(11).footer()).html(sumSharedTotal);
|
|
}
|
|
});
|
|
|
|
$("div.toolbar").html('<input type="checkbox" id="hideOffline" value="hide" checked style="margin-right: 5pt"><label>Hide offline miners</label>');
|
|
|
|
$('#clientStatusList tbody').on( 'click', 'button', function () {
|
|
var data = table.row( $(this).parents('tr') ).data();
|
|
var clientId = data['client_status']['client_id'];
|
|
var action = this.id;
|
|
|
|
if (action != "EDIT"){
|
|
$.ajax({
|
|
type: "POST",
|
|
url: "/admin/setClientCommand?clientId=" + clientId,
|
|
dataType:"text",
|
|
data: '{"control_command":{"command": "' + action + '"}}',
|
|
success: function(data){
|
|
alert("Successfully send: " + action + " to: " + clientId);
|
|
},
|
|
error: function (data) {
|
|
alert("Failed to send: " + action +" to: " + clientId + "\nError: " + JSON.stringify(data,undefined, 2));
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
$.ajax({
|
|
type: "GET",
|
|
url: "/admin/getClientConfig?clientId=" + clientId,
|
|
dataType:"json",
|
|
success: function(jsonClientConfig) {
|
|
var htmlContent = "<div class='form-group' id='editor' data-value='" + clientId + "'>" +
|
|
"<label for='config'>Config for: " + clientId + "</label>"+
|
|
"<textarea class='form-control' rows='20' id='config'>" +
|
|
JSON.stringify(jsonClientConfig,undefined, 2) +
|
|
"</textarea>" +
|
|
"</div>";
|
|
|
|
$('#editConfig').find('.modal-body').html(htmlContent);
|
|
$('#editConfig').modal('show');
|
|
},
|
|
error: function (data) {
|
|
alert("Unable to fetch " + clientId + "_config.json or default_config.json, please check your Server configuration and the the config files are located on the Server!");
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
$('button.btn.btn-success').click(function(event)
|
|
{
|
|
var clientId = $('#editConfig').find('.form-group')["0"].dataset.value;
|
|
|
|
event.preventDefault();
|
|
$.ajax({
|
|
url: "/admin/setClientConfig?clientId=" + clientId,
|
|
type: 'POST',
|
|
dataType: "text",
|
|
data: $('#config').val(),
|
|
success: function(data){
|
|
alert("Successfully saved config for: " + clientId);
|
|
},
|
|
error: function (data) {
|
|
alert("Failed to store config for: " + clientId + "\nError: " + JSON.stringify(data,undefined, 2));
|
|
}
|
|
});
|
|
});
|
|
|
|
$('#hideOffline').click( function() {
|
|
table.draw();
|
|
} );
|
|
|
|
setInterval(function () {
|
|
table.ajax.reload();
|
|
}, 10000);
|
|
});
|
|
|
|
function laststatus( data, type, row ) {
|
|
var date = new Date(data*1000);
|
|
|
|
return '<span data-toggle="tooltip" title="' + date + '">' + jQuery.timeago(date) + '</span>';
|
|
}
|
|
|
|
function clientInfo( data, type, row ) {
|
|
var tooltip = "CPU: " + row.client_status.cpu_brand + " [" + row.client_status.cpu_cores + " cores]";
|
|
tooltip += '\n';
|
|
tooltip += "CPU Flags: " + (row.client_status.cpu_has_aes ? "AES-NI " : "");
|
|
tooltip += (row.client_status.cpu_is_x64 ? "x64" : "");
|
|
tooltip += '\n';
|
|
tooltip += "CPU Cache L2/L3: " + (row.client_status.cpu_l2 / 1024) + " MB/"+ (row.client_status.cpu_l3 / 1024) + " MB";
|
|
tooltip += '\n';
|
|
tooltip += "Huge Pages: " + (row.client_status.hugepages_available ? " available, " : " unavailable, ");
|
|
tooltip += (row.client_status.hugepages_enabled ? "enabled" : "disabled");
|
|
tooltip += '\n';
|
|
tooltip += "Used Threads: " + row.client_status.current_threads;
|
|
tooltip += (row.client_status.double_hash_mode ? " [double hash mode]" :"");
|
|
tooltip += '\n';
|
|
tooltip += "Client IP: " + row.client_status.external_ip;
|
|
tooltip += '\n';
|
|
tooltip += "Status: ";
|
|
|
|
var lastStatus = row.client_status.last_status_update * 1000;
|
|
var threshold = new Date().getTime() - 60 * 1000;
|
|
if (lastStatus > threshold) {
|
|
tooltip += "Online";
|
|
return '<span data-toggle="tooltip" title="'+ tooltip + '"><div class="online">' + data + '</div></span>';
|
|
}
|
|
else {
|
|
tooltip += "Offline";
|
|
return '<span data-toggle="tooltip" title="'+ tooltip + '"><div class="offline">' + data + '</div></span>';
|
|
}
|
|
}
|
|
|
|
function round( data, type, row ) {
|
|
return Math.round(data * 100) / 100;
|
|
}
|
|
|
|
</script>
|
|
|
|
</head>
|
|
<body>
|
|
<br/>
|
|
<div style="width: 90%; margin:0 auto;">
|
|
<div class="center">
|
|
<h1>XMRigCC Dashboard</h1>
|
|
</div>
|
|
<table id="clientStatusList" class="display" cellspacing="0" width="100%">
|
|
<thead>
|
|
<tr>
|
|
<th>Client Id</th>
|
|
<th>Pool</th>
|
|
<th>Status</th>
|
|
<th>Algo</th>
|
|
|
|
<th>Hashrate</th>
|
|
<th>Hashrate 5m</th>
|
|
<th>Hashrate 60m</th>
|
|
|
|
<th>Hashrate Highest</th>
|
|
<th>Hashes Total</th>
|
|
<th>Avg. Time</th>
|
|
|
|
<th>Shares Good</th>
|
|
<th>Shares Total</th>
|
|
<th>Last Update</th>
|
|
<th colspan="6" class="center">Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tfoot>
|
|
<tr>
|
|
<th class="left">Total:</th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
|
|
<div class="modal fade" id="editConfig" role="dialog">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
|
<h4 class="modal-title">Config editor</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-success" data-dismiss="modal">Save</button>
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html> |