mirror of
https://github.com/crivion/laranode.git
synced 2026-05-06 21:52:34 +08:00
php version manager attempt #1
This commit is contained in:
@@ -15,4 +15,153 @@ class PHPManagerController extends Controller
|
||||
|
||||
return response()->json($versions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the PHP management page
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return inertia('PHP/Index');
|
||||
}
|
||||
|
||||
/**
|
||||
* List all installed PHP versions with their systemctl status
|
||||
*/
|
||||
public function list(): JsonResponse
|
||||
{
|
||||
$scriptPath = base_path('laranode-scripts/bin/laranode-php-list.sh');
|
||||
$output = shell_exec("sudo bash {$scriptPath}");
|
||||
|
||||
$phpVersions = json_decode($output, true) ?? [];
|
||||
|
||||
return response()->json($phpVersions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a new PHP version
|
||||
*/
|
||||
public function install(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'version' => 'required|string|regex:/^\d+\.\d+$/',
|
||||
]);
|
||||
|
||||
$version = $request->input('version');
|
||||
$scriptPath = base_path('laranode-scripts/bin/laranode-php-install.sh');
|
||||
|
||||
// Execute installation script
|
||||
$output = shell_exec("sudo bash {$scriptPath} {$version} 2>&1");
|
||||
|
||||
// Check if installation was successful
|
||||
if (strpos($output, 'installed successfully') !== false) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "PHP {$version} installed successfully",
|
||||
'output' => $output
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => "Failed to install PHP {$version}",
|
||||
'output' => $output
|
||||
], 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall a PHP version
|
||||
*/
|
||||
public function uninstall(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'version' => 'required|string|regex:/^\d+\.\d+$/',
|
||||
]);
|
||||
|
||||
$version = $request->input('version');
|
||||
$scriptPath = base_path('laranode-scripts/bin/laranode-php-uninstall.sh');
|
||||
|
||||
// Execute uninstallation script
|
||||
$output = shell_exec("sudo bash {$scriptPath} {$version} 2>&1");
|
||||
|
||||
// Check if uninstallation was successful
|
||||
if (strpos($output, 'uninstalled successfully') !== false) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "PHP {$version} uninstalled successfully",
|
||||
'output' => $output
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => "Failed to uninstall PHP {$version}",
|
||||
'output' => $output
|
||||
], 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle PHP-FPM service (enable/disable)
|
||||
*/
|
||||
public function toggleService(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'version' => 'required|string|regex:/^\d+\.\d+$/',
|
||||
'enabled' => 'required|boolean',
|
||||
]);
|
||||
|
||||
$version = $request->input('version');
|
||||
$enabled = $request->input('enabled');
|
||||
$action = $enabled ? 'enable' : 'disable';
|
||||
|
||||
$scriptPath = base_path('laranode-scripts/bin/laranode-php-service.sh');
|
||||
|
||||
// Execute service management script
|
||||
$output = shell_exec("sudo bash {$scriptPath} {$action} {$version} 2>&1");
|
||||
|
||||
// Check if action was successful
|
||||
if (strpos($output, 'completed successfully') !== false) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "PHP {$version}-FPM service {$action}d successfully",
|
||||
'output' => $output
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => "Failed to {$action} PHP {$version}-FPM service",
|
||||
'output' => $output
|
||||
], 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart PHP-FPM service
|
||||
*/
|
||||
public function restartService(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'version' => 'required|string|regex:/^\d+\.\d+$/',
|
||||
]);
|
||||
|
||||
$version = $request->input('version');
|
||||
$scriptPath = base_path('laranode-scripts/bin/laranode-php-service.sh');
|
||||
|
||||
// Execute restart script
|
||||
$output = shell_exec("sudo bash {$scriptPath} restart {$version} 2>&1");
|
||||
|
||||
// Check if restart was successful
|
||||
if (strpos($output, 'completed successfully') !== false) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "PHP {$version}-FPM service restarted successfully",
|
||||
'output' => $output
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => "Failed to restart PHP {$version}-FPM service",
|
||||
'output' => $output
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
47
laranode-scripts/bin/laranode-php-install.sh
Executable file
47
laranode-scripts/bin/laranode-php-install.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Install a PHP-FPM version with common extensions
|
||||
# Usage: ./laranode-php-install.sh {version}
|
||||
# Example: ./laranode-php-install.sh 8.4
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "Usage: $0 {php version: example 8.4}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PHP_VERSION=$1
|
||||
|
||||
echo "Installing PHP $PHP_VERSION-FPM..."
|
||||
|
||||
# Update apt cache
|
||||
apt-get update -qq
|
||||
|
||||
# Install PHP-FPM and common extensions
|
||||
apt-get install -y \
|
||||
php${PHP_VERSION}-fpm \
|
||||
php${PHP_VERSION}-cli \
|
||||
php${PHP_VERSION}-common \
|
||||
php${PHP_VERSION}-mysql \
|
||||
php${PHP_VERSION}-xml \
|
||||
php${PHP_VERSION}-curl \
|
||||
php${PHP_VERSION}-mbstring \
|
||||
php${PHP_VERSION}-zip \
|
||||
php${PHP_VERSION}-gd \
|
||||
php${PHP_VERSION}-bcmath \
|
||||
php${PHP_VERSION}-intl
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "PHP $PHP_VERSION installed successfully"
|
||||
|
||||
# Enable the service
|
||||
systemctl enable php${PHP_VERSION}-fpm
|
||||
|
||||
# Start the service
|
||||
systemctl start php${PHP_VERSION}-fpm
|
||||
|
||||
echo "PHP $PHP_VERSION-FPM service enabled and started"
|
||||
exit 0
|
||||
else
|
||||
echo "Failed to install PHP $PHP_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
38
laranode-scripts/bin/laranode-php-list.sh
Executable file
38
laranode-scripts/bin/laranode-php-list.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# List all installed PHP-FPM versions with their systemctl status
|
||||
# Output: JSON array of PHP versions with status
|
||||
|
||||
# Get all installed php*-fpm packages
|
||||
php_versions=$(dpkg -l | grep -E 'php[0-9]+\.[0-9]+-fpm' | awk '{print $2}' | sed 's/php\(.*\)-fpm/\1/')
|
||||
|
||||
echo "["
|
||||
first=true
|
||||
|
||||
for version in $php_versions; do
|
||||
# Get systemctl status
|
||||
if systemctl is-active --quiet "php${version}-fpm"; then
|
||||
status="active"
|
||||
else
|
||||
status="inactive"
|
||||
fi
|
||||
|
||||
# Get systemctl enabled status
|
||||
if systemctl is-enabled --quiet "php${version}-fpm" 2>/dev/null; then
|
||||
enabled="true"
|
||||
else
|
||||
enabled="false"
|
||||
fi
|
||||
|
||||
# Output JSON object
|
||||
if [ "$first" = true ]; then
|
||||
first=false
|
||||
else
|
||||
echo ","
|
||||
fi
|
||||
|
||||
echo -n " {\"version\": \"$version\", \"status\": \"$status\", \"enabled\": $enabled}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "]"
|
||||
43
laranode-scripts/bin/laranode-php-service.sh
Executable file
43
laranode-scripts/bin/laranode-php-service.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Manage PHP-FPM service (enable/disable/restart)
|
||||
# Usage: ./laranode-php-service.sh {action} {version}
|
||||
# Example: ./laranode-php-service.sh enable 8.4
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "Usage: $0 {action: enable|disable|restart} {php version: example 8.4}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ACTION=$1
|
||||
PHP_VERSION=$2
|
||||
|
||||
case $ACTION in
|
||||
enable)
|
||||
echo "Enabling PHP $PHP_VERSION-FPM service..."
|
||||
systemctl enable php${PHP_VERSION}-fpm
|
||||
systemctl start php${PHP_VERSION}-fpm
|
||||
;;
|
||||
disable)
|
||||
echo "Disabling PHP $PHP_VERSION-FPM service..."
|
||||
systemctl stop php${PHP_VERSION}-fpm
|
||||
systemctl disable php${PHP_VERSION}-fpm
|
||||
;;
|
||||
restart)
|
||||
echo "Restarting PHP $PHP_VERSION-FPM service..."
|
||||
systemctl restart php${PHP_VERSION}-fpm
|
||||
;;
|
||||
*)
|
||||
echo "Invalid action: $ACTION"
|
||||
echo "Valid actions: enable, disable, restart"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Action '$ACTION' completed successfully for PHP $PHP_VERSION-FPM"
|
||||
exit 0
|
||||
else
|
||||
echo "Failed to $ACTION PHP $PHP_VERSION-FPM"
|
||||
exit 1
|
||||
fi
|
||||
37
laranode-scripts/bin/laranode-php-uninstall.sh
Executable file
37
laranode-scripts/bin/laranode-php-uninstall.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Uninstall a PHP-FPM version
|
||||
# Usage: ./laranode-php-uninstall.sh {version}
|
||||
# Example: ./laranode-php-uninstall.sh 8.4
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "Usage: $0 {php version: example 8.4}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PHP_VERSION=$1
|
||||
|
||||
echo "Uninstalling PHP $PHP_VERSION-FPM..."
|
||||
|
||||
# Stop the service
|
||||
systemctl stop php${PHP_VERSION}-fpm
|
||||
|
||||
# Disable the service
|
||||
systemctl disable php${PHP_VERSION}-fpm
|
||||
|
||||
# Remove PHP packages
|
||||
apt-get remove -y php${PHP_VERSION}-*
|
||||
|
||||
# Purge configuration files
|
||||
apt-get purge -y php${PHP_VERSION}-*
|
||||
|
||||
# Clean up
|
||||
apt-get autoremove -y
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "PHP $PHP_VERSION uninstalled successfully"
|
||||
exit 0
|
||||
else
|
||||
echo "Failed to uninstall PHP $PHP_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
@@ -107,11 +107,10 @@ const SidebarNavi = () => {
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
{/* Postponed for next release
|
||||
{auth.user.role == 'admin' && (
|
||||
<li>
|
||||
<Link
|
||||
href="/php-manager"
|
||||
href={route('php.index')}
|
||||
className="relative flex flex-row items-center h-11 focus:outline-none hover:bg-gray-900 text-gray-300 border-l-4 border-transparent hover:border-indigo-900 pr-6"
|
||||
>
|
||||
<div>
|
||||
@@ -121,7 +120,6 @@ const SidebarNavi = () => {
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
*/}
|
||||
|
||||
<li>
|
||||
<Link
|
||||
|
||||
212
resources/js/Pages/PHP/Index.jsx
Normal file
212
resources/js/Pages/PHP/Index.jsx
Normal file
@@ -0,0 +1,212 @@
|
||||
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
|
||||
import { Head, router, usePage } from '@inertiajs/react';
|
||||
import { TbBrandPhp } from 'react-icons/tb';
|
||||
import { TiDelete } from 'react-icons/ti';
|
||||
import { FaToggleOn, FaToggleOff, FaSync } from 'react-icons/fa';
|
||||
import { toast } from 'react-toastify';
|
||||
import InstallPHPForm from './Partials/InstallPHPForm';
|
||||
import ConfirmationButton from '@/Components/ConfirmationButton';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function PHPIndex() {
|
||||
const { auth } = usePage().props;
|
||||
const [phpVersions, setPhpVersions] = useState([]);
|
||||
const [liveStats, setLiveStats] = useState({});
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const echo = window.Echo;
|
||||
|
||||
// Fetch installed PHP versions
|
||||
const fetchPhpVersions = () => {
|
||||
fetch(route('php.list'), {
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
setPhpVersions(data);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error('Failed to fetch PHP versions');
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchPhpVersions();
|
||||
|
||||
// Subscribe to live stats
|
||||
const dashboardChannel = echo.private("systemstats");
|
||||
|
||||
dashboardChannel.listen("SystemStatsEvent", (data) => {
|
||||
if (data.phpFpm) {
|
||||
setLiveStats(data.phpFpm);
|
||||
}
|
||||
});
|
||||
|
||||
const whisperInterval = setInterval(() => {
|
||||
dashboardChannel.whisper("typing", { requesting: "dashboard-realtime-stats" });
|
||||
}, 2000);
|
||||
|
||||
return () => {
|
||||
clearInterval(whisperInterval);
|
||||
echo.leave("systemstats");
|
||||
};
|
||||
}, []);
|
||||
|
||||
const uninstallPhp = (version) => {
|
||||
router.delete(route('php.uninstall'), {
|
||||
data: { version },
|
||||
onBefore: () => toast('Uninstalling PHP ' + version + '...'),
|
||||
onSuccess: () => {
|
||||
toast.success('PHP ' + version + ' uninstalled successfully');
|
||||
fetchPhpVersions();
|
||||
},
|
||||
onError: () => toast.error('Failed to uninstall PHP ' + version),
|
||||
});
|
||||
};
|
||||
|
||||
const toggleService = (version, currentEnabled) => {
|
||||
const enabled = !currentEnabled;
|
||||
const action = enabled ? 'enable' : 'disable';
|
||||
|
||||
router.post(route('php.service.toggle'),
|
||||
{ version, enabled },
|
||||
{
|
||||
onBefore: () => toast(`${action === 'enable' ? 'Enabling' : 'Disabling'} PHP ${version}-FPM...`),
|
||||
onSuccess: () => {
|
||||
toast.success(`PHP ${version}-FPM ${action}d successfully`);
|
||||
fetchPhpVersions();
|
||||
},
|
||||
onError: () => toast.error(`Failed to ${action} PHP ${version}-FPM`),
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const restartService = (version) => {
|
||||
router.post(route('php.service.restart'),
|
||||
{ version },
|
||||
{
|
||||
onBefore: () => toast('Restarting PHP ' + version + '-FPM...'),
|
||||
onSuccess: () => {
|
||||
toast.success('PHP ' + version + '-FPM restarted successfully');
|
||||
fetchPhpVersions();
|
||||
},
|
||||
onError: () => toast.error('Failed to restart PHP ' + version + '-FPM'),
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout
|
||||
header={
|
||||
<div className="flex flex-col xl:flex-row xl:justify-between max-w-7xl pr-5">
|
||||
<h2 className="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight flex items-center">
|
||||
<TbBrandPhp className='mr-2' />
|
||||
PHP Versions
|
||||
</h2>
|
||||
<InstallPHPForm />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Head title="PHP Versions" />
|
||||
|
||||
<div className="max-w-7xl px-4 my-8">
|
||||
{loading ? (
|
||||
<div className="text-center py-8 text-gray-600 dark:text-gray-400">
|
||||
Loading PHP versions...
|
||||
</div>
|
||||
) : (
|
||||
<div className="relative overflow-x-auto bg-white dark:bg-gray-850 mt-3">
|
||||
<table className="w-full text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
||||
<thead className="text-gray-700 uppercase bg-gray-200 dark:bg-gray-700 dark:text-gray-300 text-sm">
|
||||
<tr>
|
||||
<th className="px-6 py-3">Version</th>
|
||||
<th className="px-6 py-3">Status</th>
|
||||
<th className="px-6 py-3">Memory</th>
|
||||
<th className="px-6 py-3">CPU Time</th>
|
||||
<th className="px-6 py-3">Uptime</th>
|
||||
<th className="px-6 py-3">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-sm">
|
||||
{phpVersions.length === 0 ? (
|
||||
<tr>
|
||||
<td colSpan="6" className="px-6 py-8 text-center text-gray-500 dark:text-gray-400">
|
||||
No PHP versions installed
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
phpVersions.map((php, index) => {
|
||||
const stats = liveStats[php.version] || {};
|
||||
return (
|
||||
<tr key={`php-${index}`} className="bg-white border-b text-gray-700 dark:text-gray-200 dark:bg-gray-850 dark:border-gray-700 border-gray-200">
|
||||
<td className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
|
||||
<div className="flex items-center">
|
||||
<TbBrandPhp className="w-5 h-5 mr-2 text-blue-600" />
|
||||
PHP {php.version}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
|
||||
<div className={`inline-flex items-center px-3 py-1 rounded-md text-sm font-medium ${php.status === 'active'
|
||||
? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'
|
||||
: 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200'
|
||||
}`}>
|
||||
{php.status === 'active' ? 'Active' : 'Inactive'}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
|
||||
{stats.memory || '--'}
|
||||
</td>
|
||||
<td className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
|
||||
{stats.cpuTime || '--'}
|
||||
</td>
|
||||
<td className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
|
||||
{stats.uptime || '--'}
|
||||
</td>
|
||||
<td className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
|
||||
<div className='flex items-center space-x-2'>
|
||||
<ConfirmationButton doAction={() => toggleService(php.version, php.enabled)}>
|
||||
<button
|
||||
className={`p-2 rounded-lg transition-colors ${php.enabled
|
||||
? 'bg-green-100 hover:bg-green-200 text-green-600 dark:bg-green-900 dark:hover:bg-green-800 dark:text-green-300'
|
||||
: 'bg-gray-100 hover:bg-gray-200 text-gray-600 dark:bg-gray-800 dark:hover:bg-gray-700 dark:text-gray-400'
|
||||
}`}
|
||||
title={php.enabled ? 'Disable Service' : 'Enable Service'}
|
||||
>
|
||||
{php.enabled ? (
|
||||
<FaToggleOn className='w-5 h-5' />
|
||||
) : (
|
||||
<FaToggleOff className='w-5 h-5' />
|
||||
)}
|
||||
</button>
|
||||
</ConfirmationButton>
|
||||
|
||||
<ConfirmationButton doAction={() => restartService(php.version)}>
|
||||
<button
|
||||
className="p-2 rounded-lg bg-blue-100 hover:bg-blue-200 text-blue-600 dark:bg-blue-900 dark:hover:bg-blue-800 dark:text-blue-300 transition-colors"
|
||||
title="Restart Service"
|
||||
>
|
||||
<FaSync className='w-4 h-4' />
|
||||
</button>
|
||||
</ConfirmationButton>
|
||||
|
||||
<ConfirmationButton doAction={() => uninstallPhp(php.version)}>
|
||||
<TiDelete className='w-6 h-6 text-red-500' />
|
||||
</ConfirmationButton>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</AuthenticatedLayout>
|
||||
);
|
||||
}
|
||||
92
resources/js/Pages/PHP/Partials/InstallPHPForm.jsx
Normal file
92
resources/js/Pages/PHP/Partials/InstallPHPForm.jsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import { useState } from 'react';
|
||||
import Modal from '@/Components/Modal';
|
||||
import PrimaryButton from '@/Components/PrimaryButton';
|
||||
import SecondaryButton from '@/Components/SecondaryButton';
|
||||
import { router } from '@inertiajs/react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { TbBrandPhp } from 'react-icons/tb';
|
||||
|
||||
export default function InstallPHPForm() {
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [version, setVersion] = useState('');
|
||||
const [isInstalling, setIsInstalling] = useState(false);
|
||||
|
||||
const availableVersions = ['8.4', '8.3', '8.2', '8.1', '8.0', '7.4'];
|
||||
|
||||
const handleInstall = () => {
|
||||
if (!version) {
|
||||
toast.error('Please select a PHP version');
|
||||
return;
|
||||
}
|
||||
|
||||
setIsInstalling(true);
|
||||
|
||||
router.post(route('php.install'),
|
||||
{ version },
|
||||
{
|
||||
onBefore: () => toast('Installing PHP ' + version + '...'),
|
||||
onSuccess: () => {
|
||||
toast.success('PHP ' + version + ' installed successfully');
|
||||
setShowModal(false);
|
||||
setVersion('');
|
||||
router.reload();
|
||||
},
|
||||
onError: (errors) => {
|
||||
toast.error('Failed to install PHP ' + version);
|
||||
console.error(errors);
|
||||
},
|
||||
onFinish: () => setIsInstalling(false),
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<PrimaryButton onClick={() => setShowModal(true)}>
|
||||
<TbBrandPhp className="mr-2" />
|
||||
Install New Version
|
||||
</PrimaryButton>
|
||||
|
||||
<Modal show={showModal} onClose={() => !isInstalling && setShowModal(false)}>
|
||||
<div className="p-6">
|
||||
<h2 className="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
Install PHP Version
|
||||
</h2>
|
||||
|
||||
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||
Select a PHP version to install. This will install PHP-FPM and common extensions.
|
||||
</p>
|
||||
|
||||
<div className="mt-6">
|
||||
<label htmlFor="php-version" className="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
PHP Version
|
||||
</label>
|
||||
<select
|
||||
id="php-version"
|
||||
value={version}
|
||||
onChange={(e) => setVersion(e.target.value)}
|
||||
disabled={isInstalling}
|
||||
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-white sm:text-sm"
|
||||
>
|
||||
<option value="">Select a version</option>
|
||||
{availableVersions.map((v) => (
|
||||
<option key={v} value={v}>
|
||||
PHP {v}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 flex justify-end space-x-3">
|
||||
<SecondaryButton onClick={() => setShowModal(false)} disabled={isInstalling}>
|
||||
Cancel
|
||||
</SecondaryButton>
|
||||
<PrimaryButton onClick={handleInstall} disabled={isInstalling || !version}>
|
||||
{isInstalling ? 'Installing...' : 'Install'}
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -35,7 +35,15 @@ Route::post('/websites/{website}/ssl/toggle', [WebsiteController::class, 'toggle
|
||||
Route::get('/websites/{website}/ssl/status', [WebsiteController::class, 'checkSslStatus'])->middleware(['auth'])->name('websites.ssl.status');
|
||||
|
||||
// PHP FPM Pools [Admin | User]
|
||||
Route::get('/php', [PHPManagerController::class, 'index'])->middleware(['auth', AdminMiddleware::class])->name('php.index');
|
||||
Route::get('/php/get-versions', [PHPManagerController::class, 'getVersions'])->middleware(['auth'])->name('php.get-versions');
|
||||
Route::get('/php/list', [PHPManagerController::class, 'list'])->middleware(['auth', AdminMiddleware::class])->name('php.list');
|
||||
Route::post('/php/install', [PHPManagerController::class, 'install'])->middleware(['auth', AdminMiddleware::class])->name('php.install');
|
||||
Route::delete('/php/uninstall', [PHPManagerController::class, 'uninstall'])->middleware(['auth', AdminMiddleware::class])->name('php.uninstall');
|
||||
Route::post('/php/service/toggle', [PHPManagerController::class, 'toggleService'])->middleware(['auth', AdminMiddleware::class])->name('php.service.toggle');
|
||||
Route::post('/php/service/restart', [PHPManagerController::class, 'restartService'])->middleware(['auth', AdminMiddleware::class])->name('php.service.restart');
|
||||
|
||||
|
||||
|
||||
// MySQL management [Admin | User]
|
||||
Route::get('/mysql', [MysqlController::class, 'index'])->middleware(['auth'])->name('mysql.index');
|
||||
|
||||
Reference in New Issue
Block a user