mirror of
https://gitlab.com/ArkHost/WHMCS-ArkhostVPSAG.git
synced 2026-07-23 23:36:06 +02:00
vnc embedded option
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* WHMCS Server Module - VPSAG
|
||||
*
|
||||
* @package WHMCS
|
||||
* @version 1.4
|
||||
* @version 1.5
|
||||
* @copyright Copyright (c) ArkHost 2025
|
||||
* @author ArkHost <support@arkhost.com>
|
||||
* @link https://arkhost.com
|
||||
@@ -383,13 +383,29 @@ function ArkhostVPSAG_MetaData() {
|
||||
'order' => 30,
|
||||
'icon' => 'fa-sync'
|
||||
]);
|
||||
$actionsPanel->addChild('VPSVNC', [
|
||||
'label' => $_LANG['VNC'],
|
||||
'uri' => 'clientarea.php?action=productdetails&id=' . $serviceId . '&modop=custom&a=VNC',
|
||||
'order' => 40,
|
||||
'icon' => 'fa-desktop',
|
||||
'attributes' => ['target' => '_blank']
|
||||
]);
|
||||
|
||||
// Check VNC mode from product config
|
||||
$product = Capsule::table('tblproducts')->where('id', $service->packageid)->first();
|
||||
$vncMode = isset($product->configoption3) && $product->configoption3 !== '' ? $product->configoption3 : 'newtab';
|
||||
|
||||
if ($vncMode === 'embedded') {
|
||||
// For embedded mode, link to the page with hash to trigger VNC tab
|
||||
$actionsPanel->addChild('VPSVNC', [
|
||||
'label' => $_LANG['VNC'],
|
||||
'uri' => 'clientarea.php?action=productdetails&id=' . $serviceId . '#vnc',
|
||||
'order' => 40,
|
||||
'icon' => 'fa-desktop'
|
||||
]);
|
||||
} else {
|
||||
// For new tab mode, open VNC in new window
|
||||
$actionsPanel->addChild('VPSVNC', [
|
||||
'label' => $_LANG['VNC'],
|
||||
'uri' => 'clientarea.php?action=productdetails&id=' . $serviceId . '&modop=custom&a=VNC',
|
||||
'order' => 40,
|
||||
'icon' => 'fa-desktop',
|
||||
'attributes' => ['target' => '_blank']
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -422,6 +438,16 @@ function ArkhostVPSAG_ConfigOptions() {
|
||||
'Type' => 'dropdown',
|
||||
'Options' => array(),
|
||||
),
|
||||
'vnc_mode' => array(
|
||||
'FriendlyName' => 'VNC Display Mode',
|
||||
'Description' => 'How to display the VNC console to clients.',
|
||||
'Type' => 'dropdown',
|
||||
'Options' => array(
|
||||
'newtab' => 'New Tab',
|
||||
'embedded' => 'Embedded in Page',
|
||||
),
|
||||
'Default' => 'newtab',
|
||||
),
|
||||
// Extra resource options removed - now handled via plan selection
|
||||
// Plans have fixed resources defined within them in the new API
|
||||
);
|
||||
@@ -718,7 +744,7 @@ function ArkhostVPSAG_AdminLink(array $params) {
|
||||
function ArkhostVPSAG_ClientAreaAPI(array $params) {
|
||||
try {
|
||||
$action = App::getFromRequest('api');
|
||||
$actions = array('Server Info', 'Graphs', 'Reinstall', 'Reboot', 'Stop', 'Start', 'IPv4 Addresses', 'Hostname rDNS', 'Create backup', 'Delete backup', 'List backups', 'Restore backup', 'Get Firewall rules', 'Add Firewall rules', 'Delete Firewall rule', 'Commit Firewall rules', 'ISO Images', 'Load ISO', 'Eject ISO', 'Reset root');
|
||||
$actions = array('Server Info', 'Graphs', 'Reinstall', 'Reboot', 'Stop', 'Start', 'IPv4 Addresses', 'Hostname rDNS', 'Create backup', 'Delete backup', 'List backups', 'Restore backup', 'Get Firewall rules', 'Add Firewall rules', 'Delete Firewall rule', 'Commit Firewall rules', 'ISO Images', 'Load ISO', 'Eject ISO', 'Reset root', 'VNC Console');
|
||||
$results = array('result' => 'success');
|
||||
|
||||
if (in_array($action, $actions)) {
|
||||
@@ -1000,6 +1026,11 @@ function ArkhostVPSAG_ClientArea(array $params) {
|
||||
$serverInfo['bandwidth_used'] = isset($serverInfo['bandwidth_used']) ? $serverInfo['bandwidth_used'] : 0;
|
||||
$serverInfo['bandwidth'] = isset($serverInfo['bandwidth']) ? $serverInfo['bandwidth'] : 1;
|
||||
|
||||
// Get VNC mode setting (configoption3)
|
||||
$vncMode = isset($params['configoption3']) && $params['configoption3'] !== ''
|
||||
? $params['configoption3']
|
||||
: 'newtab';
|
||||
|
||||
return array(
|
||||
'templatefile' => 'template/clientarea_direct',
|
||||
'templateVariables' => array(
|
||||
@@ -1008,6 +1039,7 @@ function ArkhostVPSAG_ClientArea(array $params) {
|
||||
'operatingSystems' => $operatingSystems,
|
||||
'token' => generate_token('plain'),
|
||||
'_LANG' => ArkhostVPSAG_Translation(),
|
||||
'vncMode' => $vncMode,
|
||||
)
|
||||
);
|
||||
} catch (Exception $err) {
|
||||
|
||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Gebruikt';
|
||||
$_ADDONLANG['Start'] = 'Start';
|
||||
$_ADDONLANG['Stop'] = 'Stop';
|
||||
$_ADDONLANG['Restart'] = 'Herstarten';
|
||||
$_ADDONLANG['VNC'] = 'VNC-console';
|
||||
$_ADDONLANG['VNC'] = 'VNC';
|
||||
$_ADDONLANG['General']['Note'] = 'Opmerking';
|
||||
$_ADDONLANG['LoadingFirewallRules'] = 'Firewall-regels laden...';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Used';
|
||||
$_ADDONLANG['Start'] = 'Start';
|
||||
$_ADDONLANG['Stop'] = 'Stop';
|
||||
$_ADDONLANG['Restart'] = 'Restart';
|
||||
$_ADDONLANG['VNC'] = 'VNC Console';
|
||||
$_ADDONLANG['VNC'] = 'VNC';
|
||||
$_ADDONLANG['General']['Note'] = 'Note';
|
||||
$_ADDONLANG['LoadingFirewallRules'] = 'Loading firewall rules...';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Utilisé';
|
||||
$_ADDONLANG['Start'] = 'Démarrer';
|
||||
$_ADDONLANG['Stop'] = 'Arrêter';
|
||||
$_ADDONLANG['Restart'] = 'Redémarrer';
|
||||
$_ADDONLANG['VNC'] = 'Console VNC';
|
||||
$_ADDONLANG['VNC'] = 'VNC';
|
||||
$_ADDONLANG['General']['Note'] = 'Note';
|
||||
$_ADDONLANG['LoadingFirewallRules'] = 'Chargement des règles de pare-feu...';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Verwendet';
|
||||
$_ADDONLANG['Start'] = 'Starten';
|
||||
$_ADDONLANG['Stop'] = 'Stoppen';
|
||||
$_ADDONLANG['Restart'] = 'Neustart';
|
||||
$_ADDONLANG['VNC'] = 'VNC-Konsole';
|
||||
$_ADDONLANG['VNC'] = 'VNC';
|
||||
$_ADDONLANG['General']['Note'] = 'Notiz';
|
||||
$_ADDONLANG['LoadingFirewallRules'] = 'Firewall-Regeln werden geladen...';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Utilizzato';
|
||||
$_ADDONLANG['Start'] = 'Avvia';
|
||||
$_ADDONLANG['Stop'] = 'Ferma';
|
||||
$_ADDONLANG['Restart'] = 'Riavvia';
|
||||
$_ADDONLANG['VNC'] = 'Console VNC';
|
||||
$_ADDONLANG['VNC'] = 'VNC';
|
||||
$_ADDONLANG['General']['Note'] = 'Nota';
|
||||
$_ADDONLANG['LoadingFirewallRules'] = 'Caricamento regole firewall...';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Utilizado';
|
||||
$_ADDONLANG['Start'] = 'Iniciar';
|
||||
$_ADDONLANG['Stop'] = 'Parar';
|
||||
$_ADDONLANG['Restart'] = 'Reiniciar';
|
||||
$_ADDONLANG['VNC'] = 'Consola VNC';
|
||||
$_ADDONLANG['VNC'] = 'VNC';
|
||||
$_ADDONLANG['General']['Note'] = 'Nota';
|
||||
$_ADDONLANG['LoadingFirewallRules'] = 'Carregando regras de firewall...';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Использовано';
|
||||
$_ADDONLANG['Start'] = 'Запуск';
|
||||
$_ADDONLANG['Stop'] = 'Остановка';
|
||||
$_ADDONLANG['Restart'] = 'Перезапуск';
|
||||
$_ADDONLANG['VNC'] = 'Консоль VNC';
|
||||
$_ADDONLANG['VNC'] = 'VNC';
|
||||
$_ADDONLANG['General']['Note'] = 'Примечание';
|
||||
$_ADDONLANG['LoadingFirewallRules'] = 'Загрузка правил файрвола...';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Usado';
|
||||
$_ADDONLANG['Start'] = 'Iniciar';
|
||||
$_ADDONLANG['Stop'] = 'Detener';
|
||||
$_ADDONLANG['Restart'] = 'Reiniciar';
|
||||
$_ADDONLANG['VNC'] = 'Consola VNC';
|
||||
$_ADDONLANG['VNC'] = 'VNC';
|
||||
$_ADDONLANG['General']['Note'] = 'Nota';
|
||||
$_ADDONLANG['LoadingFirewallRules'] = 'Cargando reglas de firewall...';
|
||||
|
||||
|
||||
@@ -644,7 +644,7 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
var productURL = '{$WEB_ROOT}/clientarea.php?action=productdetails&id={$serviceid}';
|
||||
var serverInfoInitial = JSON.parse('{$serverInfo|@json_encode}');
|
||||
var serverInfoInitial = JSON.parse('{$serverInfo|json_encode}');
|
||||
var lang = {
|
||||
moduleactionfailed: 'Action failed!',
|
||||
moduleactionsuccess: 'Action completed successfully',
|
||||
@@ -1547,6 +1547,13 @@
|
||||
<i class="fa fa-cog"></i> {$_LANG['Navbar']['Settings']}
|
||||
</a>
|
||||
</li>
|
||||
{if $vncMode == 'embedded'}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="vnc-tab" data-toggle="tab" href="#vnc" role="tab" aria-controls="vnc" aria-selected="false" onclick="loadVNCConsole()">
|
||||
<i class="fa fa-desktop"></i> {$_LANG['VNC']}
|
||||
</a>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
<div class="tab-content" id="pills-tabContent">
|
||||
<div class="tab-pane fade show active" id="overview" role="tabpanel" aria-labelledby="overview-tab">
|
||||
@@ -1732,11 +1739,17 @@
|
||||
onclick="return confirmRestart();">
|
||||
<i class="fa fa-sync mr-1"></i> {$_LANG['Restart']}
|
||||
</button>
|
||||
{if $vncMode == 'embedded'}
|
||||
<button class="btn btn-info" onclick="$('#vnc-tab').tab('show'); loadVNCConsole();">
|
||||
<i class="fa fa-desktop mr-1"></i> {$_LANG['VNC']}
|
||||
</button>
|
||||
{else}
|
||||
<a href="{$WEB_ROOT}/clientarea.php?action=productdetails&id={$serviceid}&modop=custom&a=VNC"
|
||||
target="_blank"
|
||||
class="btn btn-info">
|
||||
<i class="fa fa-desktop mr-1"></i> {$_LANG['VNC']}
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2114,6 +2127,32 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{if $vncMode == 'embedded'}
|
||||
<!-- VNC Tab -->
|
||||
<div class="tab-pane fade" id="vnc" role="tabpanel" aria-labelledby="vnc-tab">
|
||||
<div class="card" id="vncCard">
|
||||
<div class="card-header bg-info text-white d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0"><i class="fa fa-desktop mr-2"></i>{$_LANG['VNC']}</h5>
|
||||
<div>
|
||||
<button class="btn btn-sm btn-light" onclick="openVNCNewTab()" title="Open in New Tab">
|
||||
<i class="fa fa-external-link-alt"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-light ml-1" onclick="toggleVNCFullscreen()" title="Fullscreen" id="vncFullscreenBtn">
|
||||
<i class="fa fa-expand"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0" id="vncContainer">
|
||||
<div id="vncLoading" class="text-center p-5">
|
||||
<i class="fa fa-spinner fa-spin fa-3x"></i>
|
||||
<p class="mt-3">Loading VNC Console...</p>
|
||||
</div>
|
||||
<iframe id="vncIframe" src="" style="width: 100%; height: 600px; border: none; display: none;"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2161,5 +2200,103 @@ jQuery(document).ready(function($) {
|
||||
}
|
||||
});
|
||||
|
||||
// Handle hash navigation for VNC tab (when coming from sidebar)
|
||||
function handleVNCHash() {
|
||||
if (window.location.hash === '#vnc') {
|
||||
$('#vnc-tab').tab('show');
|
||||
loadVNCConsole();
|
||||
}
|
||||
}
|
||||
|
||||
// Check on page load
|
||||
if (window.location.hash === '#vnc') {
|
||||
setTimeout(handleVNCHash, 100);
|
||||
}
|
||||
|
||||
// Listen for hash changes (when clicking sidebar link while already on page)
|
||||
$(window).on('hashchange', handleVNCHash);
|
||||
|
||||
// Intercept sidebar VNC link clicks
|
||||
$('a[href$="#vnc"]').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$('#vnc-tab').tab('show');
|
||||
loadVNCConsole();
|
||||
history.pushState(null, null, '#vnc');
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
// VNC Tab functions
|
||||
var vncLoaded = false;
|
||||
function loadVNCConsole() {
|
||||
if (vncLoaded) return;
|
||||
|
||||
var iframe = document.getElementById('vncIframe');
|
||||
var loading = document.getElementById('vncLoading');
|
||||
var container = document.getElementById('vncContainer');
|
||||
|
||||
if (!iframe || !container) return;
|
||||
|
||||
// Fetch VNC URL via API and load directly
|
||||
jQuery.get(productURL + '&modop=custom&a=ClientAreaAPI&api=VNC Console&token={$token}', function(data) {
|
||||
console.log('VNC API response:', data);
|
||||
if (data && data.vnc_url) {
|
||||
iframe.src = data.vnc_url;
|
||||
iframe.style.display = 'block';
|
||||
if (loading) loading.style.display = 'none';
|
||||
vncLoaded = true;
|
||||
} else if (data && data.message) {
|
||||
container.innerHTML = '<div class="alert alert-danger m-3">' + data.message + '</div>';
|
||||
} else {
|
||||
container.innerHTML = '<div class="alert alert-warning m-3">VNC URL not available. Response: ' + JSON.stringify(data) + '</div>';
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
console.log('VNC API error:', status, error);
|
||||
container.innerHTML = '<div class="alert alert-danger m-3">Failed to load VNC console: ' + error + '</div>';
|
||||
});
|
||||
}
|
||||
|
||||
// Open VNC in new tab
|
||||
function openVNCNewTab() {
|
||||
window.open(productURL + '&modop=custom&a=VNC', '_blank');
|
||||
}
|
||||
|
||||
// Toggle fullscreen for VNC
|
||||
function toggleVNCFullscreen() {
|
||||
var card = document.getElementById('vncCard');
|
||||
var iframe = document.getElementById('vncIframe');
|
||||
var btn = document.getElementById('vncFullscreenBtn');
|
||||
|
||||
if (!document.fullscreenElement) {
|
||||
if (card.requestFullscreen) {
|
||||
card.requestFullscreen();
|
||||
} else if (card.webkitRequestFullscreen) {
|
||||
card.webkitRequestFullscreen();
|
||||
} else if (card.msRequestFullscreen) {
|
||||
card.msRequestFullscreen();
|
||||
}
|
||||
iframe.style.height = '100vh';
|
||||
btn.innerHTML = '<i class="fa fa-compress"></i>';
|
||||
} else {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.webkitExitFullscreen) {
|
||||
document.webkitExitFullscreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
iframe.style.height = '600px';
|
||||
btn.innerHTML = '<i class="fa fa-expand"></i>';
|
||||
}
|
||||
}
|
||||
|
||||
// Handle fullscreen change events
|
||||
document.addEventListener('fullscreenchange', function() {
|
||||
var iframe = document.getElementById('vncIframe');
|
||||
var btn = document.getElementById('vncFullscreenBtn');
|
||||
if (!document.fullscreenElement && iframe && btn) {
|
||||
iframe.style.height = '600px';
|
||||
btn.innerHTML = '<i class="fa fa-expand"></i>';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user