This commit is contained in:
Thomas Peterson 2025-11-17 22:10:39 +01:00
parent 77c9c733ae
commit 261cc92b19
2 changed files with 167 additions and 10 deletions

View File

@ -59,7 +59,13 @@ class App
$tabContainer = new TabContainer('flex-1');
// Create tabs
$serverListTab = new ServerListTab($currentApiKey, $currentPrivateKeyPath, $tabContainer, $statusLabel);
$serverListTab = new ServerListTab(
$currentApiKey,
$currentPrivateKeyPath,
$tabContainer,
$statusLabel,
$this->settings,
);
$sftpManagerTab = new SftpManagerTab($currentApiKey, $currentPrivateKeyPath, $currentRemoteStartDir, $serverListTab, $tabContainer, $statusLabel);
// Add tabs

View File

@ -3,6 +3,7 @@
namespace ServerManager\UI;
use PHPNative\Async\TaskManager;
use PHPNative\Framework\Settings;
use PHPNative\Tailwind\Data\Icon as IconName;
use PHPNative\Ui\Widget\Button;
use PHPNative\Ui\Widget\Checkbox;
@ -17,6 +18,7 @@ use ServerManager\UI\LoadingIndicator;
class ServerListTab
{
private Settings $settings;
private Container $tab;
private Table $table;
private TextInput $searchInput;
@ -35,13 +37,20 @@ class ServerListTab
private Label $detailIpv4;
private Container $detailDomainsContainer;
private LoadingIndicator $loadingIndicator;
private TextInput $serverApiKeyInput;
private Container $todoListContainer;
private TextInput $todoInput;
private array $currentServerTodos = [];
private null|int $currentServerId = null;
public function __construct(
string &$apiKey,
string &$privateKeyPath,
TabContainer $tabContainer,
Label $statusLabel,
Settings $settings,
) {
$this->settings = $settings;
$this->statusLabel = $statusLabel;
$currentApiKey = &$apiKey;
$currentPrivateKeyPath = &$privateKeyPath;
@ -222,11 +231,53 @@ class ServerListTab
$detailPanel->addComponent($this->sshTerminalButton);
// Per-server API key and TODOs
$detailPanel->addComponent(new Label('Server API Key:', 'text-xs text-gray-500 mt-2'));
$this->serverApiKeyInput = new TextInput(
'Server API Key',
'w-full border border-gray-300 rounded px-3 py-2 bg-white text-black',
);
$detailPanel->addComponent($this->serverApiKeyInput);
$saveServerSettingsButton = new Button(
'Server-Einstellungen speichern',
'mt-1 px-3 py-2 bg-green-600 rounded hover:bg-green-700',
null,
'text-white',
);
$detailPanel->addComponent($saveServerSettingsButton);
$detailPanel->addComponent(new Label('TODOs für diesen Server:', 'text-xs text-gray-500 mt-3'));
$this->todoListContainer = new Container('flex flex-col gap-1');
$detailPanel->addComponent($this->todoListContainer);
$todoInputRow = new Container('flex flex-row gap-2 mt-1');
$this->todoInput = new TextInput(
'Neue TODO...',
'flex-1 border border-gray-300 rounded px-3 py-2 bg-white text-black',
);
$addTodoButton = new Button(
'+',
'px-3 py-2 bg-blue-600 rounded hover:bg-blue-700',
null,
'text-white',
);
$todoInputRow->addComponent($this->todoInput);
$todoInputRow->addComponent($addTodoButton);
$detailPanel->addComponent($todoInputRow);
$this->tab->addComponent($leftSide);
$this->tab->addComponent($detailPanel);
// Setup event handlers
$this->setupEventHandlers($currentApiKey, $currentPrivateKeyPath, $rebootButton, $updateButton);
$this->setupEventHandlers(
$currentApiKey,
$currentPrivateKeyPath,
$rebootButton,
$updateButton,
$saveServerSettingsButton,
$addTodoButton,
);
}
private function setupEventHandlers(
@ -234,6 +285,8 @@ class ServerListTab
string &$currentPrivateKeyPath,
Button $rebootButton,
Button $updateButton,
Button $saveServerSettingsButton,
Button $addTodoButton,
): void {
// Table row selection
$serverListTab = $this;
@ -247,6 +300,24 @@ class ServerListTab
$serverListTab->detailType->setText($row['type']);
$serverListTab->detailIpv4->setText($row['ipv4']);
// Load per-server settings (API key, todos)
$serverId = $row['id'] ?? null;
$serverListTab->currentServerId = is_numeric($serverId) ? (int) $serverId : null;
if ($serverListTab->currentServerId !== null) {
$settingsKeyBase = 'servers.' . $serverListTab->currentServerId;
$apiKey = $serverListTab->settings->get($settingsKeyBase . '.api_key', '');
$todos = $serverListTab->settings->get($settingsKeyBase . '.todos', []);
$serverListTab->serverApiKeyInput->setValue($apiKey);
$serverListTab->currentServerTodos = is_array($todos) ? $todos : [];
$serverListTab->renderTodoList();
} else {
$serverListTab->serverApiKeyInput->setValue('');
$serverListTab->currentServerTodos = [];
$serverListTab->renderTodoList();
}
$domains = $row['domains'] ?? [];
$serverListTab->updateDomainDetails(is_array($domains) ? $domains : []);
@ -315,14 +386,20 @@ class ServerListTab
echo "Error: {$result['error']}\n";
} elseif (isset($result['success'], $result['servers'])) {
// Basisdaten setzen, Docker-Status initial auf "pending"
$serverListTab->currentServerData = array_map(static fn($row) => array_merge([
'docker_status' => 'pending',
'docker' => null,
'docker_error' => null,
'needs_reboot' => 'unbekannt',
'updates_available' => 'unbekannt',
'os_version' => 'unbekannt',
], $row), $result['servers']);
$serverListTab->currentServerData = array_map(
static fn($row) => array_merge(
[
'docker_status' => 'pending',
'docker' => null,
'docker_error' => null,
'needs_reboot' => 'unbekannt',
'updates_available' => 'unbekannt',
'os_version' => 'unbekannt',
],
$row,
),
$result['servers'],
);
$serverListTab->table->setData($serverListTab->currentServerData, false);
$serverListTab->statusLabel->setText('Server geladen: ' . $result['count'] . ' gefunden');
@ -695,6 +772,42 @@ class ServerListTab
});
}
});
// Save per-server settings (API key + todos)
$saveServerSettingsButton->setOnClick(function () use ($serverListTab) {
if ($serverListTab->currentServerId === null) {
$serverListTab->statusLabel->setText('Kein Server für das Speichern ausgewählt');
return;
}
$settingsKeyBase = 'servers.' . $serverListTab->currentServerId;
$apiKey = trim($serverListTab->serverApiKeyInput->getValue());
$serverListTab->settings->set($settingsKeyBase . '.api_key', $apiKey);
$serverListTab->settings->set($settingsKeyBase . '.todos', $serverListTab->currentServerTodos);
$serverListTab->settings->save();
$serverListTab->statusLabel->setText(
'Server-Einstellungen gespeichert für Server #' . $serverListTab->currentServerId,
);
});
// Add TODO for current server
$addTodoButton->setOnClick(function () use ($serverListTab) {
if ($serverListTab->currentServerId === null) {
$serverListTab->statusLabel->setText('Kein Server für TODO ausgewählt');
return;
}
$text = trim($serverListTab->todoInput->getValue());
if ($text === '') {
return;
}
$serverListTab->currentServerTodos[] = $text;
$serverListTab->todoInput->setValue('');
$serverListTab->renderTodoList();
});
}
public function getContainer(): Container
@ -778,6 +891,44 @@ class ServerListTab
}
}
private function renderTodoList(): void
{
$this->todoListContainer->clearChildren();
if (empty($this->currentServerTodos)) {
$this->todoListContainer->addComponent(
new Label('Keine TODOs', 'text-xs text-gray-500 italic'),
);
return;
}
foreach ($this->currentServerTodos as $index => $todo) {
$row = new Container('flex flex-row items-center gap-2');
$row->addComponent(new Label('- ' . $todo, 'text-xs text-gray-800 flex-1'));
$removeButton = new Button(
'x',
'px-2 py-1 bg-red-500 rounded hover:bg-red-600',
null,
'text-white text-xs',
);
$serverListTab = $this;
$removeButton->setOnClick(function () use ($serverListTab, $index) {
if (!isset($serverListTab->currentServerTodos[$index])) {
return;
}
unset($serverListTab->currentServerTodos[$index]);
$serverListTab->currentServerTodos = array_values($serverListTab->currentServerTodos);
$serverListTab->renderTodoList();
});
$row->addComponent($removeButton);
$this->todoListContainer->addComponent($row);
}
}
public function renderSelectCell(array $rowData, int $rowIndex): Checkbox
{
$isChecked = (bool) ($rowData['selected'] ?? false);