Simplify actions to one deploy button and per-row restart menu.

Keep only the yellow Austauschen + Neustart button; move manual restart into a three-dot row menu and probe TLS status after restart.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-03 13:21:35 +02:00
co-authored by Cursor
parent 58b7826162
commit 76e280d809
+76 -94
View File
@@ -65,10 +65,9 @@ namespace ZA.CoreService.ESBCertificateManager
private Button btnMinimize = null!;
private Button btnMaximize = null!;
private Button btnClose = null!;
private Button btnValidate = null!;
private Button btnDeploy = null!;
private Button btnRestartOnly = null!;
private Button btnCancelRun = null!;
private ContextMenuStrip _targetRowMenu = null!;
private bool isMaximized = false;
private Point dragStartPoint;
@@ -1377,6 +1376,55 @@ namespace ZA.CoreService.ESBCertificateManager
dgvTargets.Columns.Add("Container", "Neustart-Container");
dgvTargets.Columns.Add("Status", "Status");
DataGridViewButtonColumn actionsColumn = new DataGridViewButtonColumn
{
Name = "Actions",
HeaderText = "",
Text = "⋮",
UseColumnTextForButtonValue = true,
FillWeight = 18,
FlatStyle = FlatStyle.Flat
};
actionsColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
actionsColumn.DefaultCellStyle.ForeColor = MutedTextColor;
actionsColumn.DefaultCellStyle.SelectionForeColor = TextColor;
dgvTargets.Columns.Add(actionsColumn);
_targetRowMenu = new ContextMenuStrip();
ToolStripMenuItem restartMenuItem = new ToolStripMenuItem("Manuell neu starten");
restartMenuItem.Click += async (_, _) =>
{
if (_targetRowMenu.Tag is DeploymentTarget target)
{
await RunRestartOnlyAsync([target]);
}
};
_targetRowMenu.Items.Add(restartMenuItem);
dgvTargets.CellContentClick += (_, e) =>
{
if (e.RowIndex < 0
|| e.ColumnIndex < 0
|| dgvTargets.Columns[e.ColumnIndex].Name != "Actions")
{
return;
}
if (dgvTargets.Rows[e.RowIndex].Tag is not DeploymentTarget target)
{
return;
}
_targetRowMenu.Tag = target;
Rectangle cellRect = dgvTargets.GetCellDisplayRectangle(
e.ColumnIndex,
e.RowIndex,
true);
Point screenLocation = dgvTargets.PointToScreen(
new Point(cellRect.Left, cellRect.Bottom));
_targetRowMenu.Show(screenLocation);
};
dgvTargets.CurrentCellDirtyStateChanged += (_, _) =>
{
if (dgvTargets.IsCurrentCellDirty
@@ -1428,26 +1476,12 @@ namespace ZA.CoreService.ESBCertificateManager
SetStatus("Abbruch angefordert…", isError: false);
};
btnValidate = CreateSecondaryButton("Prüfung durchführen");
btnValidate.Size = new Size(175, 42);
btnValidate.Anchor = AnchorStyles.Top | AnchorStyles.Right;
btnValidate.Click += async (_, _) => await RunValidationAsync();
// Primäraktion: Neustart (Deploy vorerst deaktiviert Design/Layout bleibt)
btnRestartOnly = CreatePrimaryButton("ESB neu starten");
btnRestartOnly.Size = new Size(170, 42);
btnRestartOnly.Anchor = AnchorStyles.Top | AnchorStyles.Right;
btnRestartOnly.Click += async (_, _) => await RunRestartOnlyAsync();
btnDeploy = CreatePrimaryButton("Austauschen + Neustart");
btnDeploy.Size = new Size(190, 42);
btnDeploy.Size = new Size(220, 42);
btnDeploy.Anchor = AnchorStyles.Top | AnchorStyles.Right;
btnDeploy.Visible = true;
btnDeploy.Click += async (_, _) => await RunDeploymentAsync();
panel.Controls.Add(btnCancelRun);
panel.Controls.Add(btnValidate);
panel.Controls.Add(btnRestartOnly);
panel.Controls.Add(btnDeploy);
void PositionActionButtons()
@@ -1455,12 +1489,8 @@ namespace ZA.CoreService.ESBCertificateManager
const int spacing = 12;
const int rightMargin = 0;
// Rechts nach links anordnen:
// Deployment | Neustart | Prüfung | Abbrechen
btnDeploy.Left = panel.ClientSize.Width - btnDeploy.Width - rightMargin;
btnRestartOnly.Left = btnDeploy.Left - btnRestartOnly.Width - spacing;
btnValidate.Left = btnRestartOnly.Left - btnValidate.Width - spacing;
btnCancelRun.Left = btnValidate.Left - btnCancelRun.Width - spacing;
btnCancelRun.Left = btnDeploy.Left - btnCancelRun.Width - spacing;
}
panel.Resize += (_, _) => PositionActionButtons();
@@ -1780,14 +1810,13 @@ namespace ZA.CoreService.ESBCertificateManager
private void RefreshActionButtonStates()
{
if (btnValidate is null || btnDeploy is null || btnCancelRun is null)
if (btnDeploy is null || btnCancelRun is null)
{
return;
}
bool idle = !_isOperationRunning;
bool hasCertificate = isCertificateFileLoaded && _loadedCertificateInfo is not null;
bool hasTargets = _loadedTargets.Count > 0;
bool hasSelection = dgvTargets is not null && GetSelectedTargets().Count > 0;
if (btnSelectFile is not null)
@@ -1796,14 +1825,7 @@ namespace ZA.CoreService.ESBCertificateManager
}
btnCancelRun.Enabled = _isOperationRunning;
// Prüfung nur für Neustart-Voraussetzungen (Zertifikat optional)
btnValidate.Enabled = idle && hasTargets;
btnDeploy.Visible = true;
btnDeploy.Enabled = idle && hasCertificate && hasSelection;
if (btnRestartOnly is not null)
{
btnRestartOnly.Enabled = idle && hasSelection;
}
if (dgvTargets is not null)
{
@@ -1840,64 +1862,7 @@ namespace ZA.CoreService.ESBCertificateManager
MessageBox.Show(this, details, caption, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
private Task RunValidationAsync()
{
if (_orchestrator is null)
{
SetStatus(
"Die Anwendung ist noch nicht vollständig initialisiert.",
isError: true);
return Task.CompletedTask;
}
if (_isOperationRunning)
{
return Task.CompletedTask;
}
List<DeploymentTarget> selected = GetSelectedTargets();
PreflightValidationResult result = _orchestrator.ValidateRestartOnly(selected);
HashSet<int> failedTargetIds = result.Issues
.Where(i => i.TargetId is not null)
.Select(i => i.TargetId!.Value)
.ToHashSet();
foreach (DataGridViewRow row in dgvTargets.Rows)
{
if (row.Tag is not DeploymentTarget target)
{
continue;
}
if (failedTargetIds.Contains(target.Id))
{
SetTargetRowStatus(target.Id, "Prüfung fehlgeschlagen");
}
else if (row.Cells["Selected"].Value is true)
{
SetTargetRowStatus(target.Id, "Bereit");
}
}
if (!result.IsValid)
{
ShowPreflightIssues(result, "Vorabprüfung fehlgeschlagen.", "Vorabprüfung");
return Task.CompletedTask;
}
UpdateToNextStep(3);
SetStatus($"Vorabprüfung ok {selected.Count} Ziel(e) bereit.", isError: false);
MessageBox.Show(
this,
"Prüfung OK.",
"Vorabprüfung",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return Task.CompletedTask;
}
private async Task RunRestartOnlyAsync()
private async Task RunRestartOnlyAsync(IReadOnlyList<DeploymentTarget> targets)
{
if (_orchestrator is null)
{
@@ -1912,7 +1877,13 @@ namespace ZA.CoreService.ESBCertificateManager
return;
}
List<DeploymentTarget> selected = GetSelectedTargets();
List<DeploymentTarget> selected = [.. targets];
if (selected.Count == 0)
{
SetStatus("Kein Ziel für den Neustart ausgewählt.", isError: true);
return;
}
PreflightValidationResult preflight = _orchestrator.ValidateRestartOnly(selected);
if (!preflight.IsValid)
@@ -1920,14 +1891,18 @@ namespace ZA.CoreService.ESBCertificateManager
ShowPreflightIssues(
preflight,
"Neustart blockiert Vorabprüfung fehlgeschlagen.",
"ESB neu starten");
"Manuell neu starten");
return;
}
string targetLabel = selected.Count == 1
? selected[0].Name
: $"{selected.Count} Ziele";
DialogResult confirm = MessageBox.Show(
this,
"Neu starten?",
"ESB neu starten",
$"Container für „{targetLabel}“ neu starten?",
"Manuell neu starten",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning);
@@ -1940,7 +1915,7 @@ namespace ZA.CoreService.ESBCertificateManager
_runCts = new CancellationTokenSource();
SetOperationRunning(true);
UpdateToNextStep(3);
SetStatus($"ESB-Neustart läuft für {selected.Count} Ziel(e)…", isError: false);
SetStatus($"Neustart läuft für {selected.Count} Ziel(e)…", isError: false);
Progress<TargetProgressUpdate> progress = new(update =>
{
@@ -1969,6 +1944,13 @@ namespace ZA.CoreService.ESBCertificateManager
if (runResult.OverallSuccess)
{
UpdateToNextStep(4);
HashSet<int> restartedTargetIds = runResult.TargetResults
.Where(result => result.Success)
.Select(result => result.TargetId)
.ToHashSet();
await ProbeTargetCertificatesAsync(restartedTargetIds);
}
else
{