mirror of
https://gitlab.com/ArkHost/WHMCS-ArkhostVPSAG.git
synced 2026-07-24 07:45:55 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac2c3f08d9 | ||
|
|
f2f2222df7 | ||
|
|
9c09719fb9 | ||
|
|
ee3da3f0e7 | ||
|
|
804d05a600 | ||
|
|
1196783c2d | ||
|
|
94bc3045b8 | ||
|
|
b4529ee9b2 | ||
|
|
fae7960bbd | ||
|
|
0ed2a0076c | ||
|
|
3efb34a506 | ||
|
|
dbb00718c0 | ||
|
|
dc5e603870 |
@@ -1,26 +1,185 @@
|
|||||||
# WHMCS VPS Management Module - ArkHost VPSAG
|
# WHMCS VPS Management Module - ArkHost VPSAG
|
||||||
|
|
||||||
A WHMCS server module for VPS management with multi-language support.
|
A WHMCS server module for VPSAG/EVPS VPS management with multi-language support.
|
||||||
|
|
||||||
|
**Note:** VPSAG has rebranded to [EVPS.net](https://evps.net). The API remains unchanged at `vpsag.com`.
|
||||||
|
|
||||||
|
Originally based on [andretunes/whmcs-module-vpsag](https://github.com/andretunes/whmcs-module-vpsag). Current version has been substantially rewritten.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- VPS control (start/stop/restart)
|
- VPS provisioning and lifecycle management
|
||||||
- Backup management
|
- VPS control (start/stop/restart/shutdown)
|
||||||
|
- Backup management (create/restore/delete)
|
||||||
- Firewall configuration
|
- Firewall configuration
|
||||||
- OS reinstallation with advanced options
|
- OS reinstallation with SSH key injection and post-install scripts
|
||||||
- Resource monitoring
|
- Resource monitoring with graphs
|
||||||
- VNC console access
|
- VNC console access
|
||||||
- 8 language support
|
- Hostname and rDNS management
|
||||||
- Responsive design
|
- ISO mounting
|
||||||
|
- 8 language support (English, Dutch, French, German, Italian, Portuguese, Russian, Spanish)
|
||||||
|
- Responsive client area design
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- WHMCS 8.9+
|
- WHMCS 8.9+
|
||||||
- PHP 7.4+
|
- PHP 7.4+
|
||||||
|
- VPSAG/EVPS reseller account with API access
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Upload the `ArkhostVPSAG` folder to `/modules/servers/` in your WHMCS installation
|
||||||
|
2. Navigate to **Setup > Products/Services > Servers** in WHMCS admin
|
||||||
|
3. Add a new server with:
|
||||||
|
- **Module:** ArkhostVPSAG
|
||||||
|
- **Hostname:** `www.vpsag.com`
|
||||||
|
- **Username:** Your VPSAG API username
|
||||||
|
- **Password:** Your VPSAG API key
|
||||||
|
4. Click **Test Connection** to verify credentials
|
||||||
|
|
||||||
|
## Product Configuration
|
||||||
|
|
||||||
|
### Creating a Product
|
||||||
|
|
||||||
|
1. Go to **Setup > Products/Services > Products/Services**
|
||||||
|
2. Create a new product or edit an existing one
|
||||||
|
3. Under **Module Settings** tab:
|
||||||
|
- **Module Name:** ArkhostVPSAG
|
||||||
|
- **Server Group:** Select your VPSAG server group
|
||||||
|
|
||||||
|
### Configurable Options
|
||||||
|
|
||||||
|
The module uses two primary configurable options that are dynamically populated from the VPSAG API:
|
||||||
|
|
||||||
|
| Option | Config Key | Description |
|
||||||
|
|--------|------------|-------------|
|
||||||
|
| **Plan ID** | `configoption1` | VPS plan - dropdown populated from `/api/v1/plans` showing plan names with prices |
|
||||||
|
| **OS ID** | `configoption2` | Operating system - dropdown populated from `/api/v1/os/plan/{plan_id}` based on selected plan |
|
||||||
|
| **VNC Display Mode** | `configoption3` | How VNC console is displayed: `newtab` (opens in new browser tab) or `embedded` (shows in a tab within the client area) |
|
||||||
|
|
||||||
|
#### Setting Up Configurable Options
|
||||||
|
|
||||||
|
You can override the default product options using WHMCS Configurable Options:
|
||||||
|
|
||||||
|
1. Go to **Setup > Products/Services > Configurable Options**
|
||||||
|
2. Create a new group and link it to your VPSAG product(s)
|
||||||
|
3. Add options with these exact names:
|
||||||
|
- `planid|Plan` - To allow customers to select different plans
|
||||||
|
- `osid|Operating System` - To allow customers to select their OS during order
|
||||||
|
|
||||||
|
**Option format:** `{api_id}|{display_name}`
|
||||||
|
|
||||||
|
The numeric ID before the pipe is the API ID from VPSAG/EVPS.
|
||||||
|
|
||||||
|
#### Finding the IDs
|
||||||
|
|
||||||
|
The module displays IDs directly in the dropdowns (format: `ID | Name`):
|
||||||
|
|
||||||
|
1. Go to **Setup > Products/Services > Products/Services**
|
||||||
|
2. Edit any product using the ArkhostVPSAG module
|
||||||
|
3. Go to the **Module Settings** tab
|
||||||
|
4. The **Plan** and **Operating System** dropdowns show: `{id} | {name}`
|
||||||
|
|
||||||
|
Use those IDs when creating Configurable Options.
|
||||||
|
|
||||||
|
**API terminology:**
|
||||||
|
- `planid` = Package/Plan ID from VPSAG API
|
||||||
|
- `osid` = Operating System ID from VPSAG API
|
||||||
|
|
||||||
|
**Note:** OS availability varies by plan - you must select a Plan first before the OS dropdown populates.
|
||||||
|
|
||||||
|
The module checks for configurable options first, then falls back to product-level settings.
|
||||||
|
|
||||||
|
### Callback URL
|
||||||
|
|
||||||
|
For automatic provisioning updates (IP, password delivery), configure your callback URL in VPSAG:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://yourdomain.com/modules/servers/ArkhostVPSAG/callback.php
|
||||||
|
```
|
||||||
|
|
||||||
|
The callback handler:
|
||||||
|
- Validates requests using SHA256 signature verification
|
||||||
|
- Updates service with username, password, IPs (IPv4/IPv6)
|
||||||
|
- Sets VPS label to `WHMCS {service_id}` for easy identification
|
||||||
|
|
||||||
|
## Module Functions
|
||||||
|
|
||||||
|
### Client Area Actions
|
||||||
|
|
||||||
|
| Action | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| Start/Stop/Restart | Basic power controls |
|
||||||
|
| VNC Console | Browser-based console access |
|
||||||
|
| Reinstall OS | Fresh install with optional SSH key and post-install script |
|
||||||
|
| Reset Root Password | Generate new root password |
|
||||||
|
| Hostname/rDNS | Set hostname and reverse DNS |
|
||||||
|
| Graphs | View CPU, RAM, disk, network usage over time |
|
||||||
|
| Backups | Create, restore, and delete backups |
|
||||||
|
| Firewall | Add/remove rules, commit changes |
|
||||||
|
| ISO | Mount/unmount ISO images |
|
||||||
|
|
||||||
|
### Admin Actions
|
||||||
|
|
||||||
|
| Action | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| Start/Stop/Reboot | Power controls from admin panel |
|
||||||
|
| VNC Console | Direct VNC link |
|
||||||
|
| Suspend/Unsuspend | Service suspension management |
|
||||||
|
| Terminate | Cancel VPS at VPSAG |
|
||||||
|
| Change Package | Upgrade to higher plan |
|
||||||
|
|
||||||
|
### Sidebar Buttons
|
||||||
|
|
||||||
|
The module adds custom sidebar buttons to the client area:
|
||||||
|
- Start, Stop, Restart, VNC Console
|
||||||
|
|
||||||
|
## API Integration
|
||||||
|
|
||||||
|
Base URL: `https://www.vpsag.com/api/v1/`
|
||||||
|
|
||||||
|
Authentication headers:
|
||||||
|
- `X_API_USER`: API username
|
||||||
|
- `X_API_KEY`: API key
|
||||||
|
|
||||||
|
The module handles all API communication internally with:
|
||||||
|
- TLS 1.2 enforcement
|
||||||
|
- 15-second timeout
|
||||||
|
- Full request/response logging via WHMCS module log
|
||||||
|
|
||||||
|
## VPS ID Storage
|
||||||
|
|
||||||
|
The VPS ID is stored in WHMCS service properties with key `vpsag|VPSAG ID` in format `VPSAG-{numeric_id}`.
|
||||||
|
|
||||||
|
## Language Customization
|
||||||
|
|
||||||
|
Override translations by creating files in:
|
||||||
|
```
|
||||||
|
/modules/servers/ArkhostVPSAG/lang/overrides/{language}.php
|
||||||
|
```
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
### Overview
|
||||||
|

|
||||||
|
|
||||||
|
### Graphs
|
||||||
|

|
||||||
|
|
||||||
|
### Backups
|
||||||
|

|
||||||
|
|
||||||
|
### Firewall
|
||||||
|

|
||||||
|
|
||||||
|
### Settings
|
||||||
|

|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### Version 1.5
|
||||||
|
- WHMCS v9 compatibility: Updated Smarty template syntax for Smarty v4
|
||||||
|
|
||||||
### Version 1.4
|
### Version 1.4
|
||||||
- Fixed firewall rule duplication bug when adding new rules
|
- Fixed firewall rule duplication bug when adding new rules
|
||||||
- Added validation warning for ANY protocol with specific port numbers
|
- Added validation warning for ANY protocol with specific port numbers
|
||||||
@@ -32,10 +191,9 @@ A WHMCS server module for VPS management with multi-language support.
|
|||||||
- Resource Usage Card (RAM, Bandwidth, CPU)
|
- Resource Usage Card (RAM, Bandwidth, CPU)
|
||||||
- Quick Actions Card (Start/Stop, Restart, VNC Console)
|
- Quick Actions Card (Start/Stop, Restart, VNC Console)
|
||||||
- Fixed Quick Actions button functionality
|
- Fixed Quick Actions button functionality
|
||||||
- Completed all language translations (8 languages: English, Dutch, French, German, Italian, Portuguese, Russian, Spanish)
|
- Completed all language translations (8 languages)
|
||||||
- Enhanced UI styling with gradient backgrounds and smooth animations
|
- Enhanced UI styling with gradient backgrounds and smooth animations
|
||||||
- Improved responsive design and layout consistency
|
- Improved responsive design and layout consistency
|
||||||
- Removed duplicate VPS Information section
|
|
||||||
|
|
||||||
### Version 1.3
|
### Version 1.3
|
||||||
- Enhanced API integration
|
- Enhanced API integration
|
||||||
@@ -59,6 +217,11 @@ A WHMCS server module for VPS management with multi-language support.
|
|||||||
### Version 1.0
|
### Version 1.0
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
Originally based on work by [andretunes](https://github.com/andretunes/whmcs-module-vpsag)
|
||||||
|
Substantially rewritten and extended by ArkHost
|
||||||
|
|
||||||
|
## License
|
||||||
MIT License
|
MIT License
|
||||||
© 2025 ArkHost
|
© 2025 ArkHost
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* WHMCS Server Module - VPSAG
|
* WHMCS Server Module - VPSAG
|
||||||
*
|
*
|
||||||
* @package WHMCS
|
* @package WHMCS
|
||||||
* @version 1.4
|
* @version 1.5
|
||||||
* @copyright Copyright (c) ArkHost 2025
|
* @copyright Copyright (c) ArkHost 2025
|
||||||
* @author ArkHost <support@arkhost.com>
|
* @author ArkHost <support@arkhost.com>
|
||||||
* @link https://arkhost.com
|
* @link https://arkhost.com
|
||||||
@@ -69,7 +69,7 @@ function ArkhostVPSAG_API(array $params) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
$data += array(
|
$data += array(
|
||||||
'hostname' => $params['domain'] ?? 'vps.example.com',
|
// 'hostname' => removed - let VPSAG generate the hostname automatically
|
||||||
'notify_url' => Setting::getValue('SystemURL') . '/modules/servers/ArkhostVPSAG/callback.php',
|
'notify_url' => Setting::getValue('SystemURL') . '/modules/servers/ArkhostVPSAG/callback.php',
|
||||||
'os' => ArkhostVPSAG_GetOption($params, 'osid'),
|
'os' => ArkhostVPSAG_GetOption($params, 'osid'),
|
||||||
'billing_term' => $billingCycles[$params['model']['billingcycle']] ?? 1,
|
'billing_term' => $billingCycles[$params['model']['billingcycle']] ?? 1,
|
||||||
@@ -323,6 +323,92 @@ function ArkhostVPSAG_Error($func, $params, Exception $err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ArkhostVPSAG_MetaData() {
|
function ArkhostVPSAG_MetaData() {
|
||||||
|
// Register sidebar hook here to ensure it's always loaded
|
||||||
|
static $hookRegistered = false;
|
||||||
|
if (!$hookRegistered) {
|
||||||
|
$hookRegistered = true;
|
||||||
|
add_hook('ClientAreaPrimarySidebar', 100, function(\WHMCS\View\Menu\Item $primarySidebar) {
|
||||||
|
$serviceId = isset($_GET['id']) ? (int) $_GET['id'] : 0;
|
||||||
|
if (!$serviceId) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$service = Capsule::table('tblhosting')
|
||||||
|
->join('tblproducts', 'tblhosting.packageid', '=', 'tblproducts.id')
|
||||||
|
->where('tblhosting.id', $serviceId)
|
||||||
|
->select('tblhosting.*', 'tblproducts.servertype')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$service || $service->servertype !== 'ArkhostVPSAG' || $service->domainstatus !== 'Active') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$actionsPanel = $primarySidebar->getChild('Service Details Actions');
|
||||||
|
if (!$actionsPanel) return;
|
||||||
|
|
||||||
|
// Load language strings
|
||||||
|
if (!function_exists('ArkhostVPSAG_Translation')) {
|
||||||
|
require_once __DIR__ . '/ArkhostVPSAG.php';
|
||||||
|
}
|
||||||
|
$_LANG = ArkhostVPSAG_Translation();
|
||||||
|
|
||||||
|
// Remove only OUR custom action buttons (created by ClientAreaCustomButtonArray with cog icons)
|
||||||
|
// They have modop=custom in the URI
|
||||||
|
$existingChildren = $actionsPanel->getChildren();
|
||||||
|
foreach ($existingChildren as $childName => $child) {
|
||||||
|
$uri = $child->getUri();
|
||||||
|
if ($uri && strpos($uri, 'modop=custom') !== false) {
|
||||||
|
$actionsPanel->removeChild($childName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add custom action buttons with proper icons
|
||||||
|
$actionsPanel->addChild('VPSStart', [
|
||||||
|
'label' => $_LANG['Start'],
|
||||||
|
'uri' => 'clientarea.php?action=productdetails&id=' . $serviceId . '&modop=custom&a=Start',
|
||||||
|
'order' => 10,
|
||||||
|
'icon' => 'fa-play'
|
||||||
|
]);
|
||||||
|
$actionsPanel->addChild('VPSStop', [
|
||||||
|
'label' => $_LANG['Stop'],
|
||||||
|
'uri' => 'clientarea.php?action=productdetails&id=' . $serviceId . '&modop=custom&a=Stop',
|
||||||
|
'order' => 20,
|
||||||
|
'icon' => 'fa-stop'
|
||||||
|
]);
|
||||||
|
$actionsPanel->addChild('VPSRestart', [
|
||||||
|
'label' => $_LANG['Restart'],
|
||||||
|
'uri' => 'clientarea.php?action=productdetails&id=' . $serviceId . '&modop=custom&a=Reboot',
|
||||||
|
'order' => 30,
|
||||||
|
'icon' => 'fa-sync'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 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']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'DisplayName' => 'ArkHost - VPSAG',
|
'DisplayName' => 'ArkHost - VPSAG',
|
||||||
'APIVersion' => '1.1',
|
'APIVersion' => '1.1',
|
||||||
@@ -352,6 +438,16 @@ function ArkhostVPSAG_ConfigOptions() {
|
|||||||
'Type' => 'dropdown',
|
'Type' => 'dropdown',
|
||||||
'Options' => array(),
|
'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
|
// Extra resource options removed - now handled via plan selection
|
||||||
// Plans have fixed resources defined within them in the new API
|
// Plans have fixed resources defined within them in the new API
|
||||||
);
|
);
|
||||||
@@ -401,7 +497,7 @@ function ArkhostVPSAG_ConfigOptions() {
|
|||||||
|
|
||||||
foreach ($packageslist as $package) {
|
foreach ($packageslist as $package) {
|
||||||
$array['planid']['Options'] += array(
|
$array['planid']['Options'] += array(
|
||||||
$package['id'] => $package['name'] . ' (' . $package['price'] . '€)'
|
$package['id'] => $package['id'] . ' | ' . $package['name'] . ' (' . $package['price'] . '€)'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,7 +509,7 @@ function ArkhostVPSAG_ConfigOptions() {
|
|||||||
|
|
||||||
foreach ($operatingSystems as $operatingSystem) {
|
foreach ($operatingSystems as $operatingSystem) {
|
||||||
$array['osid']['Options'] += array(
|
$array['osid']['Options'] += array(
|
||||||
$operatingSystem['id'] => $operatingSystem['name']
|
$operatingSystem['id'] => $operatingSystem['id'] . ' | ' . $operatingSystem['name']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,7 +610,7 @@ function ArkhostVPSAG_CreateAccount(array $params) {
|
|||||||
|
|
||||||
function ArkhostVPSAG_SuspendAccount(array $params) {
|
function ArkhostVPSAG_SuspendAccount(array $params) {
|
||||||
try {
|
try {
|
||||||
$params['action'] = 'Disable';
|
$params['action'] = 'Stop';
|
||||||
ArkhostVPSAG_API($params);
|
ArkhostVPSAG_API($params);
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
ArkhostVPSAG_Error(__FUNCTION__, $params, $err);
|
ArkhostVPSAG_Error(__FUNCTION__, $params, $err);
|
||||||
@@ -526,7 +622,7 @@ function ArkhostVPSAG_SuspendAccount(array $params) {
|
|||||||
|
|
||||||
function ArkhostVPSAG_UnsuspendAccount(array $params) {
|
function ArkhostVPSAG_UnsuspendAccount(array $params) {
|
||||||
try {
|
try {
|
||||||
$params['action'] = 'Enable';
|
$params['action'] = 'Start';
|
||||||
ArkhostVPSAG_API($params);
|
ArkhostVPSAG_API($params);
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
ArkhostVPSAG_Error(__FUNCTION__, $params, $err);
|
ArkhostVPSAG_Error(__FUNCTION__, $params, $err);
|
||||||
@@ -648,7 +744,7 @@ function ArkhostVPSAG_AdminLink(array $params) {
|
|||||||
function ArkhostVPSAG_ClientAreaAPI(array $params) {
|
function ArkhostVPSAG_ClientAreaAPI(array $params) {
|
||||||
try {
|
try {
|
||||||
$action = App::getFromRequest('api');
|
$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');
|
$results = array('result' => 'success');
|
||||||
|
|
||||||
if (in_array($action, $actions)) {
|
if (in_array($action, $actions)) {
|
||||||
@@ -737,6 +833,8 @@ function ArkhostVPSAG_DeliverFile(array $params) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This function is required for WHMCS to handle the custom actions
|
||||||
|
// The hook in MetaData() replaces the sidebar buttons to remove cog icons
|
||||||
function ArkhostVPSAG_ClientAreaCustomButtonArray() {
|
function ArkhostVPSAG_ClientAreaCustomButtonArray() {
|
||||||
$_LANG = ArkhostVPSAG_Translation();
|
$_LANG = ArkhostVPSAG_Translation();
|
||||||
|
|
||||||
@@ -777,6 +875,13 @@ function ArkhostVPSAG_ClientArea(array $params) {
|
|||||||
throw new Exception('Unable to retrieve server information from API');
|
throw new Exception('Unable to retrieve server information from API');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync the domain field with VPS hostname so it shows in WHMCS product details
|
||||||
|
if (isset($serverInfo['hostname']) && !empty($serverInfo['hostname'])) {
|
||||||
|
Capsule::table('tblhosting')
|
||||||
|
->where('id', $params['serviceid'])
|
||||||
|
->update(['domain' => $serverInfo['hostname']]);
|
||||||
|
}
|
||||||
|
|
||||||
$params['action'] = 'Operating Systems - Server';
|
$params['action'] = 'Operating Systems - Server';
|
||||||
$operatingSystemsTemp = ArkhostVPSAG_API($params);
|
$operatingSystemsTemp = ArkhostVPSAG_API($params);
|
||||||
|
|
||||||
@@ -921,6 +1026,11 @@ function ArkhostVPSAG_ClientArea(array $params) {
|
|||||||
$serverInfo['bandwidth_used'] = isset($serverInfo['bandwidth_used']) ? $serverInfo['bandwidth_used'] : 0;
|
$serverInfo['bandwidth_used'] = isset($serverInfo['bandwidth_used']) ? $serverInfo['bandwidth_used'] : 0;
|
||||||
$serverInfo['bandwidth'] = isset($serverInfo['bandwidth']) ? $serverInfo['bandwidth'] : 1;
|
$serverInfo['bandwidth'] = isset($serverInfo['bandwidth']) ? $serverInfo['bandwidth'] : 1;
|
||||||
|
|
||||||
|
// Get VNC mode setting (configoption3)
|
||||||
|
$vncMode = isset($params['configoption3']) && $params['configoption3'] !== ''
|
||||||
|
? $params['configoption3']
|
||||||
|
: 'newtab';
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'templatefile' => 'template/clientarea_direct',
|
'templatefile' => 'template/clientarea_direct',
|
||||||
'templateVariables' => array(
|
'templateVariables' => array(
|
||||||
@@ -929,6 +1039,7 @@ function ArkhostVPSAG_ClientArea(array $params) {
|
|||||||
'operatingSystems' => $operatingSystems,
|
'operatingSystems' => $operatingSystems,
|
||||||
'token' => generate_token('plain'),
|
'token' => generate_token('plain'),
|
||||||
'_LANG' => ArkhostVPSAG_Translation(),
|
'_LANG' => ArkhostVPSAG_Translation(),
|
||||||
|
'vncMode' => $vncMode,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* WHMCS Server Module - VPSAG Hooks
|
||||||
|
*
|
||||||
|
* @package WHMCS
|
||||||
|
* @version 1.4
|
||||||
|
* @copyright Copyright (c) ArkHost 2025
|
||||||
|
* @author ArkHost <support@arkhost.com>
|
||||||
|
* @link https://arkhost.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
use WHMCS\Database\Capsule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide default WHMCS product details and cog icons for ArkhostVPSAG products
|
||||||
|
* Injects CSS early to prevent flash of content
|
||||||
|
*/
|
||||||
|
add_hook('ClientAreaHeadOutput', 1, function($vars) {
|
||||||
|
// Only run on product details page
|
||||||
|
if (!isset($_GET['action']) || $_GET['action'] !== 'productdetails') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the service ID from the request
|
||||||
|
$serviceId = isset($_GET['id']) ? (int) $_GET['id'] : 0;
|
||||||
|
if (!$serviceId) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this service uses the ArkhostVPSAG module
|
||||||
|
try {
|
||||||
|
$service = Capsule::table('tblhosting')
|
||||||
|
->where('id', $serviceId)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$service || $service->servertype !== 'ArkhostVPSAG') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inject CSS early in the HEAD to prevent flash
|
||||||
|
// This works for both active and suspended services
|
||||||
|
return <<<HTML
|
||||||
|
<style>
|
||||||
|
/* Hide WHMCS default product details (Domain, Username, Server Name, IP, Visit Website) for ArkhostVPSAG */
|
||||||
|
#domain > .row:nth-child(2),
|
||||||
|
#domain > .row:nth-child(3),
|
||||||
|
#domain > .row:nth-child(4) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
#domain > br {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
#domain > p {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide cog icons from custom action buttons IMMEDIATELY */
|
||||||
|
.list-group-item[href*="modop=custom"] i.fa-cog,
|
||||||
|
.list-group-item[href*="modop=custom"] i.fas.fa-cog,
|
||||||
|
.list-group-item[href*="modop=custom"] .fa-cog,
|
||||||
|
.list-group-item[href*="modop=custom"] i.fa-wrench,
|
||||||
|
a[href*="modop=custom"] i.fa-cog,
|
||||||
|
a[href*="modop=custom"] i.fas.fa-cog,
|
||||||
|
a[href*="modop=custom"] .fa-cog {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
HTML;
|
||||||
|
});
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Gebruikt';
|
|||||||
$_ADDONLANG['Start'] = 'Start';
|
$_ADDONLANG['Start'] = 'Start';
|
||||||
$_ADDONLANG['Stop'] = 'Stop';
|
$_ADDONLANG['Stop'] = 'Stop';
|
||||||
$_ADDONLANG['Restart'] = 'Herstarten';
|
$_ADDONLANG['Restart'] = 'Herstarten';
|
||||||
$_ADDONLANG['VNC'] = 'VNC-console';
|
$_ADDONLANG['VNC'] = 'VNC';
|
||||||
$_ADDONLANG['General']['Note'] = 'Opmerking';
|
$_ADDONLANG['General']['Note'] = 'Opmerking';
|
||||||
$_ADDONLANG['LoadingFirewallRules'] = 'Firewall-regels laden...';
|
$_ADDONLANG['LoadingFirewallRules'] = 'Firewall-regels laden...';
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Used';
|
|||||||
$_ADDONLANG['Start'] = 'Start';
|
$_ADDONLANG['Start'] = 'Start';
|
||||||
$_ADDONLANG['Stop'] = 'Stop';
|
$_ADDONLANG['Stop'] = 'Stop';
|
||||||
$_ADDONLANG['Restart'] = 'Restart';
|
$_ADDONLANG['Restart'] = 'Restart';
|
||||||
$_ADDONLANG['VNC'] = 'VNC Console';
|
$_ADDONLANG['VNC'] = 'VNC';
|
||||||
$_ADDONLANG['General']['Note'] = 'Note';
|
$_ADDONLANG['General']['Note'] = 'Note';
|
||||||
$_ADDONLANG['LoadingFirewallRules'] = 'Loading firewall rules...';
|
$_ADDONLANG['LoadingFirewallRules'] = 'Loading firewall rules...';
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Utilisé';
|
|||||||
$_ADDONLANG['Start'] = 'Démarrer';
|
$_ADDONLANG['Start'] = 'Démarrer';
|
||||||
$_ADDONLANG['Stop'] = 'Arrêter';
|
$_ADDONLANG['Stop'] = 'Arrêter';
|
||||||
$_ADDONLANG['Restart'] = 'Redémarrer';
|
$_ADDONLANG['Restart'] = 'Redémarrer';
|
||||||
$_ADDONLANG['VNC'] = 'Console VNC';
|
$_ADDONLANG['VNC'] = 'VNC';
|
||||||
$_ADDONLANG['General']['Note'] = 'Note';
|
$_ADDONLANG['General']['Note'] = 'Note';
|
||||||
$_ADDONLANG['LoadingFirewallRules'] = 'Chargement des règles de pare-feu...';
|
$_ADDONLANG['LoadingFirewallRules'] = 'Chargement des règles de pare-feu...';
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Verwendet';
|
|||||||
$_ADDONLANG['Start'] = 'Starten';
|
$_ADDONLANG['Start'] = 'Starten';
|
||||||
$_ADDONLANG['Stop'] = 'Stoppen';
|
$_ADDONLANG['Stop'] = 'Stoppen';
|
||||||
$_ADDONLANG['Restart'] = 'Neustart';
|
$_ADDONLANG['Restart'] = 'Neustart';
|
||||||
$_ADDONLANG['VNC'] = 'VNC-Konsole';
|
$_ADDONLANG['VNC'] = 'VNC';
|
||||||
$_ADDONLANG['General']['Note'] = 'Notiz';
|
$_ADDONLANG['General']['Note'] = 'Notiz';
|
||||||
$_ADDONLANG['LoadingFirewallRules'] = 'Firewall-Regeln werden geladen...';
|
$_ADDONLANG['LoadingFirewallRules'] = 'Firewall-Regeln werden geladen...';
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Utilizzato';
|
|||||||
$_ADDONLANG['Start'] = 'Avvia';
|
$_ADDONLANG['Start'] = 'Avvia';
|
||||||
$_ADDONLANG['Stop'] = 'Ferma';
|
$_ADDONLANG['Stop'] = 'Ferma';
|
||||||
$_ADDONLANG['Restart'] = 'Riavvia';
|
$_ADDONLANG['Restart'] = 'Riavvia';
|
||||||
$_ADDONLANG['VNC'] = 'Console VNC';
|
$_ADDONLANG['VNC'] = 'VNC';
|
||||||
$_ADDONLANG['General']['Note'] = 'Nota';
|
$_ADDONLANG['General']['Note'] = 'Nota';
|
||||||
$_ADDONLANG['LoadingFirewallRules'] = 'Caricamento regole firewall...';
|
$_ADDONLANG['LoadingFirewallRules'] = 'Caricamento regole firewall...';
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Utilizado';
|
|||||||
$_ADDONLANG['Start'] = 'Iniciar';
|
$_ADDONLANG['Start'] = 'Iniciar';
|
||||||
$_ADDONLANG['Stop'] = 'Parar';
|
$_ADDONLANG['Stop'] = 'Parar';
|
||||||
$_ADDONLANG['Restart'] = 'Reiniciar';
|
$_ADDONLANG['Restart'] = 'Reiniciar';
|
||||||
$_ADDONLANG['VNC'] = 'Consola VNC';
|
$_ADDONLANG['VNC'] = 'VNC';
|
||||||
$_ADDONLANG['General']['Note'] = 'Nota';
|
$_ADDONLANG['General']['Note'] = 'Nota';
|
||||||
$_ADDONLANG['LoadingFirewallRules'] = 'Carregando regras de firewall...';
|
$_ADDONLANG['LoadingFirewallRules'] = 'Carregando regras de firewall...';
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Использовано';
|
|||||||
$_ADDONLANG['Start'] = 'Запуск';
|
$_ADDONLANG['Start'] = 'Запуск';
|
||||||
$_ADDONLANG['Stop'] = 'Остановка';
|
$_ADDONLANG['Stop'] = 'Остановка';
|
||||||
$_ADDONLANG['Restart'] = 'Перезапуск';
|
$_ADDONLANG['Restart'] = 'Перезапуск';
|
||||||
$_ADDONLANG['VNC'] = 'Консоль VNC';
|
$_ADDONLANG['VNC'] = 'VNC';
|
||||||
$_ADDONLANG['General']['Note'] = 'Примечание';
|
$_ADDONLANG['General']['Note'] = 'Примечание';
|
||||||
$_ADDONLANG['LoadingFirewallRules'] = 'Загрузка правил файрвола...';
|
$_ADDONLANG['LoadingFirewallRules'] = 'Загрузка правил файрвола...';
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ $_ADDONLANG['Used'] = 'Usado';
|
|||||||
$_ADDONLANG['Start'] = 'Iniciar';
|
$_ADDONLANG['Start'] = 'Iniciar';
|
||||||
$_ADDONLANG['Stop'] = 'Detener';
|
$_ADDONLANG['Stop'] = 'Detener';
|
||||||
$_ADDONLANG['Restart'] = 'Reiniciar';
|
$_ADDONLANG['Restart'] = 'Reiniciar';
|
||||||
$_ADDONLANG['VNC'] = 'Consola VNC';
|
$_ADDONLANG['VNC'] = 'VNC';
|
||||||
$_ADDONLANG['General']['Note'] = 'Nota';
|
$_ADDONLANG['General']['Note'] = 'Nota';
|
||||||
$_ADDONLANG['LoadingFirewallRules'] = 'Cargando reglas de firewall...';
|
$_ADDONLANG['LoadingFirewallRules'] = 'Cargando reglas de firewall...';
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,46 @@
|
|||||||
* @link https://arkhost.com
|
* @link https://arkhost.com
|
||||||
* @author ArkHost <support@arkhost.com>
|
* @author ArkHost <support@arkhost.com>
|
||||||
*}
|
*}
|
||||||
|
{* Store VNC hash for later, remove it to prevent page issues *}
|
||||||
|
<script>
|
||||||
|
var arkhostVNCHashDetected = (window.location.hash === '#vnc');
|
||||||
|
if (arkhostVNCHashDetected) {
|
||||||
|
history.replaceState(null, null, window.location.pathname + window.location.search);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* Hide WHMCS default product details except Domain (keep Domain visible to show VPS hostname) */
|
||||||
|
/* Hide Username, Server Name, IP Address rows using nth-child selectors */
|
||||||
|
#domain > .row:nth-child(2) {
|
||||||
|
display: none !important; /* Username */
|
||||||
|
}
|
||||||
|
#domain > .row:nth-child(3) {
|
||||||
|
display: none !important; /* Server Name */
|
||||||
|
}
|
||||||
|
#domain > .row:nth-child(4) {
|
||||||
|
display: none !important; /* IP Address */
|
||||||
|
}
|
||||||
|
#domain > br {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
#domain > p {
|
||||||
|
display: none !important; /* Visit Website button */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide original Domain label - will be replaced with Hostname via JavaScript */
|
||||||
|
#domain > .row:nth-child(1) .col-sm-5 strong {
|
||||||
|
visibility: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#domain > .row:nth-child(1) .col-sm-5 strong::after {
|
||||||
|
visibility: visible;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
content: attr(data-hostname-label);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.arkhost-vps-container {
|
.arkhost-vps-container {
|
||||||
font-family: 'Arial', sans-serif;
|
font-family: 'Arial', sans-serif;
|
||||||
margin: 15px 0;
|
margin: 15px 0;
|
||||||
@@ -615,7 +651,7 @@
|
|||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var productURL = '{$WEB_ROOT}/clientarea.php?action=productdetails&id={$serviceid}';
|
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 = {
|
var lang = {
|
||||||
moduleactionfailed: 'Action failed!',
|
moduleactionfailed: 'Action failed!',
|
||||||
moduleactionsuccess: 'Action completed successfully',
|
moduleactionsuccess: 'Action completed successfully',
|
||||||
@@ -1518,6 +1554,13 @@
|
|||||||
<i class="fa fa-cog"></i> {$_LANG['Navbar']['Settings']}
|
<i class="fa fa-cog"></i> {$_LANG['Navbar']['Settings']}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</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>
|
</ul>
|
||||||
<div class="tab-content" id="pills-tabContent">
|
<div class="tab-content" id="pills-tabContent">
|
||||||
<div class="tab-pane fade show active" id="overview" role="tabpanel" aria-labelledby="overview-tab">
|
<div class="tab-pane fade show active" id="overview" role="tabpanel" aria-labelledby="overview-tab">
|
||||||
@@ -1703,11 +1746,17 @@
|
|||||||
onclick="return confirmRestart();">
|
onclick="return confirmRestart();">
|
||||||
<i class="fa fa-sync mr-1"></i> {$_LANG['Restart']}
|
<i class="fa fa-sync mr-1"></i> {$_LANG['Restart']}
|
||||||
</button>
|
</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"
|
<a href="{$WEB_ROOT}/clientarea.php?action=productdetails&id={$serviceid}&modop=custom&a=VNC"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="btn btn-info">
|
class="btn btn-info">
|
||||||
<i class="fa fa-desktop mr-1"></i> {$_LANG['VNC']}
|
<i class="fa fa-desktop mr-1"></i> {$_LANG['VNC']}
|
||||||
</a>
|
</a>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -2085,6 +2134,32 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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="" sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock" style="width: 100%; height: 600px; border: none; display: none;"></iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -2094,5 +2169,158 @@
|
|||||||
// Wait for WHMCS jQuery to be ready and use it
|
// Wait for WHMCS jQuery to be ready and use it
|
||||||
jQuery(document).ready(function($) {
|
jQuery(document).ready(function($) {
|
||||||
// WHMCS already loads Bootstrap and Font Awesome - no need to load additional libraries
|
// WHMCS already loads Bootstrap and Font Awesome - no need to load additional libraries
|
||||||
|
|
||||||
|
// Replace "Domain" label with translated "Hostname" label
|
||||||
|
var hostnameLabel = '{$_LANG.Overview.Hostname|escape:"javascript"}';
|
||||||
|
$('#domain > .row:nth-child(1) .col-sm-5 strong').attr('data-hostname-label', hostnameLabel);
|
||||||
|
|
||||||
|
// Intercept sidebar VPS action button clicks to show confirmation popups
|
||||||
|
// Use capture phase to intercept before other handlers
|
||||||
|
$('.list-group-item').each(function() {
|
||||||
|
var $link = $(this);
|
||||||
|
var href = $link.attr('href');
|
||||||
|
|
||||||
|
if (!href) return;
|
||||||
|
|
||||||
|
// Remove any existing click handlers and add our own
|
||||||
|
if (href.indexOf('modop=custom&a=Start') !== -1) {
|
||||||
|
$link.off('click').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
ArkHostVPS_API('Start');
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
} else if (href.indexOf('modop=custom&a=Stop') !== -1) {
|
||||||
|
$link.off('click').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
confirmStop();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
} else if (href.indexOf('modop=custom&a=Reboot') !== -1) {
|
||||||
|
$link.off('click').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
confirmRestart();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle hash navigation for VNC tab (when coming from sidebar)
|
||||||
|
// Only run if embedded VNC mode is enabled (vnc tab exists)
|
||||||
|
if ($('#vnc-tab').length > 0) {
|
||||||
|
// Check on page load - use the stored variable from top of page
|
||||||
|
if (typeof arkhostVNCHashDetected !== 'undefined' && arkhostVNCHashDetected) {
|
||||||
|
setTimeout(function() {
|
||||||
|
$('#vnc-tab').tab('show');
|
||||||
|
if (typeof loadVNCConsole === 'function') {
|
||||||
|
loadVNCConsole();
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for hash changes
|
||||||
|
$(window).on('hashchange', function() {
|
||||||
|
if (window.location.hash === '#vnc') {
|
||||||
|
$('#vnc-tab').tab('show');
|
||||||
|
if (typeof loadVNCConsole === 'function') {
|
||||||
|
loadVNCConsole();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Intercept sidebar VNC link clicks
|
||||||
|
$('a[href$="#vnc"]').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$('#vnc-tab').tab('show');
|
||||||
|
if (typeof loadVNCConsole === 'function') {
|
||||||
|
loadVNCConsole();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
</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 - fetch URL via API to avoid session issues
|
||||||
|
function openVNCNewTab() {
|
||||||
|
jQuery.get(productURL + '&modop=custom&a=ClientAreaAPI&api=VNC Console&token={$token}', function(data) {
|
||||||
|
if (data && data.vnc_url) {
|
||||||
|
window.open(data.vnc_url, '_blank');
|
||||||
|
} else {
|
||||||
|
alert('Failed to get VNC URL');
|
||||||
|
}
|
||||||
|
}).fail(function() {
|
||||||
|
alert('Failed to get VNC URL');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 231 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 105 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
Reference in New Issue
Block a user