diff --git a/Data/ClientData.cs b/Data/ClientData.cs index a00e964..46d701b 100644 --- a/Data/ClientData.cs +++ b/Data/ClientData.cs @@ -34,7 +34,10 @@ namespace trakker.Data address_state, address_postal, notes, - is_active + is_active, + created_at, + updated_at, + (SELECT COUNT(*) FROM projects x WHERE x.client_id = clients.client_id ) AS project_count FROM clients WHERE @@ -66,6 +69,9 @@ namespace trakker.Data var _var9 = reader.GetOrdinal("address_postal"); var _var10 = reader.GetOrdinal("notes"); var _var11 = reader.GetOrdinal("is_active"); + var _var12 = reader.GetOrdinal("project_count"); + var _var13 = reader.GetOrdinal("created_at"); + var _var14 = reader.GetOrdinal("updated_at"); while (reader.Read()) { @@ -82,6 +88,9 @@ namespace trakker.Data AddressPostal = reader.GetString(_var9), Notes = reader.GetString(_var10), IsActive = reader.GetString(_var11), + ProjectCount = reader.GetInt32(_var12), + CreatedAt = reader.GetDateTime(_var13), + UpdatedAt = reader.GetDateTime(_var14), }); } diff --git a/Data/ProjectData.cs b/Data/ProjectData.cs index 74ab4ad..cd6b8e3 100644 --- a/Data/ProjectData.cs +++ b/Data/ProjectData.cs @@ -38,7 +38,8 @@ namespace trakker.Data IFNULL(a.amount, 0.0) AS actuals, p.notes, p.created_at, - p.updated_at + p.updated_at, + (SELECT COUNT(*) FROM tasks x WHERE x.project_id = p.project_id ) AS task_count FROM projects p LEFT JOIN clients c ON p.client_id = c.client_id LEFT JOIN (SELECT project_id, SUM(hourly_rate * actual_hours) AS amount FROM tasks GROUP BY project_id) a ON p.project_id = a.project_id @@ -75,6 +76,7 @@ namespace trakker.Data var _var14 = reader.GetOrdinal("created_at"); var _var15 = reader.GetOrdinal("updated_at"); var _var16 = reader.GetOrdinal("actuals"); + var _var17 = reader.GetOrdinal("task_count"); while (reader.Read()) { results.Add(new Project @@ -94,7 +96,8 @@ namespace trakker.Data Notes = reader.GetString(_var13), CreatedAt = reader.GetDateTime(_var14), UpdatedAt = reader.GetDateTime(_var15), - Actuals = reader.IsDBNull(_var16) ? null : reader.GetDecimal(_var16) + Actuals = reader.IsDBNull(_var16) ? null : reader.GetDecimal(_var16), + TaskCount = reader.GetInt32(_var17) }); } diff --git a/Forms/ClientForm.cs b/Forms/ClientForm.cs index 2666eef..fe86a63 100644 --- a/Forms/ClientForm.cs +++ b/Forms/ClientForm.cs @@ -53,6 +53,8 @@ namespace trakker.Forms maskedTextBoxAddressPostal.DataBindings.Add("Text", bindingSource, "AddressPostal", true); richTextBoxNotes.DataBindings.Add("Text", bindingSource, "Notes", true); + labelCreatedUpdatedDT.Text = $"Created: {_client.CreatedAt:G} | Updated: {_client.UpdatedAt:G}"; + // Configure dialog buttons and window behavior. buttonOkay.DialogResult = DialogResult.OK; buttonCancel.DialogResult = DialogResult.Cancel; diff --git a/Forms/MainForm.Designer.cs b/Forms/MainForm.Designer.cs index d255f92..28bcec9 100644 --- a/Forms/MainForm.Designer.cs +++ b/Forms/MainForm.Designer.cs @@ -39,9 +39,21 @@ MainForm_TabPage2 = new TabPage(); tableLayoutPanelClients1 = new TableLayoutPanel(); dataGridViewClients = new DataGridView(); + contextMenuStripClients = new ContextMenuStrip(components); + addClilentToolStripMenuItem = new ToolStripMenuItem(); + editThisClientToolStripMenuItem = new ToolStripMenuItem(); + deleteThisClientToolStripMenuItem = new ToolStripMenuItem(); + toolStripSeparator2 = new ToolStripSeparator(); + refreshToolStripMenuItem = new ToolStripMenuItem(); MainForm_TabPage3 = new TabPage(); tableLayoutPanelProjects1 = new TableLayoutPanel(); dataGridViewProjects = new DataGridView(); + contextMenuStripProjects = new ContextMenuStrip(components); + toolStripMenuItem1 = new ToolStripMenuItem(); + toolStripMenuItem2 = new ToolStripMenuItem(); + toolStripMenuItem3 = new ToolStripMenuItem(); + toolStripSeparator3 = new ToolStripSeparator(); + toolStripMenuItem4 = new ToolStripMenuItem(); groupBoxProjectWorkItems = new GroupBox(); splitContainerTasks1 = new SplitContainer(); treeViewTasks1 = new TreeView(); @@ -51,19 +63,33 @@ deleteThisTaskSubtaskToolStripMenuItem = new ToolStripMenuItem(); toolStripSeparator1 = new ToolStripSeparator(); addACommentToolStripMenuItem = new ToolStripMenuItem(); + toolStripSeparator4 = new ToolStripSeparator(); + expandAllToolStripMenuItem = new ToolStripMenuItem(); + collapseAllToolStripMenuItem = new ToolStripMenuItem(); + toolStripSeparator5 = new ToolStripSeparator(); + refreshToolStripMenuItem1 = new ToolStripMenuItem(); splitContainerTasks2 = new SplitContainer(); dataGridViewProjectTasks = new DataGridView(); tableLayoutPanelTasks2 = new TableLayoutPanel(); groupBoxTaskComments = new GroupBox(); richTextBoxTaskComments = new RichTextBox(); + contextMenuStripPTasks = new ContextMenuStrip(components); + editThisWorkItemToolStripMenuItem = new ToolStripMenuItem(); + deleteThisWorkItemToolStripMenuItem = new ToolStripMenuItem(); + toolStripSeparator7 = new ToolStripSeparator(); + addACommentToThisWorkItemToolStripMenuItem = new ToolStripMenuItem(); + toolStripSeparator6 = new ToolStripSeparator(); + refreshToolStripMenuItem2 = new ToolStripMenuItem(); MainForm_MenuStrip.SuspendLayout(); tabControlMainForm.SuspendLayout(); MainForm_TabPage2.SuspendLayout(); tableLayoutPanelClients1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)dataGridViewClients).BeginInit(); + contextMenuStripClients.SuspendLayout(); MainForm_TabPage3.SuspendLayout(); tableLayoutPanelProjects1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)dataGridViewProjects).BeginInit(); + contextMenuStripProjects.SuspendLayout(); groupBoxProjectWorkItems.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)splitContainerTasks1).BeginInit(); splitContainerTasks1.Panel1.SuspendLayout(); @@ -77,6 +103,7 @@ ((System.ComponentModel.ISupportInitialize)dataGridViewProjectTasks).BeginInit(); tableLayoutPanelTasks2.SuspendLayout(); groupBoxTaskComments.SuspendLayout(); + contextMenuStripPTasks.SuspendLayout(); SuspendLayout(); // // MainForm_MenuStrip @@ -165,6 +192,7 @@ dataGridViewClients.AllowUserToAddRows = false; dataGridViewClients.AllowUserToDeleteRows = false; dataGridViewClients.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridViewClients.ContextMenuStrip = contextMenuStripClients; dataGridViewClients.Dock = DockStyle.Fill; dataGridViewClients.Location = new Point(3, 4); dataGridViewClients.Name = "dataGridViewClients"; @@ -172,6 +200,47 @@ dataGridViewClients.RowHeadersWidth = 82; dataGridViewClients.Size = new Size(1850, 953); dataGridViewClients.TabIndex = 0; + dataGridViewClients.DoubleClick += Client_DataGridViewClients_DoubleClick; + // + // contextMenuStripClients + // + contextMenuStripClients.ImageScalingSize = new Size(32, 32); + contextMenuStripClients.Items.AddRange(new ToolStripItem[] { addClilentToolStripMenuItem, editThisClientToolStripMenuItem, deleteThisClientToolStripMenuItem, toolStripSeparator2, refreshToolStripMenuItem }); + contextMenuStripClients.Name = "contextMenuStripClients"; + contextMenuStripClients.Size = new Size(278, 162); + // + // addClilentToolStripMenuItem + // + addClilentToolStripMenuItem.Name = "addClilentToolStripMenuItem"; + addClilentToolStripMenuItem.Size = new Size(277, 38); + addClilentToolStripMenuItem.Text = "Add New Client"; + addClilentToolStripMenuItem.Click += addClilentToolStripMenuItem_Click; + // + // editThisClientToolStripMenuItem + // + editThisClientToolStripMenuItem.Name = "editThisClientToolStripMenuItem"; + editThisClientToolStripMenuItem.Size = new Size(277, 38); + editThisClientToolStripMenuItem.Text = "Edit This Client"; + editThisClientToolStripMenuItem.Click += editThisClientToolStripMenuItem_Click; + // + // deleteThisClientToolStripMenuItem + // + deleteThisClientToolStripMenuItem.Name = "deleteThisClientToolStripMenuItem"; + deleteThisClientToolStripMenuItem.Size = new Size(277, 38); + deleteThisClientToolStripMenuItem.Text = "Delete This Client"; + deleteThisClientToolStripMenuItem.Click += deleteThisClientToolStripMenuItem_Click; + // + // toolStripSeparator2 + // + toolStripSeparator2.Name = "toolStripSeparator2"; + toolStripSeparator2.Size = new Size(274, 6); + // + // refreshToolStripMenuItem + // + refreshToolStripMenuItem.Name = "refreshToolStripMenuItem"; + refreshToolStripMenuItem.Size = new Size(277, 38); + refreshToolStripMenuItem.Text = "Refresh"; + refreshToolStripMenuItem.Click += refreshToolStripMenuItem_Click; // // MainForm_TabPage3 // @@ -204,6 +273,7 @@ dataGridViewProjects.AllowUserToAddRows = false; dataGridViewProjects.AllowUserToDeleteRows = false; dataGridViewProjects.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridViewProjects.ContextMenuStrip = contextMenuStripProjects; dataGridViewProjects.Dock = DockStyle.Fill; dataGridViewProjects.Location = new Point(3, 4); dataGridViewProjects.Name = "dataGridViewProjects"; @@ -212,6 +282,46 @@ dataGridViewProjects.Size = new Size(1856, 380); dataGridViewProjects.TabIndex = 0; // + // contextMenuStripProjects + // + contextMenuStripProjects.ImageScalingSize = new Size(32, 32); + contextMenuStripProjects.Items.AddRange(new ToolStripItem[] { toolStripMenuItem1, toolStripMenuItem2, toolStripMenuItem3, toolStripSeparator3, toolStripMenuItem4 }); + contextMenuStripProjects.Name = "contextMenuStripClients"; + contextMenuStripProjects.Size = new Size(289, 162); + // + // toolStripMenuItem1 + // + toolStripMenuItem1.Name = "toolStripMenuItem1"; + toolStripMenuItem1.Size = new Size(288, 38); + toolStripMenuItem1.Text = "Add New Project"; + toolStripMenuItem1.Click += toolStripMenuItem1_Click; + // + // toolStripMenuItem2 + // + toolStripMenuItem2.Name = "toolStripMenuItem2"; + toolStripMenuItem2.Size = new Size(288, 38); + toolStripMenuItem2.Text = "Edit This Project"; + toolStripMenuItem2.Click += Project_DataGridViewProjects_Edit_Click; + // + // toolStripMenuItem3 + // + toolStripMenuItem3.Name = "toolStripMenuItem3"; + toolStripMenuItem3.Size = new Size(288, 38); + toolStripMenuItem3.Text = "Delete This Project"; + toolStripMenuItem3.Click += Project_DataGridViewProjects_Delete_Click; + // + // toolStripSeparator3 + // + toolStripSeparator3.Name = "toolStripSeparator3"; + toolStripSeparator3.Size = new Size(285, 6); + // + // toolStripMenuItem4 + // + toolStripMenuItem4.Name = "toolStripMenuItem4"; + toolStripMenuItem4.Size = new Size(288, 38); + toolStripMenuItem4.Text = "Refresh"; + toolStripMenuItem4.Click += Project_DataGridViewProjects_Refresh_Click; + // // groupBoxProjectWorkItems // groupBoxProjectWorkItems.Controls.Add(splitContainerTasks1); @@ -252,43 +362,74 @@ // contextMenuStripTreeviewTasks // contextMenuStripTreeviewTasks.ImageScalingSize = new Size(32, 32); - contextMenuStripTreeviewTasks.Items.AddRange(new ToolStripItem[] { addTaskSubtaskToolStripMenuItem, editThisTaskSubtaskToolStripMenuItem, deleteThisTaskSubtaskToolStripMenuItem, toolStripSeparator1, addACommentToolStripMenuItem }); + contextMenuStripTreeviewTasks.Items.AddRange(new ToolStripItem[] { addTaskSubtaskToolStripMenuItem, editThisTaskSubtaskToolStripMenuItem, deleteThisTaskSubtaskToolStripMenuItem, toolStripSeparator1, addACommentToolStripMenuItem, toolStripSeparator4, expandAllToolStripMenuItem, collapseAllToolStripMenuItem, toolStripSeparator5, refreshToolStripMenuItem1 }); contextMenuStripTreeviewTasks.Name = "contextMenuStripTreeviewTasks"; - contextMenuStripTreeviewTasks.Size = new Size(371, 162); + contextMenuStripTreeviewTasks.Size = new Size(508, 288); // // addTaskSubtaskToolStripMenuItem // addTaskSubtaskToolStripMenuItem.Name = "addTaskSubtaskToolStripMenuItem"; - addTaskSubtaskToolStripMenuItem.Size = new Size(370, 38); - addTaskSubtaskToolStripMenuItem.Text = "Add Task / Sub-task"; + addTaskSubtaskToolStripMenuItem.Size = new Size(507, 38); + addTaskSubtaskToolStripMenuItem.Text = "Add New Work Item"; addTaskSubtaskToolStripMenuItem.Click += PTask_AddTaskSubtaskToolStripMenuItem_Click; // // editThisTaskSubtaskToolStripMenuItem // editThisTaskSubtaskToolStripMenuItem.Name = "editThisTaskSubtaskToolStripMenuItem"; - editThisTaskSubtaskToolStripMenuItem.Size = new Size(370, 38); - editThisTaskSubtaskToolStripMenuItem.Text = "Edit this Task / Sub-task"; + editThisTaskSubtaskToolStripMenuItem.Size = new Size(507, 38); + editThisTaskSubtaskToolStripMenuItem.Text = "Edit This Work Item"; editThisTaskSubtaskToolStripMenuItem.Click += PTask_EditThisTaskSubtaskToolStripMenuItem_Click; // // deleteThisTaskSubtaskToolStripMenuItem // deleteThisTaskSubtaskToolStripMenuItem.Name = "deleteThisTaskSubtaskToolStripMenuItem"; - deleteThisTaskSubtaskToolStripMenuItem.Size = new Size(370, 38); - deleteThisTaskSubtaskToolStripMenuItem.Text = "Delete this Task / Sub-task"; + deleteThisTaskSubtaskToolStripMenuItem.Size = new Size(507, 38); + deleteThisTaskSubtaskToolStripMenuItem.Text = "Delete This Work Item"; deleteThisTaskSubtaskToolStripMenuItem.Click += PTask_DeleteThisTaskSubtaskToolStripMenuItem_Click; // // toolStripSeparator1 // toolStripSeparator1.Name = "toolStripSeparator1"; - toolStripSeparator1.Size = new Size(367, 6); + toolStripSeparator1.Size = new Size(504, 6); // // addACommentToolStripMenuItem // addACommentToolStripMenuItem.Name = "addACommentToolStripMenuItem"; - addACommentToolStripMenuItem.Size = new Size(370, 38); - addACommentToolStripMenuItem.Text = "Add a comment"; + addACommentToolStripMenuItem.Size = new Size(507, 38); + addACommentToolStripMenuItem.Text = "Add a Comment to Selected Work Item"; addACommentToolStripMenuItem.Click += PTask_AddACommentToolStripMenuItem_Click; // + // toolStripSeparator4 + // + toolStripSeparator4.Name = "toolStripSeparator4"; + toolStripSeparator4.Size = new Size(504, 6); + // + // expandAllToolStripMenuItem + // + expandAllToolStripMenuItem.Name = "expandAllToolStripMenuItem"; + expandAllToolStripMenuItem.Size = new Size(507, 38); + expandAllToolStripMenuItem.Text = "Expand All"; + expandAllToolStripMenuItem.Click += expandAllToolStripMenuItem_Click; + // + // collapseAllToolStripMenuItem + // + collapseAllToolStripMenuItem.Name = "collapseAllToolStripMenuItem"; + collapseAllToolStripMenuItem.Size = new Size(507, 38); + collapseAllToolStripMenuItem.Text = "Collapse All"; + collapseAllToolStripMenuItem.Click += collapseAllToolStripMenuItem_Click; + // + // toolStripSeparator5 + // + toolStripSeparator5.Name = "toolStripSeparator5"; + toolStripSeparator5.Size = new Size(504, 6); + // + // refreshToolStripMenuItem1 + // + refreshToolStripMenuItem1.Name = "refreshToolStripMenuItem1"; + refreshToolStripMenuItem1.Size = new Size(507, 38); + refreshToolStripMenuItem1.Text = "Refresh"; + refreshToolStripMenuItem1.Click += refreshToolStripMenuItem1_Click; + // // splitContainerTasks2 // splitContainerTasks2.Dock = DockStyle.Fill; @@ -358,6 +499,47 @@ richTextBoxTaskComments.Text = ""; richTextBoxTaskComments.LinkClicked += PTask_RichTextBoxTaskComments_LinkClicked; // + // contextMenuStripPTasks + // + contextMenuStripPTasks.ImageScalingSize = new Size(32, 32); + contextMenuStripPTasks.Items.AddRange(new ToolStripItem[] { editThisWorkItemToolStripMenuItem, deleteThisWorkItemToolStripMenuItem, toolStripSeparator7, addACommentToThisWorkItemToolStripMenuItem, toolStripSeparator6, refreshToolStripMenuItem2 }); + contextMenuStripPTasks.Name = "contextMenuStripPTasks"; + contextMenuStripPTasks.Size = new Size(508, 168); + // + // editThisWorkItemToolStripMenuItem + // + editThisWorkItemToolStripMenuItem.Name = "editThisWorkItemToolStripMenuItem"; + editThisWorkItemToolStripMenuItem.Size = new Size(507, 38); + editThisWorkItemToolStripMenuItem.Text = "Edit This Work Item"; + // + // deleteThisWorkItemToolStripMenuItem + // + deleteThisWorkItemToolStripMenuItem.Name = "deleteThisWorkItemToolStripMenuItem"; + deleteThisWorkItemToolStripMenuItem.Size = new Size(507, 38); + deleteThisWorkItemToolStripMenuItem.Text = "Delete This Work Item"; + // + // toolStripSeparator7 + // + toolStripSeparator7.Name = "toolStripSeparator7"; + toolStripSeparator7.Size = new Size(504, 6); + // + // addACommentToThisWorkItemToolStripMenuItem + // + addACommentToThisWorkItemToolStripMenuItem.Name = "addACommentToThisWorkItemToolStripMenuItem"; + addACommentToThisWorkItemToolStripMenuItem.Size = new Size(507, 38); + addACommentToThisWorkItemToolStripMenuItem.Text = "Add a Comment to Selected Work Item"; + // + // toolStripSeparator6 + // + toolStripSeparator6.Name = "toolStripSeparator6"; + toolStripSeparator6.Size = new Size(504, 6); + // + // refreshToolStripMenuItem2 + // + refreshToolStripMenuItem2.Name = "refreshToolStripMenuItem2"; + refreshToolStripMenuItem2.Size = new Size(507, 38); + refreshToolStripMenuItem2.Text = "Refresh"; + // // MainForm // AutoScaleDimensions = new SizeF(13F, 32F); @@ -376,9 +558,11 @@ MainForm_TabPage2.ResumeLayout(false); tableLayoutPanelClients1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)dataGridViewClients).EndInit(); + contextMenuStripClients.ResumeLayout(false); MainForm_TabPage3.ResumeLayout(false); tableLayoutPanelProjects1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)dataGridViewProjects).EndInit(); + contextMenuStripProjects.ResumeLayout(false); groupBoxProjectWorkItems.ResumeLayout(false); splitContainerTasks1.Panel1.ResumeLayout(false); splitContainerTasks1.Panel2.ResumeLayout(false); @@ -392,6 +576,7 @@ ((System.ComponentModel.ISupportInitialize)dataGridViewProjectTasks).EndInit(); tableLayoutPanelTasks2.ResumeLayout(false); groupBoxTaskComments.ResumeLayout(false); + contextMenuStripPTasks.ResumeLayout(false); ResumeLayout(false); PerformLayout(); } @@ -424,5 +609,29 @@ private TableLayoutPanel tableLayoutPanelTasks2; private GroupBox groupBoxTaskComments; private RichTextBox richTextBoxTaskComments; + private ContextMenuStrip contextMenuStripClients; + private ToolStripMenuItem addClilentToolStripMenuItem; + private ToolStripMenuItem editThisClientToolStripMenuItem; + private ToolStripMenuItem deleteThisClientToolStripMenuItem; + private ToolStripSeparator toolStripSeparator2; + private ToolStripMenuItem refreshToolStripMenuItem; + private ContextMenuStrip contextMenuStripProjects; + private ToolStripMenuItem toolStripMenuItem1; + private ToolStripMenuItem toolStripMenuItem2; + private ToolStripMenuItem toolStripMenuItem3; + private ToolStripSeparator toolStripSeparator3; + private ToolStripMenuItem toolStripMenuItem4; + private ToolStripSeparator toolStripSeparator4; + private ToolStripMenuItem expandAllToolStripMenuItem; + private ToolStripMenuItem collapseAllToolStripMenuItem; + private ToolStripSeparator toolStripSeparator5; + private ToolStripMenuItem refreshToolStripMenuItem1; + private ContextMenuStrip contextMenuStripPTasks; + private ToolStripMenuItem editThisWorkItemToolStripMenuItem; + private ToolStripMenuItem deleteThisWorkItemToolStripMenuItem; + private ToolStripSeparator toolStripSeparator7; + private ToolStripMenuItem addACommentToThisWorkItemToolStripMenuItem; + private ToolStripSeparator toolStripSeparator6; + private ToolStripMenuItem refreshToolStripMenuItem2; } } diff --git a/Forms/MainForm.cs b/Forms/MainForm.cs index cbcca39..669ccb1 100644 --- a/Forms/MainForm.cs +++ b/Forms/MainForm.cs @@ -110,11 +110,6 @@ namespace trakker dataGridViewClients.Columns.Add(textColumn); } - dataGridViewClients.DoubleClick += (s, e) => - { - Client_DataGridViewClients_DoubleClick(s!, e); - }; - dataGridViewClients.SelectionChanged += (s, e) => { Client_DataGridViewClients_SelectionChanged(s!, e); @@ -137,7 +132,7 @@ namespace trakker try { clientData.Upsert(client); - dataGridViewClients.Refresh(); // Refresh the DataGridView to reflect changes + _ctrl.LoadClients(); // Reload clients to update the DataGridView with any changes } catch (Exception ex) { @@ -279,7 +274,7 @@ namespace trakker dataGridViewProjects.DoubleClick += (s, e) => { - Project_DataGridViewProjects_DoubleClick(s!, e); + Project_DataGridViewProjects_DoubleClick(s!, e); }; dataGridViewProjects.SelectionChanged += (s, e) => @@ -773,9 +768,7 @@ namespace trakker public void PTask_DataGridViewProjectTasks_Fill(BindingSource tasks) { - //dataGridViewProjectTasks.Rows.Clear(); dataGridViewProjectTasks.DataSource = tasks; - //dataGridViewProjectTasks.Refresh(); } private void PTask_RichTextBoxTaskComments_LinkClicked(object sender, LinkClickedEventArgs e) @@ -794,5 +787,131 @@ namespace trakker DialogExtensions.GenericError(String.Format($"Failed to open link: {ex.Message}")); } } + + private void expandAllToolStripMenuItem_Click(object sender, EventArgs e) + { + treeViewTasks1.ExpandAll(); + } + + private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e) + { + treeViewTasks1.CollapseAll(); + } + + private void refreshToolStripMenuItem1_Click(object sender, EventArgs e) + { + _ctrl.LoadProjects(); + } + + private void toolStripMenuItem1_Click(object sender, EventArgs e) + { + Project selectedProject = new(); + selectedProject.ProjectName = "New Project"; + var dialog = new ProjectForm(selectedProject, _ctrl.GetClients(), _ctrl.GetLOV("project.status")); + if (dialog.ShowDialog(this) == DialogResult.OK) + { + Project project = dialog.Project; + ProjectData projectData = new ProjectData(_ConnectionString); + try + { + projectData.Upsert(project); + MessageBox.Show("Project saved successfully!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); + _ctrl.LoadProjects(); // Reload projects to update the DataGridView with any changes + } + catch (Exception ex) + { + MessageBox.Show($"Error saving project: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + return; + + } + + private void Project_DataGridViewProjects_Edit_Click(object sender, EventArgs e) + { + Project_DataGridViewProjects_DoubleClick(sender, e); + } + + private void Project_DataGridViewProjects_Delete_Click(object sender, EventArgs e) + { + var project = dataGridViewProjects.SelectedRows[0].DataBoundItem as Project; + if (project != null && project.TaskCount > 0) { + MessageBox.Show("Cannot delete project with associated tasks.", "Delete Project", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + if (MessageBox.Show("Are you sure you want to delete this project?", "Delete Project", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) + { + try + { + ProjectData projectData = new ProjectData(_ConnectionString); + projectData.Delete(project?.ProjectId ?? _empty); + _ctrl.LoadProjects(); // Reload projects to update the DataGridView with any changes + } + catch (Exception ex) + { + MessageBox.Show($"Error deleting project: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + private void Project_DataGridViewProjects_Refresh_Click(object sender, EventArgs e) + { + _ctrl.LoadProjects(); // Reload projects to update the DataGridView with any changes + } + + private void addClilentToolStripMenuItem_Click(object sender, EventArgs e) + { + Client selectedClient = new(); + selectedClient.Name = "New Client"; + var dialog = new ClientForm(selectedClient, _ctrl.GetLOV("state")); + if (dialog.ShowDialog(this) == DialogResult.OK) + { + Client client = dialog.Client; + ClientData clientData = new ClientData(_ConnectionString); + try + { + clientData.Upsert(client); + MessageBox.Show("Client saved successfully!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); + _ctrl.LoadClients(); // Reload clients to update the DataGridView with any changes + } + catch (Exception ex) + { + MessageBox.Show($"Error saving client: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + private void editThisClientToolStripMenuItem_Click(object sender, EventArgs e) + { + Client_DataGridViewClients_DoubleClick(sender, e); + } + + private void deleteThisClientToolStripMenuItem_Click(object sender, EventArgs e) + { + var client = dataGridViewClients.SelectedRows[0].DataBoundItem as Client; + if (client != null && client.ProjectCount > 0) { + MessageBox.Show("Cannot delete client with associated projects.", "Delete Client", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + if (MessageBox.Show("Are you sure you want to delete this client?", "Delete Client", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) + { + try + { + ClientData clientData = new ClientData(_ConnectionString); + clientData.Delete(client?.ClientId ?? _empty); + _ctrl.LoadClients(); // Reload clients to update the DataGridView with any changes + } + catch (Exception ex) + { + MessageBox.Show($"Error deleting client: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + } + + private void refreshToolStripMenuItem_Click(object sender, EventArgs e) + { + _ctrl.LoadClients(); + } } } diff --git a/Forms/MainForm.resx b/Forms/MainForm.resx index d18a8cc..aca8133 100644 --- a/Forms/MainForm.resx +++ b/Forms/MainForm.resx @@ -123,9 +123,18 @@ 16, 55 + + 794, 71 + + + 356, 64 + 358, 12 + + 805, 9 + 162 diff --git a/Forms/ProjectForm.cs b/Forms/ProjectForm.cs index 3d1155d..85ecaa8 100644 --- a/Forms/ProjectForm.cs +++ b/Forms/ProjectForm.cs @@ -67,6 +67,8 @@ namespace trakker.Forms comboBoxStatus.DataBindings.Add("SelectedValue", bindingSource, "Status", true); richTextBoxNotes.DataBindings.Add("Text", bindingSource, "Notes", true); + labelCreatedUpdatedDT.Text = $"Created: {_project.CreatedAt:G} | Updated: {_project.UpdatedAt:G}"; + // Configure dialog buttons and window behavior. buttonOkay.DialogResult = DialogResult.OK; buttonCancel.DialogResult = DialogResult.Cancel; diff --git a/Forms/TaskForm.cs b/Forms/TaskForm.cs index 963cc22..a44e443 100644 --- a/Forms/TaskForm.cs +++ b/Forms/TaskForm.cs @@ -78,6 +78,8 @@ namespace trakker.Forms comboBoxStatus.DataBindings.Add("SelectedValue", bindingSource, "Status", true); comboBoxPriority.DataBindings.Add("SelectedValue", bindingSource, "Priority", true); + labelCreatedUpdatedDT.Text = $"Created: {_task.CreatedAt:G} | Updated: {_task.UpdatedAt:G}"; + // Configure dialog buttons and window behavior. buttonOkay.DialogResult = DialogResult.OK; buttonCancel.DialogResult = DialogResult.Cancel; diff --git a/Models/Client.cs b/Models/Client.cs index a768e16..94c6151 100644 --- a/Models/Client.cs +++ b/Models/Client.cs @@ -10,17 +10,12 @@ namespace trakker.Models /// public class Client { - public Client() - { - this.ClientId = Guid.NewGuid().ToString(); - this.IsActive = "y"; - } /// /// Primary identifier for the client. This maps to the database client_id. /// Marked with to indicate the primary key. /// [Key] - public string ClientId { get; set; } = string.Empty; + public string ClientId { get; set; } = Guid.NewGuid().ToString(); /// /// The client's full name. This field is required and has a maximum length of 200 characters. @@ -101,6 +96,9 @@ namespace trakker.Models /// Updates the timestamp to the current UTC time. Call this /// before persisting changes to ensure the audit timestamp is accurate. /// + + public int ProjectCount { get; set; } = 0; + public void UpdateTimestamp() { UpdatedAt = DateTime.UtcNow; diff --git a/Models/Project.cs b/Models/Project.cs index c58076d..fa35699 100644 --- a/Models/Project.cs +++ b/Models/Project.cs @@ -3,7 +3,7 @@ namespace trakker.Models { public class Project { - public string ProjectId { get; set; } = string.Empty; + public string ProjectId { get; set; } = Guid.NewGuid().ToString(); public string ClientId { get; set; } = string.Empty; @@ -15,9 +15,9 @@ namespace trakker.Models public string? Description { get; set; } = string.Empty; - public DateTime? StartDate { get; set; } + public DateTime? StartDate { get; set; } = DateTime.UtcNow; - public DateTime? EndDate { get; set; } + public DateTime? EndDate { get; set; } = DateTime.UtcNow; public decimal Budget { get; set; } = 0; @@ -25,7 +25,7 @@ namespace trakker.Models public string StatusName { get; set; } = string.Empty; - public decimal? HourlyRate { get; set; } + public decimal? HourlyRate { get; set; } = 0; public decimal? Actuals { get; set; } @@ -35,6 +35,9 @@ namespace trakker.Models public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; + public int TaskCount { get; set; } = 0; + + // Optional navigation property (for Entity Framework Core) public Client? Client { get; set; }