Merge pull request #22 from rucko24/feature/auto-refresh
Feature/auto-refresh Enhancements
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
.idea
|
||||||
+299
-44
@@ -39,6 +39,41 @@ require_once 'auth.inc';
|
|||||||
require_once 'guiconfig.inc';
|
require_once 'guiconfig.inc';
|
||||||
require_once 'bastille_manager-lib.inc';
|
require_once 'bastille_manager-lib.inc';
|
||||||
|
|
||||||
|
$img_path = [
|
||||||
|
'add' => 'images/add.png',
|
||||||
|
'mod' => 'images/edit.png',
|
||||||
|
'del' => 'images/delete.png',
|
||||||
|
'loc' => 'images/locked.png',
|
||||||
|
'unl' => 'images/unlocked.png',
|
||||||
|
'mai' => 'images/maintain.png',
|
||||||
|
'inf' => 'images/info.png',
|
||||||
|
'ena' => 'images/status_enabled.png',
|
||||||
|
'dis' => 'images/status_disabled.png',
|
||||||
|
'mup' => 'images/up.png',
|
||||||
|
'mdn' => 'images/down.png'
|
||||||
|
];
|
||||||
|
|
||||||
|
// --- START AUTO-REFRESH LOGIC ---
|
||||||
|
if (isset($_GET['action']) && $_GET['action'] === 'refresh_table') {
|
||||||
|
error_reporting(0);
|
||||||
|
ini_set('display_errors', 0);
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
// Fetch fresh data
|
||||||
|
$jls_list = [];
|
||||||
|
if (function_exists('get_jail_infos')) {
|
||||||
|
$jls_list = get_jail_infos();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return JSON
|
||||||
|
ob_clean();
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
header('Cache-Control: no-cache');
|
||||||
|
echo json_encode(['success' => true, 'jails' => $jls_list ?: []]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
// --- END AUTO-REFRESH LOGIC ---
|
||||||
|
|
||||||
function mwexec_parallel($commands) {
|
function mwexec_parallel($commands) {
|
||||||
$processes = [];
|
$processes = [];
|
||||||
$results = [];
|
$results = [];
|
||||||
@@ -53,7 +88,6 @@ function mwexec_parallel($commands) {
|
|||||||
$process = proc_open($command, $descriptors, $pipes);
|
$process = proc_open($command, $descriptors, $pipes);
|
||||||
|
|
||||||
if (is_resource($process)) {
|
if (is_resource($process)) {
|
||||||
|
|
||||||
stream_set_blocking($pipes[1], false);
|
stream_set_blocking($pipes[1], false);
|
||||||
stream_set_blocking($pipes[2], false);
|
stream_set_blocking($pipes[2], false);
|
||||||
|
|
||||||
@@ -71,7 +105,6 @@ function mwexec_parallel($commands) {
|
|||||||
foreach ($processes as $key => $proc) {
|
foreach ($processes as $key => $proc) {
|
||||||
$elapsed = time() - $start_time;
|
$elapsed = time() - $start_time;
|
||||||
if ($elapsed < $timeout) {
|
if ($elapsed < $timeout) {
|
||||||
|
|
||||||
$stdout = stream_get_contents($proc['pipes'][1]);
|
$stdout = stream_get_contents($proc['pipes'][1]);
|
||||||
$stderr = stream_get_contents($proc['pipes'][2]);
|
$stderr = stream_get_contents($proc['pipes'][2]);
|
||||||
|
|
||||||
@@ -102,8 +135,8 @@ function mwexec_parallel($commands) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mwexec_background($command) {
|
function mwexec_background($command) {
|
||||||
$command = $command . ' > /dev/null 2>&1 &';
|
$command = $command . ' > /dev/null 2>&1 &';
|
||||||
exec($command);
|
exec($command);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sphere_scriptname = basename(__FILE__);
|
$sphere_scriptname = basename(__FILE__);
|
||||||
@@ -127,19 +160,6 @@ $gt_selection_start_confirm = gtext('Do you really want to start selected jail(s
|
|||||||
$gt_selection_stop_confirm = gtext('Do you want to stop the selected jail(s)?');
|
$gt_selection_stop_confirm = gtext('Do you want to stop the selected jail(s)?');
|
||||||
$gt_selection_restart_confirm = gtext('Do you want to restart the selected jail(s)?');
|
$gt_selection_restart_confirm = gtext('Do you want to restart the selected jail(s)?');
|
||||||
$gt_selection_autoboot_confirm = gtext('Do you want to set auto-boot on selected jail(s)?');
|
$gt_selection_autoboot_confirm = gtext('Do you want to set auto-boot on selected jail(s)?');
|
||||||
$img_path = [
|
|
||||||
'add' => 'images/add.png',
|
|
||||||
'mod' => 'images/edit.png',
|
|
||||||
'del' => 'images/delete.png',
|
|
||||||
'loc' => 'images/locked.png',
|
|
||||||
'unl' => 'images/unlocked.png',
|
|
||||||
'mai' => 'images/maintain.png',
|
|
||||||
'inf' => 'images/info.png',
|
|
||||||
'ena' => 'images/status_enabled.png',
|
|
||||||
'dis' => 'images/status_disabled.png',
|
|
||||||
'mup' => 'images/up.png',
|
|
||||||
'mdn' => 'images/down.png'
|
|
||||||
];
|
|
||||||
|
|
||||||
$jls_list = get_jail_infos();
|
$jls_list = get_jail_infos();
|
||||||
$sphere_array = $jls_list;
|
$sphere_array = $jls_list;
|
||||||
@@ -184,19 +204,16 @@ if($_POST):
|
|||||||
if(isset($_POST['start_selected_jail']) && $_POST['start_selected_jail']):
|
if(isset($_POST['start_selected_jail']) && $_POST['start_selected_jail']):
|
||||||
$checkbox_member_array = isset($_POST[$checkbox_member_name]) ? $_POST[$checkbox_member_name] : [];
|
$checkbox_member_array = isset($_POST[$checkbox_member_name]) ? $_POST[$checkbox_member_name] : [];
|
||||||
$commands = [];
|
$commands = [];
|
||||||
$jail_names = [];
|
|
||||||
|
|
||||||
foreach($checkbox_member_array as $checkbox_member_record):
|
foreach($checkbox_member_array as $checkbox_member_record):
|
||||||
if(false !== ($index = array_search_ex($checkbox_member_record, $sphere_array, 'jailname'))):
|
if(false !== ($index = array_search_ex($checkbox_member_record, $sphere_array, 'jailname'))):
|
||||||
if(!isset($sphere_array[$index]['protected'])):
|
if(!isset($sphere_array[$index]['protected'])):
|
||||||
$commands[] = "/usr/local/bin/bastille start {$checkbox_member_record}";
|
$commands[] = "/usr/local/bin/bastille start {$checkbox_member_record}";
|
||||||
$jail_names[] = $checkbox_member_record;
|
|
||||||
endif;
|
endif;
|
||||||
endif;
|
endif;
|
||||||
endforeach;
|
endforeach;
|
||||||
|
|
||||||
if (!empty($commands)):
|
if (!empty($commands)):
|
||||||
|
|
||||||
$results = mwexec_parallel($commands);
|
$results = mwexec_parallel($commands);
|
||||||
|
|
||||||
$success_count = 0;
|
$success_count = 0;
|
||||||
@@ -345,36 +362,116 @@ if($_POST):
|
|||||||
endif;
|
endif;
|
||||||
endif;
|
endif;
|
||||||
|
|
||||||
$pgtitle = [gtext("Extensions"), gtext('Bastille')];
|
$pgtitle = [gtext("Extensions"), gtext('Bastille'), gtext('Manager')];
|
||||||
include 'fbegin.inc';
|
include 'fbegin.inc';
|
||||||
?>
|
?>
|
||||||
|
<style>
|
||||||
|
/* Refresh button style */
|
||||||
|
#refresh-now {
|
||||||
|
appearance: none;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--txc-input-rw);
|
||||||
|
background-color: var(--bgc-area-data);
|
||||||
|
border: 1px solid var(--boc-button);
|
||||||
|
border-radius: var(--bor);
|
||||||
|
padding: 0.125rem 0.375rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#refresh-now:hover {
|
||||||
|
filter: brightness(150%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- SIMPLE RESIZE STYLES --- */
|
||||||
|
table.area_data_selection {
|
||||||
|
table-layout: fixed;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.area_data_selection th {
|
||||||
|
position: relative;
|
||||||
|
padding: 5px 8px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The visible handle */
|
||||||
|
.resizer {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 6px;
|
||||||
|
height: 100%;
|
||||||
|
cursor: col-resize;
|
||||||
|
z-index: 100;
|
||||||
|
user-select: none;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resizer:hover, .resizing {
|
||||||
|
background-color: #007bff; /* Azul */
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
//<![CDATA[
|
//<![CDATA[
|
||||||
$(window).on("load", function() {
|
$(window).on("load", function() {
|
||||||
// Init action buttons
|
// Init action buttons
|
||||||
$("#start_selected_jail").click(function () {
|
$("#start_selected_jail").click(function () {
|
||||||
|
stopAutoRefresh(); // Pause for safety
|
||||||
return confirm('<?=$gt_selection_start_confirm;?>');
|
return confirm('<?=$gt_selection_start_confirm;?>');
|
||||||
});
|
});
|
||||||
$("#stop_selected_jail").click(function () {
|
$("#stop_selected_jail").click(function () {
|
||||||
|
stopAutoRefresh();
|
||||||
return confirm('<?=$gt_selection_stop_confirm;?>');
|
return confirm('<?=$gt_selection_stop_confirm;?>');
|
||||||
});
|
});
|
||||||
$("#restart_selected_jail").click(function () {
|
$("#restart_selected_jail").click(function () {
|
||||||
|
stopAutoRefresh();
|
||||||
return confirm('<?=$gt_selection_restart_confirm;?>');
|
return confirm('<?=$gt_selection_restart_confirm;?>');
|
||||||
});
|
});
|
||||||
$("#autoboot_selected_jail").click(function () {
|
$("#autoboot_selected_jail").click(function () {
|
||||||
return confirm('<?=$gt_selection_restart_confirm;?>');
|
stopAutoRefresh();
|
||||||
|
return confirm('<?=$gt_selection_autoboot_confirm;?>');
|
||||||
});
|
});
|
||||||
// Disable action buttons.
|
// Disable action buttons.
|
||||||
disableactionbuttons(true);
|
disableactionbuttons(true);
|
||||||
|
|
||||||
// Init member checkboxes
|
|
||||||
$("input[name='<?=$checkbox_member_name;?>[]']").click(function() {
|
|
||||||
controlactionbuttons(this, '<?=$checkbox_member_name;?>[]');
|
|
||||||
});
|
|
||||||
// Init spinner onsubmit()
|
|
||||||
$("#iform").submit(function() { spinner(); });
|
$("#iform").submit(function() { spinner(); });
|
||||||
$(".spin").click(function() { spinner(); });
|
$(".spin").click(function() { spinner(); });
|
||||||
|
|
||||||
|
// Attempt to load the previously saved interval
|
||||||
|
var savedInterval = localStorage.getItem('bastille_refresh_interval');
|
||||||
|
if (savedInterval !== null) {
|
||||||
|
$("#refresh-interval").val(savedInterval);
|
||||||
|
autoRefresh.interval = parseInt(savedInterval);
|
||||||
|
}
|
||||||
|
// --- REFRESH INIT ---
|
||||||
|
// Only start if the button is visible (enabled in settings)
|
||||||
|
if (localStorage.getItem('bastille_show_refresh_button') === 'true') {
|
||||||
|
$("#refresh-controls").show();
|
||||||
|
startAutoRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#refresh-now").click(function() {
|
||||||
|
updateJailTable();
|
||||||
|
});
|
||||||
|
|
||||||
|
// save interval value in local storage
|
||||||
|
$("#refresh-interval").change(function() {
|
||||||
|
var val = parseInt($(this).val());
|
||||||
|
localStorage.setItem('bastille_refresh_interval', val);
|
||||||
|
stopAutoRefresh();
|
||||||
|
if (val > 0) {
|
||||||
|
autoRefresh.interval = val;
|
||||||
|
startAutoRefresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
initSimpleResize();
|
||||||
});
|
});
|
||||||
|
|
||||||
function disableactionbuttons(ab_disable) {
|
function disableactionbuttons(ab_disable) {
|
||||||
$("#start_selected_jail").prop("disabled", ab_disable);
|
$("#start_selected_jail").prop("disabled", ab_disable);
|
||||||
$("#stop_selected_jail").prop("disabled", ab_disable);
|
$("#stop_selected_jail").prop("disabled", ab_disable);
|
||||||
@@ -397,6 +494,149 @@ function controlactionbuttons(ego, triggerbyname) {
|
|||||||
}
|
}
|
||||||
disableactionbuttons(ab_disable);
|
disableactionbuttons(ab_disable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- AUTO-REFRESH JS ---
|
||||||
|
var autoRefresh = {
|
||||||
|
enabled: true,
|
||||||
|
interval: 30000,
|
||||||
|
timerId: null,
|
||||||
|
lastUpdate: Date.now(),
|
||||||
|
isUpdating: false,
|
||||||
|
selectedJails: []
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateJailTable() {
|
||||||
|
if (autoRefresh.isUpdating) return;
|
||||||
|
autoRefresh.isUpdating = true;
|
||||||
|
$("#refresh-status").text('Updating...');
|
||||||
|
|
||||||
|
// Backup of checked checkboxes for persistence
|
||||||
|
autoRefresh.selectedJails = [];
|
||||||
|
$("input[name='<?=$checkbox_member_name;?>[]']:checked").each(function() {
|
||||||
|
autoRefresh.selectedJails.push($(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: 'bastille_manager_gui.php?action=refresh_table',
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
if (data.success) {
|
||||||
|
var tbody = $(".area_data_selection tbody");
|
||||||
|
tbody.empty();
|
||||||
|
data.jails.forEach(function(jail) {
|
||||||
|
var row = $('<tr>');
|
||||||
|
var checkCell = $('<td class="lcelc">');
|
||||||
|
var cb = $('<input type="checkbox">')
|
||||||
|
.attr('name', '<?=$checkbox_member_name;?>[]')
|
||||||
|
.attr('value', jail.jailname)
|
||||||
|
.attr('id', jail.jailname)
|
||||||
|
.prop('checked', autoRefresh.selectedJails.includes(jail.jailname))
|
||||||
|
.click(function() { controlactionbuttons(this, '<?=$checkbox_member_name;?>[]'); });
|
||||||
|
checkCell.append(cb);
|
||||||
|
row.append(checkCell);
|
||||||
|
|
||||||
|
// 2. Data Columns
|
||||||
|
row.append($('<td class="lcell">').text(jail.id || '-'));
|
||||||
|
row.append($('<td class="lcell">').text(jail.name || '-'));
|
||||||
|
row.append($('<td class="lcell">').text(jail.boot || '-'));
|
||||||
|
row.append($('<td class="lcell">').text(jail.prio || '-'));
|
||||||
|
row.append($('<td class="lcell">').text(jail.state || '-'));
|
||||||
|
row.append($('<td class="lcell">').text(jail.type || '-'));
|
||||||
|
row.append($('<td class="lcell">').text(jail.ip || '-'));
|
||||||
|
row.append($('<td class="lcell">').text(jail.ports || '-'));
|
||||||
|
row.append($('<td class="lcell">').text(jail.rel || '-'));
|
||||||
|
row.append($('<td class="lcell">').text(jail.tags || '-'));
|
||||||
|
|
||||||
|
var statImg = (jail.state === "Up") ? '<?=$img_path['ena'];?>' : '<?=$img_path['dis'];?>';
|
||||||
|
row.append($('<td class="lcell">').append($('<img>').attr('src', statImg)));
|
||||||
|
row.append($('<td class="lcell">').append($('<img>').attr('src', jail.logo)));
|
||||||
|
|
||||||
|
var tools = $('<td class="lcebld">').html('<table class="area_data_selection_toolbox"><tbody><tr>' +
|
||||||
|
'<td><a href="<?=$sphere_scriptname_child;?>?jailname=' + encodeURIComponent(jail.jailname) + '"><img src="<?=$img_path['mai'];?>" class="spin oneemhigh"></a></td>' +
|
||||||
|
'<td><a href="bastille_manager_jconf.php?jailname=' + encodeURIComponent(jail.jailname) + '"><img src="<?=$g_img['mod'];?>"></a></td>' +
|
||||||
|
'<td><a href="bastille_manager_info.php?uuid=' + encodeURIComponent(jail.jailname) + '"><img src="<?=$g_img['inf'];?>"></a></td>' +
|
||||||
|
'</tr></tbody></table>');
|
||||||
|
row.append(tools);
|
||||||
|
|
||||||
|
tbody.append(row);
|
||||||
|
});
|
||||||
|
autoRefresh.lastUpdate = Date.now();
|
||||||
|
$("#refresh-status").text('Last update: just now');
|
||||||
|
controlactionbuttons(null, '<?=$checkbox_member_name;?>[]');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
complete: function() { autoRefresh.isUpdating = false; }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startAutoRefresh() {
|
||||||
|
if (autoRefresh.interval > 0) {
|
||||||
|
autoRefresh.timerId = setInterval(updateJailTable, autoRefresh.interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopAutoRefresh() {
|
||||||
|
if (autoRefresh.timerId) clearInterval(autoRefresh.timerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- STABLE REDIMENSIONING FUNCTION (without %) ---
|
||||||
|
function initSimpleResize() {
|
||||||
|
var $table = $("table.area_data_selection");
|
||||||
|
var $cols = $table.find('colgroup col');
|
||||||
|
var $headers = $table.find('thead th');
|
||||||
|
|
||||||
|
$headers.each(function(i) {
|
||||||
|
if (i >= $headers.length - 1) return; // Ignore the last column
|
||||||
|
var $resizer = $('<div class="resizer"></div>');
|
||||||
|
$(this).append($resizer);
|
||||||
|
});
|
||||||
|
|
||||||
|
var isResizing = false;
|
||||||
|
var startX = 0;
|
||||||
|
var $currentCol = null;
|
||||||
|
var startWidth = 0;
|
||||||
|
|
||||||
|
$table.on('mousedown', '.resizer', function(e) {
|
||||||
|
e.preventDefault(); e.stopPropagation();
|
||||||
|
stopAutoRefresh();
|
||||||
|
|
||||||
|
// Convert all columns to fixed pixels when starting to drag
|
||||||
|
$cols.each(function() {
|
||||||
|
var w = $(this).width();
|
||||||
|
$(this).css('width', w + 'px');
|
||||||
|
});
|
||||||
|
|
||||||
|
var idx = $(this).parent().index();
|
||||||
|
$currentCol = $cols.eq(idx);
|
||||||
|
|
||||||
|
isResizing = true;
|
||||||
|
startX = e.pageX;
|
||||||
|
startWidth = $currentCol.width();
|
||||||
|
$(this).addClass('resizing');
|
||||||
|
|
||||||
|
$(document).on('mousemove.rsz', function(e) {
|
||||||
|
if (!isResizing) return;
|
||||||
|
var diff = e.pageX - startX;
|
||||||
|
var newW = startWidth + diff;
|
||||||
|
|
||||||
|
if (newW > 30) {
|
||||||
|
$currentCol.css('width', newW + 'px');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('mouseup.rsz', function() {
|
||||||
|
if (!isResizing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isResizing = false;
|
||||||
|
$('.resizer').removeClass('resizing');
|
||||||
|
$(document).off('mousemove.rsz mouseup.rsz');
|
||||||
|
setTimeout(function() {
|
||||||
|
startAutoRefresh();
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
//]]>
|
//]]>
|
||||||
</script>
|
</script>
|
||||||
<?php
|
<?php
|
||||||
@@ -438,24 +678,37 @@ $document->render();
|
|||||||
<tbody>
|
<tbody>
|
||||||
<?php
|
<?php
|
||||||
?>
|
?>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<table class="area_data_selection">
|
|
||||||
|
<div id="refresh-controls" style="text-align: right; display: none;">
|
||||||
|
<span id="refresh-status" style="font-style: italic; margin-right: 15px; color: #666;">Last update: just now</span>
|
||||||
|
<button type="button" id="refresh-now" class="formbtn">Refresh</button>
|
||||||
|
<select id="refresh-interval" class="formfld">
|
||||||
|
<option value="5000">5s</option>
|
||||||
|
<option value="10000">10s</option>
|
||||||
|
<option value="30000" selected>30s</option>
|
||||||
|
<option value="60000">60s</option>
|
||||||
|
<option value="0">Manual</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="area_data_selection" style="width: 100%; table-layout: fixed; border-collapse: collapse;">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col style="width:2%">
|
<col style="width:2%">
|
||||||
<col style="width:2%">
|
<col style="width:3%">
|
||||||
|
<col style="width:12%">
|
||||||
|
<col style="width:4%">
|
||||||
|
<col style="width:4%">
|
||||||
|
<col style="width:4%">
|
||||||
|
<col style="width:4%">
|
||||||
|
<col style="width:12%">
|
||||||
|
<col style="width:12%">
|
||||||
|
<col style="width:7%">
|
||||||
|
<col style="width:12%">
|
||||||
|
<col style="width:4%">
|
||||||
|
<col style="width:4%">
|
||||||
<col style="width:10%">
|
<col style="width:10%">
|
||||||
<col style="width:3%">
|
|
||||||
<col style="width:3%">
|
|
||||||
<col style="width:3%">
|
|
||||||
<col style="width:3%">
|
|
||||||
<col style="width:10%">
|
|
||||||
<col style="width:10%">
|
|
||||||
<col style="width:5%">
|
|
||||||
<col style="width:10%">
|
|
||||||
<col style="width:3%">
|
|
||||||
<col style="width:3%">
|
|
||||||
<col style="width:5%">
|
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<thead>
|
<thead>
|
||||||
<?php
|
<?php
|
||||||
@@ -533,6 +786,7 @@ $document->render();
|
|||||||
endif;
|
endif;
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="bastille_manager_jconf.php?jailname=<?=urlencode($sphere_record['jailname']);?>"><img src="<?=$g_img['mod'];?>" title="<?=$gt_record_conf?>" alt="<?=$gt_record_conf?>"/></a>
|
<a href="bastille_manager_jconf.php?jailname=<?=urlencode($sphere_record['jailname']);?>"><img src="<?=$g_img['mod'];?>" title="<?=$gt_record_conf?>" alt="<?=$gt_record_conf?>"/></a>
|
||||||
</td>
|
</td>
|
||||||
@@ -562,8 +816,9 @@ $document->render();
|
|||||||
<input name="autoboot_selected_jail" id="autoboot_selected_jail" type="submit" class="formbtn" value="<?=$gt_selection_autoboot;?>"/>
|
<input name="autoboot_selected_jail" id="autoboot_selected_jail" type="submit" class="formbtn" value="<?=$gt_selection_autoboot;?>"/>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
include 'formend.inc';
|
include 'formend.inc';
|
||||||
?>
|
?>
|
||||||
</td></tr></tbody></table></form>
|
</td></tr></tbody></table></form>
|
||||||
<?php
|
<?php
|
||||||
include 'fend.inc';
|
include 'fend.inc';
|
||||||
|
?>
|
||||||
@@ -306,6 +306,23 @@ $(document).ready(function(){
|
|||||||
$('#getinfo_bastille').html(data.bastille);
|
$('#getinfo_bastille').html(data.bastille);
|
||||||
$('#getinfo_ext').html(data.ext);
|
$('#getinfo_ext').html(data.ext);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- LOGICA DEL CHECKBOX REFRESH (LocalStorage) ---
|
||||||
|
var $chk = $("#show_refresh_button");
|
||||||
|
|
||||||
|
// 1. Leer estado inicial desde LocalStorage
|
||||||
|
var savedState = localStorage.getItem('bastille_show_refresh_button');
|
||||||
|
if (savedState === 'true') {
|
||||||
|
$chk.prop('checked', true);
|
||||||
|
} else {
|
||||||
|
$chk.prop('checked', false); // Por defecto deshabilitado
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Guardar cambios al hacer click
|
||||||
|
$chk.change(function() {
|
||||||
|
var isChecked = $(this).is(':checked');
|
||||||
|
localStorage.setItem('bastille_show_refresh_button', isChecked);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
//]]>
|
//]]>
|
||||||
</script>
|
</script>
|
||||||
@@ -373,6 +390,9 @@ $(document).ready(function(){
|
|||||||
<?php html_titleline(gtext("Uninstall"));?>
|
<?php html_titleline(gtext("Uninstall"));?>
|
||||||
<?php html_checkbox2('delete_confirm',gtext('Uninstall confirm'),'' ? true : false,gtext('Check to confirm extension uninstall. Note: Jail related content will be preserved by default.'),'',false);?>
|
<?php html_checkbox2('delete_confirm',gtext('Uninstall confirm'),'' ? true : false,gtext('Check to confirm extension uninstall. Note: Jail related content will be preserved by default.'),'',false);?>
|
||||||
<?php html_separator();?>
|
<?php html_separator();?>
|
||||||
|
<?php html_titleline(gtext("Refresh"));?>
|
||||||
|
<?php html_checkbox2('show_refresh_button',gtext('Show refresh button'),'' ? true : false,gtext('This will display a refresh button in the containers tab.'),'',false);?>
|
||||||
|
<?php html_separator();?>
|
||||||
</table>
|
</table>
|
||||||
<div id="submit1">
|
<div id="submit1">
|
||||||
<input name="uninstall" type="submit" class="formbtn" title="<?=gtext("Uninstall Extension");?>" value="<?=gtext("Uninstall");?>" onclick="return confirm('<?=gtext("Bastille Extension and packages will be completely removed, Bastille containers and child directories will not be touched, really to proceed?");?>')" />
|
<input name="uninstall" type="submit" class="formbtn" title="<?=gtext("Uninstall Extension");?>" value="<?=gtext("Uninstall");?>" onclick="return confirm('<?=gtext("Bastille Extension and packages will be completely removed, Bastille containers and child directories will not be touched, really to proceed?");?>')" />
|
||||||
@@ -384,4 +404,4 @@ $(document).ready(function(){
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
<!--enable_change(false);-->
|
<!--enable_change(false);-->
|
||||||
</script>
|
</script>
|
||||||
<?php include("fend.inc");?>
|
<?php include("fend.inc");?>
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/* bastille_manager.css
|
||||||
|
Estilo NATIVO (Minimalista)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#refresh-controls {
|
||||||
|
/* Fondo transparente y sin bordes para integrarse con el tema */
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
|
||||||
|
/* Alineación a la derecha */
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
|
||||||
|
/* Fuente estándar del sistema */
|
||||||
|
font-size: 13px;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#refresh-status {
|
||||||
|
/* Color de texto por defecto del tema (negro/gris) */
|
||||||
|
color: inherit;
|
||||||
|
margin-right: 5px;
|
||||||
|
|
||||||
|
/* Coloca el texto a la izquierda de los botones */
|
||||||
|
order: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pequeño spinner azul discreto solo cuando actualiza */
|
||||||
|
#refresh-status.updating .refresh-spinner {
|
||||||
|
display: inline-block;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
border-top-color: #007bff;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animación del spinner */
|
||||||
|
@keyframes spin {
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Asegurar que los iconos de la tabla estén centrados verticalmente */
|
||||||
|
.area_data_selection tbody td img {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Centrado perfecto para los checkboxes */
|
||||||
|
.lcelc {
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user