big changes
This commit is contained in:
@@ -0,0 +1,802 @@
|
||||
using ZA.CoreService.ESBCertificateManager.Models;
|
||||
|
||||
namespace ZA.CoreService.ESBCertificateManager.Setup;
|
||||
|
||||
public sealed class SetupWizardForm : Form
|
||||
{
|
||||
private readonly SetupCoordinator _coordinator;
|
||||
|
||||
private readonly Color _backgroundColor =
|
||||
Color.FromArgb(10, 18, 34);
|
||||
|
||||
private readonly Color _cardColor =
|
||||
Color.FromArgb(16, 38, 65);
|
||||
|
||||
private readonly Color _textColor =
|
||||
Color.FromArgb(241, 245, 249);
|
||||
|
||||
private readonly Color _mutedTextColor =
|
||||
Color.FromArgb(169, 184, 200);
|
||||
|
||||
private readonly Color _goldColor =
|
||||
Color.FromArgb(208, 171, 57);
|
||||
|
||||
private readonly Color _greenColor =
|
||||
Color.FromArgb(60, 203, 127);
|
||||
|
||||
private readonly Color _redColor =
|
||||
Color.FromArgb(239, 106, 106);
|
||||
|
||||
private Label _lblRuntime = null!;
|
||||
private Label _lblCertificate = null!;
|
||||
private Label _lblDatabase = null!;
|
||||
private Label _lblSelection = null!;
|
||||
private Label _lblEnvironment = null!;
|
||||
private Label _lblSystemDetails = null!;
|
||||
|
||||
private ComboBox _cmbSystem = null!;
|
||||
private ComboBox _cmbCredential = null!;
|
||||
|
||||
private Button _btnImportCertificate = null!;
|
||||
private Button _btnRefresh = null!;
|
||||
private Button _btnSaveSelection = null!;
|
||||
private Button _btnFinish = null!;
|
||||
private Button _btnAddCredential = null!;
|
||||
|
||||
private IReadOnlyList<SonicSystemOption> _systems = [];
|
||||
private IReadOnlyList<SonicCredentialProfile> _profiles = [];
|
||||
|
||||
private bool _running;
|
||||
|
||||
public SetupWizardForm(
|
||||
SetupCoordinator coordinator)
|
||||
{
|
||||
_coordinator = coordinator;
|
||||
|
||||
BuildInterface();
|
||||
|
||||
Shown += async (_, _) =>
|
||||
await InitializeAsync();
|
||||
}
|
||||
|
||||
private void BuildInterface()
|
||||
{
|
||||
Text = "ESB Certificate Manager einrichten";
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
Size = new Size(950, 690);
|
||||
MinimumSize = new Size(900, 650);
|
||||
MaximizeBox = false;
|
||||
|
||||
BackColor = _backgroundColor;
|
||||
ForeColor = _textColor;
|
||||
Font = new Font("Segoe UI", 10);
|
||||
|
||||
Label title = new()
|
||||
{
|
||||
Text = "Ersteinrichtung",
|
||||
AutoSize = true,
|
||||
Location = new Point(38, 25),
|
||||
ForeColor = _textColor,
|
||||
Font = new Font(
|
||||
"Segoe UI",
|
||||
24,
|
||||
FontStyle.Bold)
|
||||
};
|
||||
|
||||
Label subtitle = new()
|
||||
{
|
||||
Text =
|
||||
"Runtime, Datenbank, Zertifikat und Systemauswahl prüfen.",
|
||||
AutoSize = true,
|
||||
Location = new Point(42, 70),
|
||||
ForeColor = _mutedTextColor
|
||||
};
|
||||
|
||||
Panel checkCard = CreateCard(
|
||||
new Point(38, 105),
|
||||
new Size(870, 225));
|
||||
|
||||
Label checkTitle = CreateTitle(
|
||||
"Systemprüfung",
|
||||
new Point(20, 16));
|
||||
|
||||
_lblRuntime = CreateStatus(
|
||||
new Point(20, 55));
|
||||
|
||||
_lblCertificate = CreateStatus(
|
||||
new Point(20, 95));
|
||||
|
||||
_lblDatabase = CreateStatus(
|
||||
new Point(20, 135));
|
||||
|
||||
_lblSelection = CreateStatus(
|
||||
new Point(20, 175));
|
||||
|
||||
_btnImportCertificate = CreateButton(
|
||||
"PFX importieren");
|
||||
|
||||
_btnImportCertificate.Location =
|
||||
new Point(680, 90);
|
||||
|
||||
_btnImportCertificate.Size =
|
||||
new Size(160, 38);
|
||||
|
||||
_btnImportCertificate.Click +=
|
||||
async (_, _) =>
|
||||
await ImportCertificateAsync();
|
||||
_cmbCredential = new ComboBox
|
||||
{
|
||||
Location = new Point(185, 133),
|
||||
Size = new Size(300, 30),
|
||||
DropDownStyle =
|
||||
ComboBoxStyle.DropDownList
|
||||
};
|
||||
|
||||
checkCard.Controls.Add(checkTitle);
|
||||
checkCard.Controls.Add(_lblRuntime);
|
||||
checkCard.Controls.Add(_lblCertificate);
|
||||
checkCard.Controls.Add(_lblDatabase);
|
||||
checkCard.Controls.Add(_lblSelection);
|
||||
checkCard.Controls.Add(_btnImportCertificate);
|
||||
|
||||
Panel selectionCard = CreateCard(
|
||||
new Point(38, 350),
|
||||
new Size(870, 205));
|
||||
|
||||
Label selectionTitle = CreateTitle(
|
||||
"System auswählen",
|
||||
new Point(20, 16));
|
||||
|
||||
_lblEnvironment = new Label
|
||||
{
|
||||
Text =
|
||||
$"Umgebung: {_coordinator.Settings.EnvironmentCode}",
|
||||
AutoSize = true,
|
||||
Location = new Point(22, 55),
|
||||
ForeColor = _goldColor,
|
||||
Font = new Font(
|
||||
"Segoe UI",
|
||||
10,
|
||||
FontStyle.Bold)
|
||||
};
|
||||
|
||||
Label systemLabel = CreateLabel(
|
||||
"Sonic-System",
|
||||
new Point(22, 92));
|
||||
|
||||
_cmbSystem = new ComboBox
|
||||
{
|
||||
Location = new Point(185, 88),
|
||||
Size = new Size(300, 30),
|
||||
DropDownStyle =
|
||||
ComboBoxStyle.DropDownList
|
||||
};
|
||||
|
||||
_cmbSystem.SelectedIndexChanged +=
|
||||
async (_, _) =>
|
||||
await SystemChangedAsync();
|
||||
|
||||
Label credentialLabel = CreateLabel(
|
||||
"Benutzerprofil",
|
||||
new Point(22, 137));
|
||||
|
||||
_cmbCredential = new ComboBox
|
||||
{
|
||||
Location = new Point(185, 133),
|
||||
Size = new Size(300, 30),
|
||||
DropDownStyle =
|
||||
ComboBoxStyle.DropDownList
|
||||
};
|
||||
|
||||
_lblSystemDetails = new Label
|
||||
{
|
||||
Location = new Point(515, 88),
|
||||
Size = new Size(325, 72),
|
||||
ForeColor = _mutedTextColor
|
||||
};
|
||||
|
||||
_btnSaveSelection = CreateButton(
|
||||
"Auswahl übernehmen");
|
||||
|
||||
_btnSaveSelection.Location =
|
||||
new Point(640, 153);
|
||||
|
||||
_btnSaveSelection.Size =
|
||||
new Size(200, 38);
|
||||
|
||||
_btnSaveSelection.Click +=
|
||||
async (_, _) =>
|
||||
await SaveSelectionAsync();
|
||||
_btnAddCredential = CreateButton(
|
||||
"Profil hinzufügen");
|
||||
|
||||
_btnAddCredential.Location =
|
||||
new Point(495, 132);
|
||||
|
||||
_btnAddCredential.Size =
|
||||
new Size(140, 32);
|
||||
|
||||
_btnAddCredential.Click +=
|
||||
async (_, _) =>
|
||||
await AddCredentialAsync();
|
||||
selectionCard.Controls.Add(selectionTitle);
|
||||
selectionCard.Controls.Add(_lblEnvironment);
|
||||
selectionCard.Controls.Add(systemLabel);
|
||||
selectionCard.Controls.Add(_cmbSystem);
|
||||
selectionCard.Controls.Add(credentialLabel);
|
||||
selectionCard.Controls.Add(credentialLabel);
|
||||
selectionCard.Controls.Add(_cmbCredential);
|
||||
selectionCard.Controls.Add(_btnAddCredential);
|
||||
selectionCard.Controls.Add(_lblSystemDetails);
|
||||
selectionCard.Controls.Add(_btnSaveSelection);
|
||||
|
||||
_btnRefresh = CreateButton(
|
||||
"Erneut prüfen");
|
||||
|
||||
_btnRefresh.Location =
|
||||
new Point(525, 580);
|
||||
|
||||
_btnRefresh.Size =
|
||||
new Size(140, 42);
|
||||
|
||||
_btnRefresh.Click +=
|
||||
async (_, _) =>
|
||||
await InitializeAsync();
|
||||
|
||||
Button cancelButton = CreateButton(
|
||||
"Abbrechen");
|
||||
|
||||
cancelButton.Location =
|
||||
new Point(675, 580);
|
||||
|
||||
cancelButton.Size =
|
||||
new Size(110, 42);
|
||||
|
||||
cancelButton.Click += (_, _) =>
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
Close();
|
||||
};
|
||||
|
||||
_btnFinish = CreateButton(
|
||||
"Setup abschließen");
|
||||
|
||||
_btnFinish.Location =
|
||||
new Point(795, 580);
|
||||
|
||||
_btnFinish.Size =
|
||||
new Size(140, 42);
|
||||
|
||||
_btnFinish.Enabled = false;
|
||||
|
||||
_btnFinish.Click += (_, _) =>
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
};
|
||||
|
||||
Controls.Add(title);
|
||||
Controls.Add(subtitle);
|
||||
Controls.Add(checkCard);
|
||||
Controls.Add(selectionCard);
|
||||
Controls.Add(_btnRefresh);
|
||||
Controls.Add(cancelButton);
|
||||
Controls.Add(_btnFinish);
|
||||
}
|
||||
|
||||
private async Task InitializeAsync()
|
||||
{
|
||||
if (_running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetRunning(true);
|
||||
|
||||
try
|
||||
{
|
||||
SetupCheckResult result =
|
||||
await _coordinator.CheckAsync();
|
||||
|
||||
SetStatus(
|
||||
_lblRuntime,
|
||||
"Runtime",
|
||||
result.RuntimeReady,
|
||||
result.RuntimeMessage);
|
||||
|
||||
SetStatus(
|
||||
_lblCertificate,
|
||||
"Always Encrypted",
|
||||
result.CertificateReady,
|
||||
result.CertificateMessage);
|
||||
|
||||
SetStatus(
|
||||
_lblDatabase,
|
||||
"Datenbank",
|
||||
result.DatabaseReady,
|
||||
result.DatabaseMessage);
|
||||
|
||||
SetStatus(
|
||||
_lblSelection,
|
||||
"Auswahl",
|
||||
result.CredentialsReady,
|
||||
result.CredentialsMessage);
|
||||
|
||||
_btnImportCertificate.Visible =
|
||||
!result.CertificateReady;
|
||||
|
||||
_btnFinish.Enabled =
|
||||
result.IsReady;
|
||||
|
||||
if (result.CertificateReady)
|
||||
{
|
||||
await LoadSystemsAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(
|
||||
this,
|
||||
ex.Message,
|
||||
"Setup fehlgeschlagen",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetRunning(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadSystemsAsync()
|
||||
{
|
||||
LocalSetupSelection? previousSelection =
|
||||
_coordinator.LoadSelection();
|
||||
|
||||
_systems =
|
||||
await _coordinator.LoadSystemsAsync();
|
||||
|
||||
_cmbSystem.Items.Clear();
|
||||
_cmbCredential.Items.Clear();
|
||||
|
||||
foreach (SonicSystemOption system in _systems)
|
||||
{
|
||||
_cmbSystem.Items.Add(system);
|
||||
}
|
||||
|
||||
if (_systems.Count == 0)
|
||||
{
|
||||
_lblSystemDetails.Text =
|
||||
"Kein System für die gewählte Umgebung gefunden.";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int selectedIndex = 0;
|
||||
|
||||
if (previousSelection is not null)
|
||||
{
|
||||
for (int index = 0;
|
||||
index < _systems.Count;
|
||||
index++)
|
||||
{
|
||||
if (_systems[index].SonicConnectionId ==
|
||||
previousSelection.SonicConnectionId)
|
||||
{
|
||||
selectedIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_cmbSystem.SelectedIndex = selectedIndex;
|
||||
}
|
||||
private async Task AddCredentialAsync()
|
||||
{
|
||||
if (_running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_cmbSystem.SelectedItem
|
||||
is not SonicSystemOption system)
|
||||
{
|
||||
ShowWarning(
|
||||
"Bitte zuerst ein Sonic-System auswählen.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
using AddCredentialProfileForm dialog =
|
||||
new(
|
||||
_coordinator,
|
||||
system);
|
||||
|
||||
DialogResult dialogResult =
|
||||
dialog.ShowDialog(this);
|
||||
|
||||
if (dialogResult != DialogResult.OK
|
||||
|| dialog.CreatedProfile is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetRunning(true);
|
||||
|
||||
try
|
||||
{
|
||||
_profiles =
|
||||
await _coordinator.LoadCredentialsAsync(
|
||||
system.SonicConnectionId);
|
||||
|
||||
_cmbCredential.Items.Clear();
|
||||
|
||||
foreach (SonicCredentialProfile profile
|
||||
in _profiles)
|
||||
{
|
||||
_cmbCredential.Items.Add(profile);
|
||||
}
|
||||
|
||||
for (int index = 0;
|
||||
index < _cmbCredential.Items.Count;
|
||||
index++)
|
||||
{
|
||||
if (_cmbCredential.Items[index]
|
||||
is SonicCredentialProfile profile
|
||||
&& profile.SonicCredentialId
|
||||
== dialog.CreatedProfile.SonicCredentialId)
|
||||
{
|
||||
_cmbCredential.SelectedIndex =
|
||||
index;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_lblSystemDetails.Text =
|
||||
$"Domain: {system.DomainName}"
|
||||
+ Environment.NewLine
|
||||
+ $"Adresse: {system.ConnectionUrl}"
|
||||
+ Environment.NewLine
|
||||
+ $"Profil: {dialog.CreatedProfile.CredentialName}";
|
||||
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"Das geprüfte Benutzerprofil wurde geladen. " +
|
||||
"Klicke jetzt auf „Auswahl übernehmen“.",
|
||||
"Benutzerprofil hinzugefügt",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(
|
||||
this,
|
||||
ex.Message,
|
||||
"Benutzerprofile konnten nicht neu geladen werden",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetRunning(false);
|
||||
}
|
||||
}
|
||||
private async Task SystemChangedAsync()
|
||||
{
|
||||
if (_cmbSystem.SelectedItem
|
||||
is not SonicSystemOption system)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_lblSystemDetails.Text =
|
||||
$"Domain: {system.DomainName}" +
|
||||
Environment.NewLine +
|
||||
$"Adresse: {system.ConnectionUrl}";
|
||||
|
||||
_profiles =
|
||||
await _coordinator.LoadCredentialsAsync(
|
||||
system.SonicConnectionId);
|
||||
|
||||
_cmbCredential.Items.Clear();
|
||||
|
||||
foreach (SonicCredentialProfile profile
|
||||
in _profiles)
|
||||
{
|
||||
_cmbCredential.Items.Add(profile);
|
||||
}
|
||||
|
||||
if (_profiles.Count == 0)
|
||||
{
|
||||
_lblSystemDetails.Text +=
|
||||
Environment.NewLine
|
||||
+ "Kein Benutzerprofil vorhanden. "
|
||||
+ "Bitte ein neues Profil hinzufügen.";
|
||||
|
||||
_btnSaveSelection.Enabled = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_btnSaveSelection.Enabled = true;
|
||||
|
||||
LocalSetupSelection? selection =
|
||||
_coordinator.LoadSelection();
|
||||
|
||||
int selectedIndex = 0;
|
||||
|
||||
if (selection is not null)
|
||||
{
|
||||
for (int index = 0;
|
||||
index < _profiles.Count;
|
||||
index++)
|
||||
{
|
||||
if (_profiles[index].SonicCredentialId ==
|
||||
selection.SonicCredentialId)
|
||||
{
|
||||
selectedIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int defaultIndex =
|
||||
_profiles
|
||||
.Select(
|
||||
(profile, index) =>
|
||||
new
|
||||
{
|
||||
profile,
|
||||
index
|
||||
})
|
||||
.Where(item =>
|
||||
item.profile.IsDefault)
|
||||
.Select(item => item.index)
|
||||
.FirstOrDefault();
|
||||
|
||||
selectedIndex = defaultIndex;
|
||||
}
|
||||
|
||||
_cmbCredential.SelectedIndex =
|
||||
selectedIndex;
|
||||
}
|
||||
|
||||
private async Task SaveSelectionAsync()
|
||||
{
|
||||
if (_cmbSystem.SelectedItem
|
||||
is not SonicSystemOption system)
|
||||
{
|
||||
ShowWarning(
|
||||
"Bitte ein Sonic-System auswählen.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_cmbCredential.SelectedItem
|
||||
is not SonicCredentialProfile profile)
|
||||
{
|
||||
ShowWarning(
|
||||
"Bitte ein Benutzerprofil auswählen.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_coordinator.SaveSelection(
|
||||
system,
|
||||
profile);
|
||||
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"System und Benutzerprofil wurden ausgewählt.",
|
||||
"Setup",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Information);
|
||||
|
||||
await InitializeAsync();
|
||||
}
|
||||
|
||||
private async Task ImportCertificateAsync()
|
||||
{
|
||||
using OpenFileDialog dialog = new()
|
||||
{
|
||||
Title =
|
||||
"Always-Encrypted-PFX auswählen",
|
||||
Filter =
|
||||
"PFX-Zertifikat (*.pfx)|*.pfx",
|
||||
CheckFileExists = true,
|
||||
Multiselect = false
|
||||
};
|
||||
|
||||
if (dialog.ShowDialog(this)
|
||||
!= DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string? password =
|
||||
PromptForPassword();
|
||||
|
||||
if (password is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_coordinator.CertificateService.ImportPfx(
|
||||
dialog.FileName,
|
||||
password);
|
||||
|
||||
password = string.Empty;
|
||||
|
||||
await InitializeAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
password = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private static string? PromptForPassword()
|
||||
{
|
||||
using Form form = new()
|
||||
{
|
||||
Text = "PFX-Kennwort",
|
||||
Size = new Size(390, 160),
|
||||
StartPosition =
|
||||
FormStartPosition.CenterParent,
|
||||
FormBorderStyle =
|
||||
FormBorderStyle.FixedDialog
|
||||
};
|
||||
|
||||
TextBox textBox = new()
|
||||
{
|
||||
Location = new Point(15, 35),
|
||||
Width = 340,
|
||||
UseSystemPasswordChar = true
|
||||
};
|
||||
|
||||
Button ok = new()
|
||||
{
|
||||
Text = "OK",
|
||||
Location = new Point(190, 75),
|
||||
DialogResult = DialogResult.OK
|
||||
};
|
||||
|
||||
Button cancel = new()
|
||||
{
|
||||
Text = "Abbrechen",
|
||||
Location = new Point(275, 75),
|
||||
DialogResult = DialogResult.Cancel
|
||||
};
|
||||
|
||||
form.Controls.Add(textBox);
|
||||
form.Controls.Add(ok);
|
||||
form.Controls.Add(cancel);
|
||||
|
||||
form.AcceptButton = ok;
|
||||
form.CancelButton = cancel;
|
||||
|
||||
return form.ShowDialog()
|
||||
== DialogResult.OK
|
||||
? textBox.Text
|
||||
: null;
|
||||
}
|
||||
|
||||
private void SetRunning(bool running)
|
||||
{
|
||||
_running = running;
|
||||
|
||||
_cmbSystem.Enabled = !running;
|
||||
_cmbCredential.Enabled = !running;
|
||||
_btnAddCredential.Enabled = !running;
|
||||
_btnSaveSelection.Enabled = !running;
|
||||
_btnRefresh.Enabled = !running;
|
||||
_btnImportCertificate.Enabled = !running;
|
||||
|
||||
Cursor =
|
||||
running
|
||||
? Cursors.WaitCursor
|
||||
: Cursors.Default;
|
||||
}
|
||||
|
||||
private void ShowWarning(string message)
|
||||
{
|
||||
MessageBox.Show(
|
||||
this,
|
||||
message,
|
||||
"Setup",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
}
|
||||
|
||||
private Panel CreateCard(
|
||||
Point location,
|
||||
Size size)
|
||||
{
|
||||
return new Panel
|
||||
{
|
||||
Location = location,
|
||||
Size = size,
|
||||
BackColor = _cardColor,
|
||||
BorderStyle =
|
||||
BorderStyle.FixedSingle
|
||||
};
|
||||
}
|
||||
|
||||
private Label CreateTitle(
|
||||
string text,
|
||||
Point location)
|
||||
{
|
||||
return new Label
|
||||
{
|
||||
Text = text,
|
||||
Location = location,
|
||||
AutoSize = true,
|
||||
ForeColor = _textColor,
|
||||
Font = new Font(
|
||||
"Segoe UI",
|
||||
14,
|
||||
FontStyle.Bold)
|
||||
};
|
||||
}
|
||||
|
||||
private Label CreateLabel(
|
||||
string text,
|
||||
Point location)
|
||||
{
|
||||
return new Label
|
||||
{
|
||||
Text = text,
|
||||
Location = location,
|
||||
AutoSize = true,
|
||||
ForeColor = _mutedTextColor
|
||||
};
|
||||
}
|
||||
|
||||
private Label CreateStatus(
|
||||
Point location)
|
||||
{
|
||||
return new Label
|
||||
{
|
||||
Location = location,
|
||||
Size = new Size(620, 32),
|
||||
ForeColor = _mutedTextColor
|
||||
};
|
||||
}
|
||||
|
||||
private Button CreateButton(string text)
|
||||
{
|
||||
return new Button
|
||||
{
|
||||
Text = text,
|
||||
BackColor = _goldColor,
|
||||
ForeColor =
|
||||
Color.FromArgb(30, 25, 10),
|
||||
FlatStyle = FlatStyle.Flat,
|
||||
Font = new Font(
|
||||
"Segoe UI",
|
||||
9,
|
||||
FontStyle.Bold),
|
||||
Cursor = Cursors.Hand
|
||||
};
|
||||
}
|
||||
|
||||
private void SetStatus(
|
||||
Label label,
|
||||
string category,
|
||||
bool success,
|
||||
string message)
|
||||
{
|
||||
label.Text =
|
||||
$"{(success ? "✓" : "✗")} " +
|
||||
$"{category}: {message}";
|
||||
|
||||
label.ForeColor =
|
||||
success
|
||||
? _greenColor
|
||||
: _redColor;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user