comparison ServerMonitor/Forms/ServerForm.cs @ 0:3e1a2131f897

Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
author Brad Greco <brad@bgreco.net>
date Mon, 31 Dec 2018 18:32:14 -0500
parents
children 3142e52cbe69
comparison
equal deleted inserted replaced
-1:000000000000 0:3e1a2131f897
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Threading.Tasks;
9 using System.Windows.Forms;
10
11 namespace ServerMonitorApp
12 {
13 public partial class ServerForm : Form
14 {
15 private bool isNewServer;
16 private bool changedPassword;
17 private DateTime lastSaveTime;
18 private ServerMonitor monitor;
19 private BindingList<CheckResult> logResults, logResultsFiltered;
20 private CheckStatus[] filteredStatuses;
21 private readonly Dictionary<int, CheckForm> checkForms = new Dictionary<int, CheckForm>();
22 private readonly Dictionary<CheckBox, CheckStatus> filterChecks;
23
24 public Server Server { get; private set; }
25
26 private IEnumerable<Check> SelectedChecks { get { return CheckGrid.SelectedRows.Cast<DataGridViewRow>().Select(r => r.DataBoundItem).Cast<Check>(); } }
27
28 private Check SelectedCheck { get { return SelectedChecks.FirstOrDefault(); } }
29
30 public ServerForm(ServerMonitor monitor, Server server, bool isNewServer = false)
31 {
32 InitializeComponent();
33 this.monitor = monitor;
34 this.isNewServer = isNewServer;
35 Server = server;
36 filterChecks = new Dictionary<CheckBox, CheckStatus>
37 {
38 { LogSuccessCheckBox, CheckStatus.Success },
39 { LogInformationCheckBox, CheckStatus.Information },
40 { LogWarningCheckBox, CheckStatus.Warning },
41 { LogErrorCheckBox, CheckStatus.Error },
42 };
43 }
44
45 private void ServerForm_Load(object sender, EventArgs e)
46 {
47 CheckBindingSource.DataSource = Server.Checks;
48 monitor.CheckStatusChanged += Monitor_CheckStatusChanged;
49 CheckGrid.ClearSelection();
50 if (isNewServer)
51 {
52 LoginComboBox.SelectedIndex = 0;
53 }
54 else
55 {
56 Text = Server.Name;
57 TitleLabel.Text = Server.Name;
58 NameTextBox.Text = Server.Name;
59 HostTextBox.Text = Server.Host;
60 PortTextBox.Text = Server.Port.ToString();
61 UsernameTextBox.Text = Server.Username;
62 PasswordTextBox.Text = "********************";
63 LoginComboBox.SelectedIndex = (int)Server.LoginType;
64 KeyTextBox.Text = Server.KeyFile;
65 changedPassword = false;
66 }
67
68 BindChangeListeners();
69 FormatImageButtons();
70 UpdateCheckButtons();
71 }
72
73 private void Monitor_CheckStatusChanged(object sender, CheckStatusChangedEventArgs e)
74 {
75 CheckGrid.Refresh();
76 if (e.CheckResult != null && logResults != null)
77 {
78 logResults.Insert(0, e.CheckResult);
79 if (logResultsFiltered != null && MatchesFilter(e.CheckResult))
80 logResultsFiltered.Insert(0, e.CheckResult);
81 }
82 }
83
84 /// <summary>Update the server with the current input values</summary>
85 /// <param name="forceSave">
86 /// If true, immediately update the config file on disk.
87 /// If false, only update the config file if it has not been recently updated.
88 /// </param>
89 private void UpdateServer(bool forceSave = true)
90 {
91 Server.Name = NameTextBox.Text;
92 Server.Host = HostTextBox.Text.Trim();
93 Server.Port = int.TryParse(PortTextBox.Text, out int port) ? port : 0;
94 Server.Username = UsernameTextBox.Text.Trim();
95 Server.LoginType = (LoginType)LoginComboBox.SelectedIndex;
96 Server.KeyFile = KeyTextBox.Text.Trim();
97 if (changedPassword)
98 Server.Password = PasswordTextBox.Text;
99
100 if (forceSave || lastSaveTime < DateTime.Now.AddSeconds(-5))
101 {
102 lastSaveTime = DateTime.Now;
103 monitor.SaveServers();
104 }
105 }
106
107 private void NameTextBox_TextChanged(object sender, EventArgs e)
108 {
109 Text = NameTextBox.Text;
110 TitleLabel.Text = NameTextBox.Text;
111 }
112
113 private void LoginComboBox_SelectedIndexChanged(object sender, EventArgs e)
114 {
115 if (LoginComboBox.SelectedIndex == (int)LoginType.PrivateKey)
116 {
117 PasswordTextBox.Visible = false;
118 KeyTextBox.Visible = true;
119 KeyBrowseButton.Visible = true;
120 }
121 else
122 {
123 PasswordTextBox.Visible = true;
124 KeyTextBox.Visible = false;
125 KeyBrowseButton.Visible = false;
126 }
127 }
128
129 private void NewCheckButton_Click(object sender, EventArgs e)
130 {
131 ShowCheckForm(null);
132 }
133
134 private void EditCheckButton_Click(object sender, EventArgs e)
135 {
136 EditSelectedCheck();
137 }
138
139 private void RunButton_Click(object sender, EventArgs e)
140 {
141 ExecuteChecks(SelectedChecks);
142 }
143
144 private void RunAllButton_Click(object sender, EventArgs e)
145 {
146 ExecuteChecks(Server.Checks);
147 }
148
149 private void ShowCheckForm(Check check)
150 {
151 if (check != null)
152 {
153 if (!checkForms.TryGetValue(check.Id, out CheckForm form))
154 {
155 form = new CheckForm(monitor, check);
156 checkForms[check.Id] = form;
157 form.FormClosing += CheckForm_FormClosing;
158 form.Show();
159 }
160 else
161 {
162 form.Activate();
163 }
164 }
165 else
166 {
167 new CheckForm(monitor, Server).Show();
168 }
169 }
170
171 private void EditSelectedCheck()
172 {
173 ShowCheckForm(SelectedCheck);
174 }
175
176 private void DeleteSelectedChecks()
177 {
178 if (Properties.Settings.Default.ConfirmDeleteCheck)
179 {
180 string message = "Delete " + (SelectedChecks.Count() == 1 ? "\"" + SelectedCheck.Name + "\"" : "selected checks") + "?";
181 using (CheckBoxDialog dialog = new CheckBoxDialog { Message = message })
182 {
183 DialogResult result = dialog.ShowDialog();
184 if (dialog.Checked && result == DialogResult.OK)
185 {
186 Properties.Settings.Default.ConfirmDeleteCheck = false;
187 Properties.Settings.Default.Save();
188 }
189 if (result != DialogResult.OK)
190 return;
191 }
192 }
193 foreach (Check check in SelectedChecks)
194 Server.DeleteCheck(check);
195 }
196
197 private async void ExecuteChecks(IEnumerable<Check> checks)
198 {
199 await Task.WhenAll(checks.Select(c => monitor.ExecuteCheckAsync(c)));
200 }
201
202 private void ShowLog(Check check)
203 {
204 LogCheckComboBox.SelectedItem = check;
205 CheckTabControl.SelectedTab = LogTabPage;
206 }
207
208 private void UpdateCheckButtons()
209 {
210 RunAllButton.Enabled = CheckGrid.RowCount > 0;
211 RunButton.Enabled = DeleteCheckButton.Enabled = CheckGrid.SelectedRows.Count > 0;
212 EditCheckButton.Enabled = CheckGrid.SelectedRows.Count == 1;
213 }
214
215 private void FormatImageButtons()
216 {
217 Button[] buttons = new Button[] { NewCheckButton, RunAllButton, RunButton, EditCheckButton, DeleteCheckButton };
218 foreach (Button button in buttons)
219 Helpers.FormatImageButton(button);
220 }
221
222 private void BindChangeListeners()
223 {
224 foreach (Control control in ServerInfoPanel.Controls.OfType<Control>().Where(c => c is TextBox))
225 control.TextChanged += (sender, e) => UpdateServer(false);
226 foreach (Control control in Controls.OfType<Control>().Where(c => c is ComboBox))
227 control.TextChanged += (sender, e) => UpdateServer();
228 foreach (CheckBox control in LogTabPage.Controls.OfType<CheckBox>())
229 control.CheckedChanged += FilterChanged;
230 }
231
232 private void CheckForm_FormClosing(object sender, FormClosingEventArgs e)
233 {
234 CheckForm form = (CheckForm)sender;
235 form.FormClosing -= CheckForm_FormClosing;
236 checkForms.Remove(form.CheckId);
237 if (form.DialogResult == DialogResult.OK)
238 CheckGrid.Refresh();
239 }
240
241 private void CheckGrid_SelectionChanged(object sender, EventArgs e)
242 {
243 UpdateCheckButtons();
244 }
245
246 private void PasswordTextBox_TextChanged(object sender, EventArgs e)
247 {
248 changedPassword = true;
249 }
250
251 private void ServerForm_FormClosing(object sender, FormClosingEventArgs e)
252 {
253 UpdateServer();
254 }
255
256 private void CheckGrid_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
257 {
258 EditSelectedCheck();
259 }
260
261 private void CheckGrid_KeyDown(object sender, KeyEventArgs e)
262 {
263 if (e.KeyCode == Keys.Enter)
264 {
265 EditSelectedCheck();
266 e.Handled = true;
267 }
268 }
269
270 private void DeleteCheckButton_Click(object sender, EventArgs e)
271 {
272 DeleteSelectedChecks();
273 UpdateServer();
274 }
275
276 private void CheckGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
277 {
278 if (e.ColumnIndex == StatusColumn.Index)
279 {
280 e.Value = ((CheckStatus)e.Value).GetIcon();
281 }
282 }
283
284 private void LogGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
285 {
286 if (e.ColumnIndex == LogStatusColumn.Index)
287 {
288 e.Value = ((CheckStatus)e.Value).GetIcon();
289 }
290 }
291
292 private void CheckBindingSource_ListChanged(object sender, ListChangedEventArgs e)
293 {
294 if (Server?.Checks != null)
295 {
296 //TODO this might result in the selection being reset to all (if a new check is added, for example.) Restore selected index.
297 LogCheckComboBox.Items.Clear();
298 LogCheckComboBox.Items.Add("(All)");
299 LogCheckComboBox.Items.AddRange(Server.Checks.ToArray());
300 LogCheckComboBox.SelectedIndex = 0;
301 }
302 }
303
304 private void CheckTabControl_SelectedIndexChanged(object sender, EventArgs e)
305 {
306 if (logResults == null && CheckTabControl.SelectedTab == LogTabPage)
307 {
308 logResults = new BindingList<CheckResult>(monitor.GetLog(Server));
309 LogGrid.DataSource = logResults;
310 }
311 }
312
313 private void CheckGrid_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
314 {
315 if (e.ColumnIndex == StatusColumn.Index)
316 CheckGrid.Cursor = Cursors.Hand;
317 }
318
319 private void CheckGrid_CellMouseLeave(object sender, DataGridViewCellEventArgs e)
320 {
321 if (e.ColumnIndex == StatusColumn.Index)
322 CheckGrid.Cursor = Cursors.Default;
323 }
324
325 private void CheckGrid_CellClick(object sender, DataGridViewCellEventArgs e)
326 {
327 if (e.ColumnIndex == StatusColumn.Index)
328 ShowLog((Check)CheckBindingSource[e.RowIndex]);
329 }
330
331 private void CheckGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
332 {
333 // The status column is set to read-only, and updates are manually done here.
334 // Otherwise, the change doesn't take effect until the cell loses focus.
335 if (e.ColumnIndex == EnabledColumn.Index)
336 {
337 Check check = (Check)CheckBindingSource[e.RowIndex];
338 check.Enabled = !(bool)CheckGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; ;
339 Server.UpdateCheck(check);
340 }
341 }
342
343 private void FilterChanged(object sender, EventArgs e)
344 {
345 filteredStatuses = filterChecks.Where(fc => fc.Key.Checked).Select(fc => fc.Value).ToArray();
346 if (filteredStatuses.Length == filterChecks.Count && LogCheckComboBox.SelectedIndex == 0) {
347 LogGrid.DataSource = logResults;
348 logResultsFiltered = null;
349 }
350 else
351 {
352 logResultsFiltered = new BindingList<CheckResult>(logResults.Where(result => MatchesFilter(result)).ToList());
353 LogGrid.DataSource = logResultsFiltered;
354 }
355 }
356
357 private bool MatchesFilter(CheckResult result)
358 {
359 return filteredStatuses.Contains(result.CheckStatus) && (LogCheckComboBox.SelectedIndex == 0 || LogCheckComboBox.SelectedItem == result.Check);
360 }
361 }
362 }