From b07058f742a44a68f969b6331fa6a6acde825ef6 Mon Sep 17 00:00:00 2001 From: Thomas Peterson Date: Mon, 17 Nov 2025 10:20:51 +0100 Subject: [PATCH] Backup --- .../ServerManager/UI/LoadingIndicator.php | 44 +++++++++++++++++ examples/ServerManager/UI/ServerListTab.php | 48 +++++++++++++------ 2 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 examples/ServerManager/UI/LoadingIndicator.php diff --git a/examples/ServerManager/UI/LoadingIndicator.php b/examples/ServerManager/UI/LoadingIndicator.php new file mode 100644 index 0000000..5e43291 --- /dev/null +++ b/examples/ServerManager/UI/LoadingIndicator.php @@ -0,0 +1,44 @@ +icon = new Icon(IconName::sync, 14, 'text-blue-600'); + $this->label = new Label('Laden...', 'text-xs text-gray-700'); + + $this->addComponent($this->icon); + $this->addComponent($this->label); + + $this->setVisible(false); + } + + public function setLoading(bool $loading): void + { + if ($this->loading === $loading) { + return; + } + + $this->loading = $loading; + $this->setVisible($loading); + } + + public function isLoading(): bool + { + return $this->loading; + } +} + diff --git a/examples/ServerManager/UI/ServerListTab.php b/examples/ServerManager/UI/ServerListTab.php index a63baa9..8f848ba 100644 --- a/examples/ServerManager/UI/ServerListTab.php +++ b/examples/ServerManager/UI/ServerListTab.php @@ -12,6 +12,7 @@ use PHPNative\Ui\Widget\TabContainer; use PHPNative\Ui\Widget\Table; use PHPNative\Ui\Widget\TextInput; use ServerManager\Services\HetznerService; +use ServerManager\UI\LoadingIndicator; class ServerListTab { @@ -32,6 +33,7 @@ class ServerListTab private Label $detailType; private Label $detailIpv4; private Container $detailDomainsContainer; + private LoadingIndicator $loadingIndicator; public function __construct( string &$apiKey, @@ -49,6 +51,9 @@ class ServerListTab // Left side: Table with search and refresh $leftSide = new Container('flex flex-col gap-2 flex-1'); + // Header row with refresh button and loading indicator on the right + $headerRow = new Container('flex flex-row items-center gap-2'); + // Refresh button $this->refreshButton = new Button( 'Server aktualisieren', @@ -58,7 +63,13 @@ class ServerListTab ); $refreshIcon = new Icon(IconName::sync, 16, 'text-white'); $this->refreshButton->setIcon($refreshIcon); - $leftSide->addComponent($this->refreshButton); + $headerRow->addComponent($this->refreshButton); + + // Loading indicator (top-right in the server tab header) + $this->loadingIndicator = new LoadingIndicator('ml-auto'); + $headerRow->addComponent($this->loadingIndicator); + + $leftSide->addComponent($headerRow); // Search input $this->searchInput = new TextInput( @@ -222,9 +233,11 @@ class ServerListTab } }); - // Refresh button - use reference to apiKey & privateKey variable - $this->refreshButton->setOnClickAsync( - function () use (&$currentApiKey) { + // Refresh button - use TaskManager directly so we can control the loading indicator + $this->refreshButton->setOnClick(function () use (&$currentApiKey, $serverListTab, &$currentPrivateKeyPath) { + $serverListTab->loadingIndicator->setLoading(true); + + $task = TaskManager::getInstance()->runAsync(function () use (&$currentApiKey) { try { if (empty($currentApiKey)) { return ['error' => 'Kein API-Key konfiguriert']; @@ -253,8 +266,9 @@ class ServerListTab } catch (\Exception $e) { return ['error' => 'Exception: ' . $e->getMessage()]; } - }, - function ($result) use (&$serverListTab, &$currentPrivateKeyPath) { + }); + + $task->onComplete(function ($result) use (&$serverListTab, &$currentPrivateKeyPath) { if (is_array($result)) { if (isset($result['error'])) { $serverListTab->statusLabel->setText('Fehler: ' . $result['error']); @@ -275,12 +289,13 @@ class ServerListTab $ip = $row['ipv4'] ?? ''; if (empty($ip) || empty($currentPrivateKeyPath) || !file_exists($currentPrivateKeyPath)) { - $serverListTab->currentServerData[$index]['docker_error'] = 'Kein gültiger Private-Key oder IP'; + $serverListTab->currentServerData[$index]['docker_error'] = + 'Kein gültiger Private-Key oder IP'; $serverListTab->currentServerData[$index]['docker_status'] = 'error'; continue; } - $task = TaskManager::getInstance()->runAsync(function () use ( + $dockerTask = TaskManager::getInstance()->runAsync(function () use ( $ip, $currentPrivateKeyPath, $index, @@ -337,7 +352,7 @@ class ServerListTab } }); - $task->onComplete(function ($dockerResult) use (&$serverListTab) { + $dockerTask->onComplete(function ($dockerResult) use (&$serverListTab) { if (!is_array($dockerResult) || !isset($dockerResult['index'])) { return; } @@ -380,7 +395,7 @@ class ServerListTab } }); - $task->onError(function ($error) use ($serverListTab, $index) { + $dockerTask->onError(function ($error) use (&$serverListTab, $index) { $errorMsg = is_object($error) && method_exists($error, 'getMessage') ? $error->getMessage() : ((string) $error); @@ -392,15 +407,20 @@ class ServerListTab } } } - }, - function ($error) use (&$serverListTab) { + + $serverListTab->loadingIndicator->setLoading(false); + }); + + $task->onError(function ($error) use (&$serverListTab) { $errorMsg = is_object($error) && method_exists($error, 'getMessage') ? $error->getMessage() : ((string) $error); $serverListTab->statusLabel->setText('Async Fehler: ' . $errorMsg); echo "Async error: {$errorMsg}\n"; - }, - ); + + $serverListTab->loadingIndicator->setLoading(false); + }); + }); } public function getContainer(): Container