diff --git a/partials/landingpages/modules/setup.php b/partials/landingpages/modules/setup.php index da689c6..771f790 100644 --- a/partials/landingpages/modules/setup.php +++ b/partials/landingpages/modules/setup.php @@ -3,6 +3,8 @@ $moduleName = (string)($_GET['module'] ?? ''); $module = modules()->get($moduleName); $error = null; $notice = null; +$testGroup = null; +$dbTestMessages = []; require_admin(); @@ -176,14 +178,18 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $current = array_replace_recursive($current, $payload); - $testGroup = (string)($_POST['test_db'] ?? ''); - if ($testGroup !== '') { - if (!array_key_exists($testGroup, $dbGroups)) { + $postedTestGroup = (string)($_POST['test_db'] ?? ''); + if ($postedTestGroup !== '') { + $testGroup = $postedTestGroup; + if (!array_key_exists($postedTestGroup, $dbGroups)) { $error = 'Unbekannte Datenbank-Konfiguration.'; } else { - $dbConfig = $getNested($current, $testGroup); + $dbConfig = $getNested($current, $postedTestGroup); if (!is_array($dbConfig)) { - $error = 'Datenbank-Konfiguration ist unvollstaendig.'; + $dbTestMessages[$postedTestGroup] = [ + 'type' => 'error', + 'text' => 'Datenbank-Konfiguration ist unvollstaendig.', + ]; } else { try { $dbConfig['options'] = array_replace([ @@ -193,9 +199,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $testPdo = \App\Database::createFromArray($dbConfig); $testPdo->query('SELECT 1')->fetchColumn(); - $notice = $dbGroups[$testGroup] . ': Verbindung erfolgreich.'; + $dbTestMessages[$postedTestGroup] = [ + 'type' => 'success', + 'text' => 'Verbindung erfolgreich.', + ]; } catch (\Throwable $e) { - $error = $dbGroups[$testGroup] . ': Verbindung fehlgeschlagen. ' . $e->getMessage(); + $dbTestMessages[$postedTestGroup] = [ + 'type' => 'error', + 'text' => 'Verbindung fehlgeschlagen. ' . $e->getMessage(), + ]; } } } @@ -205,6 +217,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $module = modules()->get($moduleName) ?: $module; } } + +$activeDbGroup = $testGroup !== null && array_key_exists($testGroup, $dbGroups) + ? $testGroup + : (array_key_first($dbGroups) ?? ''); ?>
Setup
@@ -239,7 +255,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { -
+
Datenbanken @@ -249,12 +265,20 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$label): ?> - +
$label): ?> -
+
>
@@ -264,6 +288,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { Verbindung testen
+ +
+ +
+
diff --git a/public/assets/css/app.css b/public/assets/css/app.css index 85c632e..e35c46b 100644 --- a/public/assets/css/app.css +++ b/public/assets/css/app.css @@ -599,6 +599,11 @@ a { .setup-shell { display: grid; gap: 10px; + border: 1px solid var(--line); + border-radius: 8px; + background: color-mix(in srgb, var(--surface) 92%, transparent); + padding: 16px; + box-shadow: 0 10px 24px rgba(1, 22, 32, 0.06); } .setup-title { @@ -664,6 +669,38 @@ a { margin-bottom: 14px; } +.setup-tab { + cursor: pointer; +} + +.setup-tab.is-active { + border-color: var(--accent); + background: color-mix(in srgb, var(--accent) 14%, var(--surface)); + color: var(--text); +} + +.setup-tab[aria-selected="true"] { + border-color: var(--accent); +} + +.setup-db-message { + margin: 0 0 14px; + border: 1px solid var(--line); + border-radius: 8px; + padding: 12px 14px; + font-weight: 800; +} + +.setup-db-message--success { + border-color: color-mix(in srgb, var(--accent-2) 60%, var(--line)); + background: color-mix(in srgb, var(--accent-2) 14%, var(--surface)); +} + +.setup-db-message--error { + border-color: color-mix(in srgb, #d92d20 60%, var(--line)); + background: color-mix(in srgb, #d92d20 10%, var(--surface)); +} + .setup-db-panels { display: grid; gap: 14px; @@ -680,6 +717,23 @@ a { gap: 6px; } +.setup-field input:not([type="checkbox"]), +.setup-field select, +.setup-field textarea { + width: 100%; + border: 1px solid var(--line); + border-radius: 8px; + background: var(--surface); + color: var(--text); + padding: 10px 12px; +} + +.setup-field input[type="checkbox"] { + width: 18px; + height: 18px; + accent-color: var(--accent); +} + .setup-field > span { font-weight: 800; color: var(--text); diff --git a/public/assets/js/app.js b/public/assets/js/app.js index 728c96f..d5b0848 100755 --- a/public/assets/js/app.js +++ b/public/assets/js/app.js @@ -83,3 +83,40 @@ if (themeAccentSelect) { for (const element of document.querySelectorAll('[data-reveal]')) { element.classList.add('reveal'); } + +const setupTabs = document.querySelectorAll('[data-setup-tab-target]'); +if (setupTabs.length > 0) { + const setupPanels = document.querySelectorAll('.setup-db-panel'); + const setupControls = document.querySelectorAll('.setup-db-panel input, .setup-db-panel select, .setup-db-panel textarea'); + for (const control of setupControls) { + if (control.required) { + control.dataset.setupRequired = 'true'; + } + } + + const activateSetupTab = (targetId) => { + for (const tab of setupTabs) { + const isActive = tab.dataset.setupTabTarget === targetId; + tab.classList.toggle('is-active', isActive); + tab.setAttribute('aria-selected', isActive ? 'true' : 'false'); + } + for (const panel of setupPanels) { + const isActive = panel.id === targetId; + panel.hidden = !isActive; + for (const control of panel.querySelectorAll('input, select, textarea')) { + if (control.dataset.setupRequired === 'true') { + control.required = isActive; + } + } + } + }; + + for (const tab of setupTabs) { + tab.addEventListener('click', () => { + activateSetupTab(tab.dataset.setupTabTarget); + }); + } + + const activeSetupTab = document.querySelector('[data-setup-tab-target].is-active') || setupTabs[0]; + activateSetupTab(activeSetupTab.dataset.setupTabTarget); +}