Added notification when miner went offline
Added multi miner editor (search&replace) Cleaned error and info notifications
This commit is contained in:
parent
1573f50a4b
commit
b4af0b0e18
1 changed files with 157 additions and 68 deletions
225
index.html
225
index.html
|
@ -29,15 +29,32 @@
|
||||||
<script src="https://use.fontawesome.com/6b3cdfc597.js"></script>
|
<script src="https://use.fontawesome.com/6b3cdfc597.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
var TRESHOLD_IN_MS = 60 * 1000;
|
||||||
|
var RELOAD_INTERVAL_IN_MS = 10 * 1000;
|
||||||
|
|
||||||
$.fn.dataTable.ext.search.push(
|
$.fn.dataTable.ext.search.push(
|
||||||
function( settings, data, dataIndex ) {
|
function( settings, data, dataIndex ) {
|
||||||
var hide = document.getElementById("hideOffline").checked;
|
var hide = $('#hideOffline').hasClass("fa fa-check-square-o");
|
||||||
return (isOnline(settings.aoData[dataIndex]._aData.client_status.last_status_update * 1000) || !hide);
|
|
||||||
|
var clientId = settings.aoData[dataIndex]._aData.client_status.client_id;
|
||||||
|
var lastStatus = settings.aoData[dataIndex]._aData.client_status.last_status_update * 1000;
|
||||||
|
var online = isOnline(lastStatus);
|
||||||
|
|
||||||
|
if (!online) {
|
||||||
|
var threshold = new Date().getTime() - (TRESHOLD_IN_MS + RELOAD_INTERVAL_IN_MS);
|
||||||
|
if (lastStatus > threshold) {
|
||||||
|
$("#notificationBar").after('<div class="alert alert-danger alert-dismissable fade in">' +
|
||||||
|
'<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>' +
|
||||||
|
'<strong>Client ' + clientId + ' just went offline!</strong> Last update: ' + new Date(lastStatus) +
|
||||||
|
'</div>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (online || !hide);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
var latestRelease = "";
|
var latestRelease = "";
|
||||||
|
|
||||||
var table = $('#clientStatusList').DataTable({
|
var table = $('#clientStatusList').DataTable({
|
||||||
|
@ -71,7 +88,7 @@
|
||||||
{
|
{
|
||||||
data: null,
|
data: null,
|
||||||
defaultContent:
|
defaultContent:
|
||||||
"<td class='center-tab'><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 class='center-tab'><button type='button' id='EDIT' class='btn btn-xs btn-primary' data-toggle='tooltip' title='Edit Client Config'><i class='fa fa-edit'></i></button></td>",
|
||||||
orderable: false,
|
orderable: false,
|
||||||
className: "center-tab"
|
className: "center-tab"
|
||||||
}
|
}
|
||||||
|
@ -160,6 +177,14 @@
|
||||||
sendAction("SHUTDOWN", data.client_status.client_id);
|
sendAction("SHUTDOWN", data.client_status.client_id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '<i class="fa fa-edit"> Multi miner editor</i>',
|
||||||
|
className: 'btn-primary',
|
||||||
|
enabled: false,
|
||||||
|
action: function () {
|
||||||
|
$('#multiMinerEditor').modal('show');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -256,7 +281,7 @@
|
||||||
success: function (release) {
|
success: function (release) {
|
||||||
latestRelease = release.tag_name;
|
latestRelease = release.tag_name;
|
||||||
if (latestRelease !== $(api).context[0].json.current_version) {
|
if (latestRelease !== $(api).context[0].json.current_version) {
|
||||||
$("#notificationBar").html('<div class="alert alert-info alert-dismissable fade in">' +
|
$("#updateNotificationBar").html('<div class="alert alert-info alert-dismissable fade in">' +
|
||||||
'<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>' +
|
'<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>' +
|
||||||
'<a href="https://github.com/Bendr0id/xmrigCC/releases/latest"><strong>Update!</strong> XMRigCC v' + latestRelease + ' is available for download\n</a>' +
|
'<a href="https://github.com/Bendr0id/xmrigCC/releases/latest"><strong>Update!</strong> XMRigCC v' + latestRelease + ' is available for download\n</a>' +
|
||||||
'</div>');
|
'</div>');
|
||||||
|
@ -276,6 +301,7 @@
|
||||||
table.button(3).enable(selectedRows > 0);
|
table.button(3).enable(selectedRows > 0);
|
||||||
table.button(4).enable(selectedRows > 0);
|
table.button(4).enable(selectedRows > 0);
|
||||||
table.button(5).enable(selectedRows > 0);
|
table.button(5).enable(selectedRows > 0);
|
||||||
|
table.button(6).enable(selectedRows > 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
table.on('deselect', function () {
|
table.on('deselect', function () {
|
||||||
|
@ -287,11 +313,12 @@
|
||||||
table.button(3).enable(selectedRows > 0);
|
table.button(3).enable(selectedRows > 0);
|
||||||
table.button(4).enable(selectedRows > 0);
|
table.button(4).enable(selectedRows > 0);
|
||||||
table.button(5).enable(selectedRows > 0);
|
table.button(5).enable(selectedRows > 0);
|
||||||
|
table.button(6).enable(selectedRows > 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
table.buttons().container().appendTo( '#clientStatusList_wrapper .col-sm-6:eq(0)' );
|
table.buttons().container().appendTo( '#clientStatusList_wrapper .col-sm-6:eq(0)' );
|
||||||
|
|
||||||
$("div.toolbar").html('<input type="checkbox" id="hideOffline" value="hide" checked style="margin-right: 5pt"><label>Hide offline miners</label>');
|
$("div.toolbar").html('<div class="col-sm-13 fa fa-check-square-o" id="hideOffline"></div><label style="margin-left: 5px">Hide offline miners</label>');
|
||||||
|
|
||||||
$('#clientStatusList tbody').on( 'click', 'button', function () {
|
$('#clientStatusList tbody').on( 'click', 'button', function () {
|
||||||
var data = table.row( $(this).parents('tr') ).data();
|
var data = table.row( $(this).parents('tr') ).data();
|
||||||
|
@ -309,59 +336,56 @@
|
||||||
"</textarea>" +
|
"</textarea>" +
|
||||||
"</div>";
|
"</div>";
|
||||||
|
|
||||||
$('#editConfig').find('.modal-body').html(htmlContent);
|
$('#minerEditor').find('.modal-body').html(htmlContent);
|
||||||
$('#editConfig').modal('show');
|
$('#minerEditor').modal('show');
|
||||||
},
|
},
|
||||||
error: function (data) {
|
error: function (data) {
|
||||||
$("#statusBar").html('<div class="alert alert-danger" role="alert">' +
|
setError('Unable to fetch <strong>' + clientId + '_config.json</strong> - Please make sure that you pulled the config before!');
|
||||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
|
||||||
'<strong>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!</strong></div>');
|
|
||||||
|
|
||||||
window.setTimeout(function() {
|
|
||||||
$(".alert-danger").fadeTo(500, 0).slideUp(500, function(){
|
|
||||||
$(".alert-danger").alert('close');
|
|
||||||
});
|
|
||||||
}, 10000);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('button.btn.btn-success').click(function(event)
|
$('#minerEditorSave').click(function(event) {
|
||||||
{
|
var clientId = $('#minerEditor').find('.form-group')["0"].dataset.value;
|
||||||
var clientId = $('#editConfig').find('.form-group')["0"].dataset.value;
|
var clientConfig = $('#config').val();
|
||||||
|
|
||||||
event.preventDefault();
|
setClientConfig(clientId, clientConfig, false);
|
||||||
$.ajax({
|
});
|
||||||
url: "/admin/setClientConfig?clientId=" + clientId,
|
|
||||||
type: 'POST',
|
|
||||||
dataType: "text",
|
|
||||||
data: $('#config').val(),
|
|
||||||
success: function(data){
|
|
||||||
$("#statusBar").html('<div class="alert alert-success" role="alert">' +
|
|
||||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
|
||||||
'Successfully saved config for: ' + clientId + '<strong> - You need push the config to the client to apply the config.</strong></div>');
|
|
||||||
|
|
||||||
window.setTimeout(function() {
|
$('#multiMinerEditorReplace').click(function(event) {
|
||||||
$(".alert-success").fadeTo(500, 0).slideUp(500, function(){
|
table.rows({ selected: true }).eq(0).each(function (index) {
|
||||||
$(".alert-success").alert('close');
|
var row = table.row(index);
|
||||||
});
|
var data = row.data();
|
||||||
}, 5000);
|
|
||||||
},
|
|
||||||
error: function (data) {
|
|
||||||
$("#statusBar").html('<div class="alert alert-danger" role="alert">' +
|
|
||||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
|
||||||
'<strong>Failed to store config for: ' + clientId + '\nError: ' + JSON.stringify(data,undefined, 2) + '</strong></div>');
|
|
||||||
|
|
||||||
window.setTimeout(function() {
|
var clientId = data['client_status']['client_id'];
|
||||||
$(".alert-danger").fadeTo(500, 0).slideUp(500, function(){
|
var search = $('#search').val();
|
||||||
$(".alert-danger").alert('close');
|
var replacement = $('#replacement').val();
|
||||||
});
|
|
||||||
}, 10000);
|
$.ajax({
|
||||||
}
|
type: "GET",
|
||||||
|
url: "/admin/getClientConfig?clientId=" + clientId,
|
||||||
|
dataType:"json",
|
||||||
|
success: function(jsonClientConfig) {
|
||||||
|
jsonClientConfig = JSON.stringify(jsonClientConfig,undefined, 2);
|
||||||
|
jsonClientConfig = jsonClientConfig.replace(new RegExp(search.trim(), 'g'), replacement.trim()).trim();
|
||||||
|
|
||||||
|
setClientConfig(clientId, jsonClientConfig, true);
|
||||||
|
},
|
||||||
|
error: function (data) {
|
||||||
|
setError('Unable to fetch <strong>' + clientId + '_config.json</strong> - Please make sure that you pulled the config before!');
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$('#hideOffline').click( function() {
|
$('#hideOffline').click( function() {
|
||||||
|
if ($(this).hasClass("fa fa-square-o")) {
|
||||||
|
$(this).removeClass("fa fa-square-o").addClass("fa fa-check-square-o");
|
||||||
|
} else {
|
||||||
|
$(this).removeClass("fa fa-check-square-o").addClass("fa fa-square-o");
|
||||||
|
}
|
||||||
|
|
||||||
table.draw();
|
table.draw();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -381,7 +405,7 @@
|
||||||
|
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
table.ajax.reload();
|
table.ajax.reload();
|
||||||
}, 10000);
|
}, RELOAD_INTERVAL_IN_MS);
|
||||||
});
|
});
|
||||||
|
|
||||||
function sendAction(action, clientId) {
|
function sendAction(action, clientId) {
|
||||||
|
@ -391,26 +415,10 @@
|
||||||
dataType:"text",
|
dataType:"text",
|
||||||
data: '{"control_command":{"command": "' + action + '"}}',
|
data: '{"control_command":{"command": "' + action + '"}}',
|
||||||
success: function(data){
|
success: function(data){
|
||||||
$("#statusBar").html('<div class="alert alert-success" role="alert">' +
|
setSuccess('<strong>Successfully send ' + action + ' to ' + clientId +'</strong> - It can take up to 30s until the command is processed.');
|
||||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
|
||||||
'Successfully send ' + action + '<strong> - It can take up to 30s until the command is processed.</strong></div>');
|
|
||||||
|
|
||||||
window.setTimeout(function() {
|
|
||||||
$(".alert-success").fadeTo(500, 0).slideUp(500, function(){
|
|
||||||
$(".alert-success").alert('close');
|
|
||||||
});
|
|
||||||
}, 5000);
|
|
||||||
},
|
},
|
||||||
error: function (data) {
|
error: function (data) {
|
||||||
$("#statusBar").html('<div class="alert alert-danger" role="alert">' +
|
setError('<strong>Failed to send ' + action + ' to ' + clientId + '</strong> \nError: ' + JSON.stringify(data,undefined, 2));
|
||||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
|
||||||
'<strong>Failed to send ' + action + '</strong></div>');
|
|
||||||
|
|
||||||
window.setTimeout(function() {
|
|
||||||
$(".alert-danger").fadeTo(500, 0).slideUp(500, function(){
|
|
||||||
$(".alert-danger").alert('close');
|
|
||||||
});
|
|
||||||
}, 10000);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -464,19 +472,67 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function isOnline(lastStatus) {
|
function isOnline(lastStatus) {
|
||||||
var threshold = new Date().getTime() - 60 * 1000;
|
var threshold = new Date().getTime() - TRESHOLD_IN_MS;
|
||||||
if (lastStatus > threshold) {
|
if (lastStatus > threshold) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setSuccess(info) {
|
||||||
|
$("#statusBar").html('<div class="alert alert-success" role="alert">' +
|
||||||
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||||
|
info + '</div>');
|
||||||
|
|
||||||
|
window.setTimeout(function() {
|
||||||
|
$(".alert-success").fadeTo(500, 0).slideUp(500, function(){
|
||||||
|
$(".alert-success").alert('close');
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setError(error) {
|
||||||
|
$("#statusBar").html('<div class="alert alert-danger" role="alert">' +
|
||||||
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||||
|
error + '</div>');
|
||||||
|
|
||||||
|
window.setTimeout(function() {
|
||||||
|
$(".alert-danger").fadeTo(500, 0).slideUp(500, function(){
|
||||||
|
$(".alert-danger").alert('close');
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setClientConfig(clientId, clientConfig, isMultiConfigEdit) {
|
||||||
|
$.ajax({
|
||||||
|
url: "/admin/setClientConfig?clientId=" + clientId,
|
||||||
|
type: 'POST',
|
||||||
|
dataType: "text",
|
||||||
|
data: clientConfig,
|
||||||
|
success: function(data){
|
||||||
|
if (isMultiConfigEdit) {
|
||||||
|
setSuccess('<strong>Successfully updated configs for the selected clients</strong> - You need push the config to the clients to apply the config.');
|
||||||
|
} else {
|
||||||
|
setSuccess('<strong>Successfully updated config for: ' + clientId + '</strong> - You need push the config to the client to apply the config.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (data) {
|
||||||
|
if (isMultiConfigEdit) {
|
||||||
|
setError('<strong>Failed to update configs for the selected clients</strong> \nError:' + JSON.stringify(data,undefined, 2));
|
||||||
|
} else {
|
||||||
|
setError('<strong>Failed to update config for: ' + clientId + '</strong> \nError: ' + JSON.stringify(data,undefined, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<br/>
|
<br/>
|
||||||
<div style="width: 95%; margin:0 auto;">
|
<div style="width: 95%; margin:0 auto;">
|
||||||
|
<div id="updateNotificationBar"></div>
|
||||||
<div id="notificationBar"></div>
|
<div id="notificationBar"></div>
|
||||||
<div id="statusBar"></div>
|
<div id="statusBar"></div>
|
||||||
|
|
||||||
|
@ -530,7 +586,7 @@
|
||||||
|
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<div class="modal fade" id="editConfig" role="dialog">
|
<div class="modal fade" id="minerEditor" role="dialog">
|
||||||
<div class="modal-dialog modal-lg">
|
<div class="modal-dialog modal-lg">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
@ -540,13 +596,46 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-success" data-dismiss="modal">Save</button>
|
<button id="minerEditorSave" type="button" class="btn btn-success" data-dismiss="modal">Save</button>
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="multiMinerEditor" 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">Multi miner editor</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="alert alert-danger fade in">
|
||||||
|
<strong>Warning!</strong> - If you don't know what you are doing, [Cancel].
|
||||||
|
</div>
|
||||||
|
<h5 class="modal-title">
|
||||||
|
This will search for <strong>"x"</strong> and replace with <strong>"y"</strong> in all selected miners config<br/><br/>
|
||||||
|
<div class="alert alert-info fade in">
|
||||||
|
<strong>If you accidentally pressed [Replace], no worries just PULL again all miner configs. Don't PUSH it!</strong>
|
||||||
|
</div>
|
||||||
|
</h5>
|
||||||
|
<div class='form-group'>
|
||||||
|
<label for='search'>Search for:</label>
|
||||||
|
<textarea class='form-control' rows='2' cols="1" id='search'></textarea>
|
||||||
|
<label for='replacement'>Replace with:</label>
|
||||||
|
<textarea class='form-control' rows='2' id='replacement'></textarea>
|
||||||
|
</div>
|
||||||
|
</h5>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="multiMinerEditorReplace" type="button" class="btn btn-success" data-dismiss="modal">Replace</button>
|
||||||
|
<button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue