Add Sonic container scan with manual multi-select after system setup.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,432 @@
|
||||
using ZA.CoreService.ESBCertificateManager.Models;
|
||||
using ZA.CoreService.ESBCertificateManager.Services;
|
||||
|
||||
namespace ZA.CoreService.ESBCertificateManager.Setup;
|
||||
|
||||
public sealed class SelectContainersForm : Form
|
||||
{
|
||||
private readonly SetupCoordinator _coordinator;
|
||||
private readonly SonicSystemOption _system;
|
||||
private readonly SonicContainerScanner _scanner;
|
||||
|
||||
private readonly ComboBox _cmbCompany;
|
||||
private readonly CheckedListBox _lstContainers;
|
||||
private readonly TextBox _txtManual;
|
||||
private readonly TextBox _txtUser;
|
||||
private readonly TextBox _txtPassword;
|
||||
private readonly Label _lblStatus;
|
||||
private readonly Button _btnScan;
|
||||
private readonly Button _btnSave;
|
||||
private bool _running;
|
||||
|
||||
public int SavedCount { get; private set; }
|
||||
|
||||
public SelectContainersForm(
|
||||
SetupCoordinator coordinator,
|
||||
SonicSystemOption system)
|
||||
{
|
||||
_coordinator = coordinator;
|
||||
_system = system;
|
||||
_scanner = new SonicContainerScanner(coordinator.Settings.Runtime);
|
||||
|
||||
Text = "Container auswählen";
|
||||
StartPosition = FormStartPosition.CenterParent;
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
ShowInTaskbar = false;
|
||||
ClientSize = new Size(640, 620);
|
||||
BackColor = SettingsUi.Background;
|
||||
ForeColor = SettingsUi.Text;
|
||||
Font = new Font("Segoe UI", 10f);
|
||||
|
||||
Label title = new()
|
||||
{
|
||||
Text = "Container für System",
|
||||
Location = new Point(28, 20),
|
||||
AutoSize = true,
|
||||
Font = new Font("Segoe UI Semibold", 18f, FontStyle.Bold),
|
||||
ForeColor = SettingsUi.Text
|
||||
};
|
||||
|
||||
Label subtitle = new()
|
||||
{
|
||||
Text =
|
||||
$"{system.ConnectionName} · {system.ConnectionUrl}"
|
||||
+ Environment.NewLine
|
||||
+ "Scan von Sonic oder manuell eintragen, dann übernehmen.",
|
||||
Location = new Point(30, 54),
|
||||
Size = new Size(580, 40),
|
||||
ForeColor = SettingsUi.Muted
|
||||
};
|
||||
|
||||
Panel card = SettingsUi.CreateCard();
|
||||
card.Location = new Point(28, 110);
|
||||
card.Size = new Size(584, 430);
|
||||
card.Paint += SettingsUi.PaintCardBorder;
|
||||
|
||||
_cmbCompany = SettingsUi.CreateComboBox();
|
||||
_lstContainers = new CheckedListBox
|
||||
{
|
||||
BackColor = Color.FromArgb(12, 28, 48),
|
||||
ForeColor = SettingsUi.Text,
|
||||
BorderStyle = BorderStyle.FixedSingle,
|
||||
CheckOnClick = true,
|
||||
Font = new Font("Segoe UI", 10f)
|
||||
};
|
||||
|
||||
_txtManual = SettingsUi.CreateTextBox();
|
||||
_txtUser = SettingsUi.CreateTextBox();
|
||||
_txtPassword = SettingsUi.CreateTextBox();
|
||||
_txtPassword.UseSystemPasswordChar = true;
|
||||
|
||||
AddField(card, "Company", _cmbCompany, 18, 16, 540);
|
||||
AddField(card, "Gefundene / gewählte Container", _lstContainers, 18, 76, 540, 150);
|
||||
|
||||
Label manualLabel = SettingsUi.CreateFieldLabel("Manuell hinzufügen");
|
||||
manualLabel.Location = new Point(18, 240);
|
||||
_txtManual.Location = new Point(18, 262);
|
||||
_txtManual.Width = 400;
|
||||
|
||||
Button btnAddManual = SettingsUi.CreateGhostButton("+");
|
||||
btnAddManual.Location = new Point(430, 260);
|
||||
btnAddManual.Size = new Size(50, 32);
|
||||
btnAddManual.Click += (_, _) => AddManualContainer();
|
||||
|
||||
Button btnSuggest = SettingsUi.CreateGhostButton("ct-ZADBService");
|
||||
btnSuggest.Location = new Point(490, 260);
|
||||
btnSuggest.Size = new Size(68, 32);
|
||||
btnSuggest.Font = new Font("Segoe UI", 7.5f, FontStyle.Bold);
|
||||
btnSuggest.Click += (_, _) =>
|
||||
{
|
||||
_txtManual.Text = "ct-ZADBService";
|
||||
AddManualContainer();
|
||||
};
|
||||
|
||||
AddField(card, "Sonic-Benutzer (für Scan)", _txtUser, 18, 308, 250);
|
||||
AddField(card, "Kennwort", _txtPassword, 288, 308, 270);
|
||||
|
||||
_btnScan = SettingsUi.CreatePrimaryButton("Von Sonic scannen");
|
||||
_btnScan.Location = new Point(18, 375);
|
||||
_btnScan.Size = new Size(200, 36);
|
||||
_btnScan.Click += async (_, _) => await ScanAsync();
|
||||
|
||||
_lblStatus = new Label
|
||||
{
|
||||
Location = new Point(230, 380),
|
||||
Size = new Size(330, 30),
|
||||
ForeColor = SettingsUi.Muted
|
||||
};
|
||||
|
||||
card.Controls.Add(manualLabel);
|
||||
card.Controls.Add(_txtManual);
|
||||
card.Controls.Add(btnAddManual);
|
||||
card.Controls.Add(btnSuggest);
|
||||
card.Controls.Add(_btnScan);
|
||||
card.Controls.Add(_lblStatus);
|
||||
|
||||
_btnSave = SettingsUi.CreatePrimaryButton("Auswahl speichern");
|
||||
_btnSave.Location = new Point(352, 555);
|
||||
_btnSave.Size = new Size(260, 42);
|
||||
_btnSave.Click += async (_, _) => await SaveAsync();
|
||||
|
||||
Button skip = SettingsUi.CreateGhostButton("Später");
|
||||
skip.Location = new Point(230, 555);
|
||||
skip.Size = new Size(110, 42);
|
||||
skip.Click += (_, _) =>
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
Close();
|
||||
};
|
||||
|
||||
Controls.Add(title);
|
||||
Controls.Add(subtitle);
|
||||
Controls.Add(card);
|
||||
Controls.Add(skip);
|
||||
Controls.Add(_btnSave);
|
||||
|
||||
Shown += async (_, _) => await InitializeAsync();
|
||||
}
|
||||
|
||||
private async Task InitializeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
IReadOnlyList<CompanyOption> companies =
|
||||
await _coordinator.LoadCompaniesAsync();
|
||||
|
||||
_cmbCompany.Items.Clear();
|
||||
|
||||
foreach (CompanyOption company in companies)
|
||||
{
|
||||
_cmbCompany.Items.Add(company);
|
||||
}
|
||||
|
||||
if (_cmbCompany.Items.Count > 0)
|
||||
{
|
||||
int deIndex = 0;
|
||||
|
||||
for (int index = 0; index < companies.Count; index++)
|
||||
{
|
||||
if (string.Equals(
|
||||
companies[index].CompanyCode,
|
||||
"DE",
|
||||
StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
deIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_cmbCompany.SelectedIndex = deIndex;
|
||||
}
|
||||
|
||||
IReadOnlyList<SonicCredentialProfile> profiles =
|
||||
await _coordinator.LoadCredentialsAsync(
|
||||
_system.SonicConnectionId);
|
||||
|
||||
SonicCredentialProfile? profile =
|
||||
profiles.FirstOrDefault(item => item.IsDefault)
|
||||
?? profiles.FirstOrDefault();
|
||||
|
||||
if (profile is not null)
|
||||
{
|
||||
_txtUser.Text = profile.UserName;
|
||||
_txtPassword.Text = profile.Secret;
|
||||
_lblStatus.Text =
|
||||
"Profil geladen — Scan möglich.";
|
||||
_lblStatus.ForeColor = SettingsUi.Green;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lblStatus.Text =
|
||||
"Kein Profil — Benutzer/Kennwort für Scan eingeben oder manuell.";
|
||||
_lblStatus.ForeColor = SettingsUi.Gold;
|
||||
}
|
||||
|
||||
// Bereits vorhandene Container vorselektieren
|
||||
IReadOnlyList<ContainerOption> existing =
|
||||
await _coordinator.LoadContainersAsync(
|
||||
_system.SonicConnectionId);
|
||||
|
||||
foreach (ContainerOption container in existing)
|
||||
{
|
||||
AddContainerName(container.ContainerName, check: true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_lblStatus.Text = ex.Message;
|
||||
_lblStatus.ForeColor = SettingsUi.Red;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddManualContainer()
|
||||
{
|
||||
string name = _txtManual.Text.Trim();
|
||||
|
||||
if (name.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AddContainerName(name, check: true);
|
||||
_txtManual.Clear();
|
||||
_txtManual.Focus();
|
||||
}
|
||||
|
||||
private void AddContainerName(string name, bool check)
|
||||
{
|
||||
for (int index = 0; index < _lstContainers.Items.Count; index++)
|
||||
{
|
||||
if (string.Equals(
|
||||
_lstContainers.Items[index]?.ToString(),
|
||||
name,
|
||||
StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_lstContainers.SetItemChecked(index, check);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int added = _lstContainers.Items.Add(name);
|
||||
_lstContainers.SetItemChecked(added, check);
|
||||
}
|
||||
|
||||
private async Task ScanAsync()
|
||||
{
|
||||
if (_running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
_btnScan.Enabled = false;
|
||||
_btnSave.Enabled = false;
|
||||
Cursor = Cursors.WaitCursor;
|
||||
_lblStatus.Text = "Scanne Domain…";
|
||||
_lblStatus.ForeColor = SettingsUi.Muted;
|
||||
|
||||
try
|
||||
{
|
||||
ContainerScanResult result =
|
||||
await _scanner.ScanAsync(
|
||||
_system,
|
||||
_txtUser.Text,
|
||||
_txtPassword.Text);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
_lblStatus.Text = result.Message;
|
||||
_lblStatus.ForeColor = SettingsUi.Red;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string container in result.Containers)
|
||||
{
|
||||
AddContainerName(container, check: true);
|
||||
}
|
||||
|
||||
_lblStatus.Text =
|
||||
result.Containers.Count == 0
|
||||
? "Scan OK, aber keine Container gefunden — bitte manuell."
|
||||
: $"{result.Containers.Count} Container gescannt und vorausgewählt.";
|
||||
|
||||
_lblStatus.ForeColor =
|
||||
result.Containers.Count == 0
|
||||
? SettingsUi.Gold
|
||||
: SettingsUi.Green;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_lblStatus.Text = ex.Message;
|
||||
_lblStatus.ForeColor = SettingsUi.Red;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_running = false;
|
||||
_btnScan.Enabled = true;
|
||||
_btnSave.Enabled = true;
|
||||
Cursor = Cursors.Default;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveAsync()
|
||||
{
|
||||
if (_running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_cmbCompany.SelectedItem is not CompanyOption company)
|
||||
{
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"Bitte eine Company wählen.",
|
||||
"Container",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
List<string> selected = _lstContainers.CheckedItems
|
||||
.Cast<object>()
|
||||
.Select(item => item.ToString() ?? string.Empty)
|
||||
.Where(name => name.Length > 0)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
if (selected.Count == 0)
|
||||
{
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"Bitte mindestens einen Container angehakt lassen "
|
||||
+ "oder manuell hinzufügen.",
|
||||
"Container",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
_btnSave.Enabled = false;
|
||||
Cursor = Cursors.WaitCursor;
|
||||
|
||||
try
|
||||
{
|
||||
IReadOnlyList<ContainerOption> existing =
|
||||
await _coordinator.LoadContainersAsync(
|
||||
_system.SonicConnectionId);
|
||||
|
||||
HashSet<string> existingNames = existing
|
||||
.Select(item => item.ContainerName)
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
int created = 0;
|
||||
|
||||
foreach (string containerName in selected)
|
||||
{
|
||||
if (existingNames.Contains(containerName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
await _coordinator.AddSonicContainerAsync(
|
||||
company.CompanyId,
|
||||
_system.SonicConnectionId,
|
||||
containerName,
|
||||
containerDisplayName: null,
|
||||
restartTimeoutSeconds: 180);
|
||||
|
||||
created++;
|
||||
}
|
||||
|
||||
SavedCount = created;
|
||||
|
||||
MessageBox.Show(
|
||||
this,
|
||||
created == 0
|
||||
? "Alle gewählten Container waren bereits vorhanden."
|
||||
: $"{created} Container gespeichert und geprüft.",
|
||||
"Prüfung OK",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Information);
|
||||
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(
|
||||
this,
|
||||
ex.Message,
|
||||
"Container",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_running = false;
|
||||
_btnSave.Enabled = true;
|
||||
Cursor = Cursors.Default;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddField(
|
||||
Control parent,
|
||||
string label,
|
||||
Control input,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height = 30)
|
||||
{
|
||||
Label fieldLabel = SettingsUi.CreateFieldLabel(label);
|
||||
fieldLabel.Location = new Point(x, y);
|
||||
input.Location = new Point(x, y + 22);
|
||||
input.Width = width;
|
||||
input.Height = height;
|
||||
parent.Controls.Add(fieldLabel);
|
||||
parent.Controls.Add(input);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user