From b7b36b135582b7f95e3d983318a757b67edf51bd Mon Sep 17 00:00:00 2001 From: "Wiktor A. Falkowski" Date: Tue, 20 Oct 2026 17:17:00 +0000 Subject: [PATCH] fix(admin): repair management views and harden plugin handling --- src/features/admin/AdminSection.jsx | 25 ++++---- src/features/admin/NodeTerminalModal.jsx | 63 +++++++++++++-------- src/features/plugins/PluginDetails.jsx | 11 ++-- src/features/servers/ServerDetailsModal.jsx | 22 +++++-- src/index.css | 7 +++ src/pages/AdminPage.jsx | 12 ++-- src/pages/DashboardPage.jsx | 2 +- 7 files changed, 92 insertions(+), 50 deletions(-) diff --git a/src/features/admin/AdminSection.jsx b/src/features/admin/AdminSection.jsx index ed3cc95..d05dfc7 100644 --- a/src/features/admin/AdminSection.jsx +++ b/src/features/admin/AdminSection.jsx @@ -145,7 +145,7 @@ const AdminSection = ({ user, activeTab: parentActiveTab, showAlert }) => { demo_servers_enabled: Boolean(data.settings.demo_servers_enabled), new_user_credits: parseInt(data.settings.new_user_credits, 10) || 0 }); - showAlert('Success', 'Panel settings updated successfully', 'success'); + showAlert('Settings saved', 'The panel settings are now active.', 'success'); } else { showAlert('Error', data.error || 'Failed to update panel settings', 'error'); } @@ -216,7 +216,7 @@ const AdminSection = ({ user, activeTab: parentActiveTab, showAlert }) => { } } - showAlert('Success', `Pricing updated successfully${postNotice ? ' and announcement posted' : ''}`, 'success'); + showAlert('Pricing saved', `New prices are active${postNotice ? ', and the announcement is posted.' : '.'}`, 'success'); setPostNotice(false); // Reset checkbox } else { showAlert('Error', data.error || 'Failed to update pricing', 'error'); @@ -529,7 +529,7 @@ const AdminSection = ({ user, activeTab: parentActiveTab, showAlert }) => { if (selectedUser?.id === userId) { setSelectedUser(prev => ({ ...prev, role: isBanned ? 'user' : 'banned' })); } - showAlert('Success', `User ${isBanned ? 'unbanned' : 'banned'} successfully`, 'success'); + showAlert('User access updated', `This account is ${isBanned ? 'active' : 'suspended'}.`, 'success'); } else { showAlert('Error', data.error || 'Operation failed', 'error'); } @@ -551,7 +551,7 @@ const AdminSection = ({ user, activeTab: parentActiveTab, showAlert }) => { }); const data = await response.json(); if (data.success) { - showAlert('Success', 'User deleted successfully', 'success'); + showAlert('User deleted', 'The account has been removed.', 'success'); fetchUsers(); setSelectedUser(null); } else { @@ -579,7 +579,7 @@ const AdminSection = ({ user, activeTab: parentActiveTab, showAlert }) => { }); const data = await response.json(); if (data.success) { - showAlert('Success', 'Password reset successfully', 'success'); + showAlert('Password reset', 'The new password is ready to use.', 'success'); setNewPassword(''); } else { showAlert('Error', data.error || 'Failed to reset password', 'error'); @@ -604,7 +604,7 @@ const AdminSection = ({ user, activeTab: parentActiveTab, showAlert }) => { }); const data = await response.json(); if (data.success) { - showAlert('Success', '2FA disabled successfully', 'success'); + showAlert('Two-factor authentication disabled', 'The user can sign in without a verification code.', 'success'); // Update local state to reflect change (optional, depends if we get data back) } else { showAlert('Error', data.error || 'Failed to disable 2FA', 'error'); @@ -639,7 +639,7 @@ const AdminSection = ({ user, activeTab: parentActiveTab, showAlert }) => { )); setSelectedUser(prev => ({ ...prev, credits: data.new_credits })); setCreditAmount(''); - showAlert('Success', 'Credits updated successfully', 'success'); + showAlert('Credits updated', 'The new balance is available to the user.', 'success'); fetchUserHistory(selectedUser.id); // Refresh history } else { showAlert('Error', data.error || 'Failed to update credits', 'error'); @@ -832,20 +832,25 @@ const AdminSection = ({ user, activeTab: parentActiveTab, showAlert }) => { +

+ Review every server across user accounts. Select a server to open its controls, or refresh the list to check for recent changes. +

