Continued development

This commit is contained in:
c0d3.m0nk3y 2026-05-17 21:17:45 -04:00
parent e9ec7ca392
commit 7054a6ead9
10 changed files with 389 additions and 33 deletions

View File

@ -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),
});
}

View File

@ -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)
});
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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)
{
@ -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();
}
}
}

View File

@ -123,9 +123,18 @@
<metadata name="MainForm_StatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>16, 55</value>
</metadata>
<metadata name="contextMenuStripClients.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>794, 71</value>
</metadata>
<metadata name="contextMenuStripProjects.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>356, 64</value>
</metadata>
<metadata name="contextMenuStripTreeviewTasks.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>358, 12</value>
</metadata>
<metadata name="contextMenuStripPTasks.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>805, 9</value>
</metadata>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>162</value>
</metadata>

View File

@ -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;

View File

@ -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;

View File

@ -10,17 +10,12 @@ namespace trakker.Models
/// </summary>
public class Client
{
public Client()
{
this.ClientId = Guid.NewGuid().ToString();
this.IsActive = "y";
}
/// <summary>
/// Primary identifier for the client. This maps to the database <c>client_id</c>.
/// Marked with <see cref="Key"/> to indicate the primary key.
/// </summary>
[Key]
public string ClientId { get; set; } = string.Empty;
public string ClientId { get; set; } = Guid.NewGuid().ToString();
/// <summary>
/// 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 <see cref="UpdatedAt"/> timestamp to the current UTC time. Call this
/// before persisting changes to ensure the audit timestamp is accurate.
/// </summary>
public int ProjectCount { get; set; } = 0;
public void UpdateTimestamp()
{
UpdatedAt = DateTime.UtcNow;

View File

@ -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; }