diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerMonitor/Forms/ServerForm.cs	Mon Dec 31 18:32:14 2018 -0500
@@ -0,0 +1,362 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace ServerMonitorApp
+{
+    public partial class ServerForm : Form
+    {
+        private bool isNewServer;
+        private bool changedPassword;
+        private DateTime lastSaveTime;
+        private ServerMonitor monitor;
+        private BindingList<CheckResult> logResults, logResultsFiltered;
+        private CheckStatus[] filteredStatuses;
+        private readonly Dictionary<int, CheckForm> checkForms = new Dictionary<int, CheckForm>();
+        private readonly Dictionary<CheckBox, CheckStatus> filterChecks;
+
+        public Server Server { get; private set; }
+
+        private IEnumerable<Check> SelectedChecks { get { return CheckGrid.SelectedRows.Cast<DataGridViewRow>().Select(r => r.DataBoundItem).Cast<Check>(); } }
+
+        private Check SelectedCheck { get { return SelectedChecks.FirstOrDefault(); } }
+
+        public ServerForm(ServerMonitor monitor, Server server, bool isNewServer = false)
+        {
+            InitializeComponent();
+            this.monitor = monitor;
+            this.isNewServer = isNewServer;
+            Server = server;
+            filterChecks = new Dictionary<CheckBox, CheckStatus>
+            {
+                { LogSuccessCheckBox, CheckStatus.Success },
+                { LogInformationCheckBox, CheckStatus.Information },
+                { LogWarningCheckBox, CheckStatus.Warning },
+                { LogErrorCheckBox, CheckStatus.Error },
+            };
+        }
+
+        private void ServerForm_Load(object sender, EventArgs e)
+        {
+            CheckBindingSource.DataSource = Server.Checks;
+            monitor.CheckStatusChanged += Monitor_CheckStatusChanged;
+            CheckGrid.ClearSelection();
+            if (isNewServer)
+            {
+                LoginComboBox.SelectedIndex = 0;
+            }
+            else
+            {
+                Text = Server.Name;
+                TitleLabel.Text = Server.Name;
+                NameTextBox.Text = Server.Name;
+                HostTextBox.Text = Server.Host;
+                PortTextBox.Text = Server.Port.ToString();
+                UsernameTextBox.Text = Server.Username;
+                PasswordTextBox.Text = "********************";
+                LoginComboBox.SelectedIndex = (int)Server.LoginType;
+                KeyTextBox.Text = Server.KeyFile;
+                changedPassword = false;
+            }
+
+            BindChangeListeners();
+            FormatImageButtons();
+            UpdateCheckButtons();
+        }
+
+        private void Monitor_CheckStatusChanged(object sender, CheckStatusChangedEventArgs e)
+        {
+            CheckGrid.Refresh();
+            if (e.CheckResult != null && logResults != null)
+            {
+                logResults.Insert(0, e.CheckResult);
+                if (logResultsFiltered != null && MatchesFilter(e.CheckResult))
+                    logResultsFiltered.Insert(0, e.CheckResult);
+            }
+        }
+
+        /// <summary>Update the server with the current input values</summary>
+        /// <param name="forceSave">
+        /// If true, immediately update the config file on disk.
+        /// If false, only update the config file if it has not been recently updated.
+        /// </param>
+        private void UpdateServer(bool forceSave = true)
+        {
+            Server.Name = NameTextBox.Text;
+            Server.Host = HostTextBox.Text.Trim();
+            Server.Port = int.TryParse(PortTextBox.Text, out int port) ? port : 0;
+            Server.Username = UsernameTextBox.Text.Trim();
+            Server.LoginType = (LoginType)LoginComboBox.SelectedIndex;
+            Server.KeyFile = KeyTextBox.Text.Trim();
+            if (changedPassword)
+                Server.Password = PasswordTextBox.Text;
+
+            if (forceSave || lastSaveTime < DateTime.Now.AddSeconds(-5))
+            {
+                lastSaveTime = DateTime.Now;
+                monitor.SaveServers();
+            }
+        }
+
+        private void NameTextBox_TextChanged(object sender, EventArgs e)
+        {
+            Text = NameTextBox.Text;
+            TitleLabel.Text = NameTextBox.Text;
+        }
+
+        private void LoginComboBox_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (LoginComboBox.SelectedIndex == (int)LoginType.PrivateKey)
+            {
+                PasswordTextBox.Visible = false;
+                KeyTextBox.Visible = true;
+                KeyBrowseButton.Visible = true;
+            }
+            else
+            {
+                PasswordTextBox.Visible = true;
+                KeyTextBox.Visible = false;
+                KeyBrowseButton.Visible = false;
+            }
+        }
+
+        private void NewCheckButton_Click(object sender, EventArgs e)
+        {
+            ShowCheckForm(null);
+        }
+
+        private void EditCheckButton_Click(object sender, EventArgs e)
+        {
+            EditSelectedCheck();
+        }
+
+        private void RunButton_Click(object sender, EventArgs e)
+        {
+            ExecuteChecks(SelectedChecks);
+        }
+
+        private void RunAllButton_Click(object sender, EventArgs e)
+        {
+            ExecuteChecks(Server.Checks);
+        }
+
+        private void ShowCheckForm(Check check)
+        {
+            if (check != null)
+            {
+                if (!checkForms.TryGetValue(check.Id, out CheckForm form))
+                {
+                    form = new CheckForm(monitor, check);
+                    checkForms[check.Id] = form;
+                    form.FormClosing += CheckForm_FormClosing;
+                    form.Show();
+                }
+                else
+                {
+                    form.Activate();
+                }
+            }
+            else
+            {
+                new CheckForm(monitor, Server).Show();
+            }
+        }
+
+        private void EditSelectedCheck()
+        {
+            ShowCheckForm(SelectedCheck);
+        }
+
+        private void DeleteSelectedChecks()
+        {
+            if (Properties.Settings.Default.ConfirmDeleteCheck)
+            {
+                string message = "Delete " + (SelectedChecks.Count() == 1 ? "\"" + SelectedCheck.Name + "\"" : "selected checks") + "?";
+                using (CheckBoxDialog dialog = new CheckBoxDialog { Message = message })
+                {
+                    DialogResult result = dialog.ShowDialog();
+                    if (dialog.Checked && result == DialogResult.OK)
+                    {
+                        Properties.Settings.Default.ConfirmDeleteCheck = false;
+                        Properties.Settings.Default.Save();
+                    }
+                    if (result != DialogResult.OK)
+                        return;
+                }
+            }
+            foreach (Check check in SelectedChecks)
+                Server.DeleteCheck(check);
+        }
+
+        private async void ExecuteChecks(IEnumerable<Check> checks)
+        {
+            await Task.WhenAll(checks.Select(c => monitor.ExecuteCheckAsync(c)));
+        }
+
+        private void ShowLog(Check check)
+        {
+            LogCheckComboBox.SelectedItem = check;
+            CheckTabControl.SelectedTab = LogTabPage;
+        }
+
+        private void UpdateCheckButtons()
+        {
+            RunAllButton.Enabled = CheckGrid.RowCount > 0;
+            RunButton.Enabled = DeleteCheckButton.Enabled = CheckGrid.SelectedRows.Count > 0;
+            EditCheckButton.Enabled = CheckGrid.SelectedRows.Count == 1;
+        }
+
+        private void FormatImageButtons()
+        {
+            Button[] buttons = new Button[] { NewCheckButton, RunAllButton, RunButton, EditCheckButton, DeleteCheckButton };
+            foreach (Button button in buttons)
+                Helpers.FormatImageButton(button);
+        }
+
+        private void BindChangeListeners()
+        {
+            foreach (Control control in ServerInfoPanel.Controls.OfType<Control>().Where(c => c is TextBox))
+                control.TextChanged += (sender, e) => UpdateServer(false);
+            foreach (Control control in Controls.OfType<Control>().Where(c => c is ComboBox))
+                control.TextChanged += (sender, e) => UpdateServer();
+            foreach (CheckBox control in LogTabPage.Controls.OfType<CheckBox>())
+                control.CheckedChanged += FilterChanged;
+        }
+
+        private void CheckForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            CheckForm form = (CheckForm)sender;
+            form.FormClosing -= CheckForm_FormClosing;
+            checkForms.Remove(form.CheckId);
+            if (form.DialogResult == DialogResult.OK)
+                CheckGrid.Refresh();
+        }
+
+        private void CheckGrid_SelectionChanged(object sender, EventArgs e)
+        {
+            UpdateCheckButtons();
+        }
+
+        private void PasswordTextBox_TextChanged(object sender, EventArgs e)
+        {
+            changedPassword = true;
+        }
+
+        private void ServerForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            UpdateServer();
+        }
+
+        private void CheckGrid_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
+        {
+            EditSelectedCheck();
+        }
+
+        private void CheckGrid_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyCode == Keys.Enter)
+            {
+                EditSelectedCheck();
+                e.Handled = true;
+            }
+        }
+
+        private void DeleteCheckButton_Click(object sender, EventArgs e)
+        {
+            DeleteSelectedChecks();
+            UpdateServer();
+        }
+
+        private void CheckGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
+        {
+            if (e.ColumnIndex == StatusColumn.Index)
+            {
+                e.Value = ((CheckStatus)e.Value).GetIcon();
+            }
+        }
+
+        private void LogGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
+        {
+            if (e.ColumnIndex == LogStatusColumn.Index)
+            {
+                e.Value = ((CheckStatus)e.Value).GetIcon();
+            }
+        }
+
+        private void CheckBindingSource_ListChanged(object sender, ListChangedEventArgs e)
+        {
+            if (Server?.Checks != null)
+            {
+                //TODO this might result in the selection being reset to all (if a new check is added, for example.) Restore selected index.
+                LogCheckComboBox.Items.Clear();
+                LogCheckComboBox.Items.Add("(All)");
+                LogCheckComboBox.Items.AddRange(Server.Checks.ToArray());
+                LogCheckComboBox.SelectedIndex = 0;
+            }
+        }
+
+        private void CheckTabControl_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (logResults == null && CheckTabControl.SelectedTab == LogTabPage)
+            {
+                logResults = new BindingList<CheckResult>(monitor.GetLog(Server));
+                LogGrid.DataSource = logResults;
+            }
+        }
+
+        private void CheckGrid_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
+        {
+            if (e.ColumnIndex == StatusColumn.Index)
+                CheckGrid.Cursor = Cursors.Hand;
+        }
+
+        private void CheckGrid_CellMouseLeave(object sender, DataGridViewCellEventArgs e)
+        {
+            if (e.ColumnIndex == StatusColumn.Index)
+                CheckGrid.Cursor = Cursors.Default;
+        }
+
+        private void CheckGrid_CellClick(object sender, DataGridViewCellEventArgs e)
+        {
+            if (e.ColumnIndex == StatusColumn.Index)
+                ShowLog((Check)CheckBindingSource[e.RowIndex]);
+        }
+
+        private void CheckGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
+        {
+            // The status column is set to read-only, and updates are manually done here.
+            // Otherwise, the change doesn't take effect until the cell loses focus.
+            if (e.ColumnIndex == EnabledColumn.Index)
+            {
+                Check check = (Check)CheckBindingSource[e.RowIndex];
+                check.Enabled = !(bool)CheckGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; ;
+                Server.UpdateCheck(check);
+            }
+        }
+
+        private void FilterChanged(object sender, EventArgs e)
+        {
+            filteredStatuses = filterChecks.Where(fc => fc.Key.Checked).Select(fc => fc.Value).ToArray();
+            if (filteredStatuses.Length == filterChecks.Count && LogCheckComboBox.SelectedIndex == 0) {
+                LogGrid.DataSource = logResults;
+                logResultsFiltered = null;
+            }
+            else
+            {
+                logResultsFiltered = new BindingList<CheckResult>(logResults.Where(result => MatchesFilter(result)).ToList());
+                LogGrid.DataSource = logResultsFiltered;
+            }
+        }
+
+        private bool MatchesFilter(CheckResult result)
+        {
+            return filteredStatuses.Contains(result.CheckStatus) && (LogCheckComboBox.SelectedIndex == 0 || LogCheckComboBox.SelectedItem == result.Check);
+        }
+    }
+}