+
{isLoadingAllServers ? ( ) : allServers.length === 0 ? ( -
+
-

No servers found in the system.

+

No servers to manage

+

Servers appear here after an account creates one.

) : (
{allServers.map(server => (
diff --git a/src/features/admin/NodeTerminalModal.jsx b/src/features/admin/NodeTerminalModal.jsx index 1b462d4..eb829de 100644 --- a/src/features/admin/NodeTerminalModal.jsx +++ b/src/features/admin/NodeTerminalModal.jsx @@ -26,7 +26,6 @@ const NodeTerminalModal = ({ node, onClose }) => { const [isFullscreen, setIsFullscreen] = useState(false); const [copied, setCopied] = useState(false); const outputRef = useRef(null); - const inputRef = useRef(null); const token = localStorage.getItem('anchorhost_token'); const { @@ -113,35 +112,47 @@ const NodeTerminalModal = ({ node, onClose }) => { const handleKeyDown = (e) => { if (!isConnected) return; if (e.key === 'Enter') { + e.preventDefault(); handleTerminalInput('\r'); } else if (e.key === 'Backspace') { + e.preventDefault(); handleTerminalInput('\b'); } else if (e.key === 'Tab') { e.preventDefault(); handleTerminalInput('\t'); } else if (e.key === 'Escape') { + e.preventDefault(); handleTerminalInput('\x1b'); - } else if (e.ctrlKey && e.key === 'c') { + } else if (e.ctrlKey && e.key.toLowerCase() === 'c') { + e.preventDefault(); handleTerminalInput('\x03'); - } else if (e.ctrlKey && e.key === 'd') { + } else if (e.ctrlKey && e.key.toLowerCase() === 'd') { + e.preventDefault(); handleTerminalInput('\x04'); - } else if (e.ctrlKey && e.key === 'l') { + } else if (e.ctrlKey && e.key.toLowerCase() === 'l') { + e.preventDefault(); setTerminalOutput(''); handleTerminalInput('\x0c'); } else if (e.key === 'ArrowUp') { + e.preventDefault(); handleTerminalInput('\x1b[A'); } else if (e.key === 'ArrowDown') { + e.preventDefault(); handleTerminalInput('\x1b[B'); } else if (e.key === 'ArrowRight') { + e.preventDefault(); handleTerminalInput('\x1b[C'); } else if (e.key === 'ArrowLeft') { + e.preventDefault(); handleTerminalInput('\x1b[D'); - } - }; - - const handleKeyPress = (e) => { - if (!isConnected) return; - if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) { + } else if (e.key === 'Home') { + e.preventDefault(); + handleTerminalInput('\x1b[H'); + } else if (e.key === 'End') { + e.preventDefault(); + handleTerminalInput('\x1b[F'); + } else if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) { + e.preventDefault(); handleTerminalInput(e.key); } }; @@ -199,24 +210,24 @@ const NodeTerminalModal = ({ node, onClose }) => { }; const modalContent = ( -
+
{/* Header */} -
+
-
+

- Node Shell: {node.name} + Host terminal ยท {node.name}

- {
- {server.ports && server.ports.map((port, idx) => ( + {serverPorts.map((port, idx) => (
@@ -953,7 +965,7 @@ const ServerDetailsModal = ({ server, onClose, onServerAction, showAlert }) => { - {server.ports && server.ports.map((port, idx) => ( + {serverPorts.map((port, idx) => (
@@ -1000,7 +1012,7 @@ const ServerDetailsModal = ({ server, onClose, onServerAction, showAlert }) => { ))} - {(!server.ports || server.ports.length === 0) && ( + {serverPorts.length === 0 && (

No network mappings active

diff --git a/src/index.css b/src/index.css index 1698253..be4d1e1 100644 --- a/src/index.css +++ b/src/index.css @@ -453,8 +453,15 @@ body > div:not(#root) [class*="rounded-"] { border-radius: 2px !important; } body > div:not(#root) :not(button):not(a)[class*="shadow-"]:not(.shadow-none) { box-shadow: var(--ah-shadow) !important; } body > div:not(#root) :is(button, a)[class*="shadow-"] { box-shadow: none !important; transform: none !important; } body > div:not(#root) [class*="backdrop-blur"] { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; } +body > div:not(#root) [class*="bg-dash-surfaceElevated/"] { background-color: var(--ah-panel) !important; } body > div:not(#root) :is(button, a, input, textarea, select):focus-visible { outline: 2px solid var(--ah-accent); outline-offset: 2px; } .dashboard-app, .admin-app { background: var(--ah-background) !important; color: var(--ah-text); } +.admin-app [class*="backdrop-blur"] { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; } +.admin-app [class*="rounded-"] { border-radius: 2px !important; } +.admin-app :not(button):not(a)[class*="shadow-"]:not(.shadow-none) { box-shadow: var(--ah-shadow) !important; } +.admin-app [class*="hover:scale"] { transform: none !important; } +.admin-app :is(button, a, input, textarea, select) { border-radius: 2px; } +.admin-app :is(button, a, input, textarea, select):focus-visible { outline: 2px solid var(--ah-accent); outline-offset: 2px; } .dashboard-app .bg-dash-surface, .admin-app .bg-dash-surface { background-color: var(--ah-surface); } .dashboard-app .bg-dash-surfaceElevated, .admin-app .bg-dash-surfaceElevated { background-color: var(--ah-panel); } .dashboard-app .border-dash-border, .admin-app .border-dash-border { border-color: var(--ah-border); } diff --git a/src/pages/AdminPage.jsx b/src/pages/AdminPage.jsx index 39cc6ab..14360fc 100644 --- a/src/pages/AdminPage.jsx +++ b/src/pages/AdminPage.jsx @@ -123,7 +123,7 @@ const AdminPage = () => {
{/* Sidebar */}