Backup
This commit is contained in:
parent
77c9c733ae
commit
261cc92b19
@ -59,7 +59,13 @@ class App
|
|||||||
$tabContainer = new TabContainer('flex-1');
|
$tabContainer = new TabContainer('flex-1');
|
||||||
|
|
||||||
// Create tabs
|
// 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);
|
$sftpManagerTab = new SftpManagerTab($currentApiKey, $currentPrivateKeyPath, $currentRemoteStartDir, $serverListTab, $tabContainer, $statusLabel);
|
||||||
|
|
||||||
// Add tabs
|
// Add tabs
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
namespace ServerManager\UI;
|
namespace ServerManager\UI;
|
||||||
|
|
||||||
use PHPNative\Async\TaskManager;
|
use PHPNative\Async\TaskManager;
|
||||||
|
use PHPNative\Framework\Settings;
|
||||||
use PHPNative\Tailwind\Data\Icon as IconName;
|
use PHPNative\Tailwind\Data\Icon as IconName;
|
||||||
use PHPNative\Ui\Widget\Button;
|
use PHPNative\Ui\Widget\Button;
|
||||||
use PHPNative\Ui\Widget\Checkbox;
|
use PHPNative\Ui\Widget\Checkbox;
|
||||||
@ -17,6 +18,7 @@ use ServerManager\UI\LoadingIndicator;
|
|||||||
|
|
||||||
class ServerListTab
|
class ServerListTab
|
||||||
{
|
{
|
||||||
|
private Settings $settings;
|
||||||
private Container $tab;
|
private Container $tab;
|
||||||
private Table $table;
|
private Table $table;
|
||||||
private TextInput $searchInput;
|
private TextInput $searchInput;
|
||||||
@ -35,13 +37,20 @@ class ServerListTab
|
|||||||
private Label $detailIpv4;
|
private Label $detailIpv4;
|
||||||
private Container $detailDomainsContainer;
|
private Container $detailDomainsContainer;
|
||||||
private LoadingIndicator $loadingIndicator;
|
private LoadingIndicator $loadingIndicator;
|
||||||
|
private TextInput $serverApiKeyInput;
|
||||||
|
private Container $todoListContainer;
|
||||||
|
private TextInput $todoInput;
|
||||||
|
private array $currentServerTodos = [];
|
||||||
|
private null|int $currentServerId = null;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string &$apiKey,
|
string &$apiKey,
|
||||||
string &$privateKeyPath,
|
string &$privateKeyPath,
|
||||||
TabContainer $tabContainer,
|
TabContainer $tabContainer,
|
||||||
Label $statusLabel,
|
Label $statusLabel,
|
||||||
|
Settings $settings,
|
||||||
) {
|
) {
|
||||||
|
$this->settings = $settings;
|
||||||
$this->statusLabel = $statusLabel;
|
$this->statusLabel = $statusLabel;
|
||||||
$currentApiKey = &$apiKey;
|
$currentApiKey = &$apiKey;
|
||||||
$currentPrivateKeyPath = &$privateKeyPath;
|
$currentPrivateKeyPath = &$privateKeyPath;
|
||||||
@ -222,11 +231,53 @@ class ServerListTab
|
|||||||
|
|
||||||
$detailPanel->addComponent($this->sshTerminalButton);
|
$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($leftSide);
|
||||||
$this->tab->addComponent($detailPanel);
|
$this->tab->addComponent($detailPanel);
|
||||||
|
|
||||||
// Setup event handlers
|
// Setup event handlers
|
||||||
$this->setupEventHandlers($currentApiKey, $currentPrivateKeyPath, $rebootButton, $updateButton);
|
$this->setupEventHandlers(
|
||||||
|
$currentApiKey,
|
||||||
|
$currentPrivateKeyPath,
|
||||||
|
$rebootButton,
|
||||||
|
$updateButton,
|
||||||
|
$saveServerSettingsButton,
|
||||||
|
$addTodoButton,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setupEventHandlers(
|
private function setupEventHandlers(
|
||||||
@ -234,6 +285,8 @@ class ServerListTab
|
|||||||
string &$currentPrivateKeyPath,
|
string &$currentPrivateKeyPath,
|
||||||
Button $rebootButton,
|
Button $rebootButton,
|
||||||
Button $updateButton,
|
Button $updateButton,
|
||||||
|
Button $saveServerSettingsButton,
|
||||||
|
Button $addTodoButton,
|
||||||
): void {
|
): void {
|
||||||
// Table row selection
|
// Table row selection
|
||||||
$serverListTab = $this;
|
$serverListTab = $this;
|
||||||
@ -247,6 +300,24 @@ class ServerListTab
|
|||||||
$serverListTab->detailType->setText($row['type']);
|
$serverListTab->detailType->setText($row['type']);
|
||||||
$serverListTab->detailIpv4->setText($row['ipv4']);
|
$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'] ?? [];
|
$domains = $row['domains'] ?? [];
|
||||||
$serverListTab->updateDomainDetails(is_array($domains) ? $domains : []);
|
$serverListTab->updateDomainDetails(is_array($domains) ? $domains : []);
|
||||||
|
|
||||||
@ -315,14 +386,20 @@ class ServerListTab
|
|||||||
echo "Error: {$result['error']}\n";
|
echo "Error: {$result['error']}\n";
|
||||||
} elseif (isset($result['success'], $result['servers'])) {
|
} elseif (isset($result['success'], $result['servers'])) {
|
||||||
// Basisdaten setzen, Docker-Status initial auf "pending"
|
// Basisdaten setzen, Docker-Status initial auf "pending"
|
||||||
$serverListTab->currentServerData = array_map(static fn($row) => array_merge([
|
$serverListTab->currentServerData = array_map(
|
||||||
|
static fn($row) => array_merge(
|
||||||
|
[
|
||||||
'docker_status' => 'pending',
|
'docker_status' => 'pending',
|
||||||
'docker' => null,
|
'docker' => null,
|
||||||
'docker_error' => null,
|
'docker_error' => null,
|
||||||
'needs_reboot' => 'unbekannt',
|
'needs_reboot' => 'unbekannt',
|
||||||
'updates_available' => 'unbekannt',
|
'updates_available' => 'unbekannt',
|
||||||
'os_version' => 'unbekannt',
|
'os_version' => 'unbekannt',
|
||||||
], $row), $result['servers']);
|
],
|
||||||
|
$row,
|
||||||
|
),
|
||||||
|
$result['servers'],
|
||||||
|
);
|
||||||
|
|
||||||
$serverListTab->table->setData($serverListTab->currentServerData, false);
|
$serverListTab->table->setData($serverListTab->currentServerData, false);
|
||||||
$serverListTab->statusLabel->setText('Server geladen: ' . $result['count'] . ' gefunden');
|
$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
|
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
|
public function renderSelectCell(array $rowData, int $rowIndex): Checkbox
|
||||||
{
|
{
|
||||||
$isChecked = (bool) ($rowData['selected'] ?? false);
|
$isChecked = (bool) ($rowData['selected'] ?? false);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user