Continued development

This commit is contained in:
c0d3.m0nk3y 2026-05-15 12:51:35 -04:00
parent 3defad51f8
commit 29497cc003
5 changed files with 132 additions and 62 deletions

View File

@ -390,7 +390,7 @@ namespace trakker.Data
return result; return result;
} }
public List<PTaskFS> GetFS() public List<PTaskFS> GetFS(string projectId)
{ {
var results = new List<PTaskFS>(); var results = new List<PTaskFS>();
@ -403,6 +403,8 @@ namespace trakker.Data
a.project_id a.project_id
FROM FROM
projects a projects a
WHERE
a.project_id = $project_id
UNION UNION
@ -414,13 +416,15 @@ namespace trakker.Data
b.project_id b.project_id
FROM FROM
tasks b tasks b
WHERE
b.project_id = $project_id
; ;
"; ";
using var conn = OpenConnection(); using var conn = OpenConnection();
using var cmd = conn.CreateCommand(); using var cmd = conn.CreateCommand();
cmd.CommandText = sql; cmd.CommandText = sql;
cmd.Parameters.AddWithValue("$project_id", projectId);
using var reader = cmd.ExecuteReader(); using var reader = cmd.ExecuteReader();

View File

@ -54,8 +54,6 @@
splitContainerTasks2 = new SplitContainer(); splitContainerTasks2 = new SplitContainer();
dataGridViewProjectTasks = new DataGridView(); dataGridViewProjectTasks = new DataGridView();
tableLayoutPanelTasks2 = new TableLayoutPanel(); tableLayoutPanelTasks2 = new TableLayoutPanel();
groupBoxTaskDescription = new GroupBox();
richTextBoxTaskDescription = new RichTextBox();
groupBoxTaskComments = new GroupBox(); groupBoxTaskComments = new GroupBox();
richTextBoxTaskComments = new RichTextBox(); richTextBoxTaskComments = new RichTextBox();
MainForm_MenuStrip.SuspendLayout(); MainForm_MenuStrip.SuspendLayout();
@ -78,7 +76,6 @@
splitContainerTasks2.SuspendLayout(); splitContainerTasks2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridViewProjectTasks).BeginInit(); ((System.ComponentModel.ISupportInitialize)dataGridViewProjectTasks).BeginInit();
tableLayoutPanelTasks2.SuspendLayout(); tableLayoutPanelTasks2.SuspendLayout();
groupBoxTaskDescription.SuspendLayout();
groupBoxTaskComments.SuspendLayout(); groupBoxTaskComments.SuspendLayout();
SuspendLayout(); SuspendLayout();
// //
@ -327,47 +324,23 @@
// //
tableLayoutPanelTasks2.ColumnCount = 1; tableLayoutPanelTasks2.ColumnCount = 1;
tableLayoutPanelTasks2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F)); tableLayoutPanelTasks2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
tableLayoutPanelTasks2.Controls.Add(groupBoxTaskDescription, 0, 0); tableLayoutPanelTasks2.Controls.Add(groupBoxTaskComments, 0, 0);
tableLayoutPanelTasks2.Controls.Add(groupBoxTaskComments, 0, 1);
tableLayoutPanelTasks2.Dock = DockStyle.Fill; tableLayoutPanelTasks2.Dock = DockStyle.Fill;
tableLayoutPanelTasks2.Location = new Point(0, 0); tableLayoutPanelTasks2.Location = new Point(0, 0);
tableLayoutPanelTasks2.Name = "tableLayoutPanelTasks2"; tableLayoutPanelTasks2.Name = "tableLayoutPanelTasks2";
tableLayoutPanelTasks2.RowCount = 2; tableLayoutPanelTasks2.RowCount = 1;
tableLayoutPanelTasks2.RowStyles.Add(new RowStyle(SizeType.Percent, 25F)); tableLayoutPanelTasks2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
tableLayoutPanelTasks2.RowStyles.Add(new RowStyle(SizeType.Percent, 75F)); tableLayoutPanelTasks2.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
tableLayoutPanelTasks2.Size = new Size(1230, 303); tableLayoutPanelTasks2.Size = new Size(1230, 303);
tableLayoutPanelTasks2.TabIndex = 0; tableLayoutPanelTasks2.TabIndex = 0;
// //
// groupBoxTaskDescription
//
groupBoxTaskDescription.Controls.Add(richTextBoxTaskDescription);
groupBoxTaskDescription.Dock = DockStyle.Fill;
groupBoxTaskDescription.Location = new Point(3, 3);
groupBoxTaskDescription.Name = "groupBoxTaskDescription";
groupBoxTaskDescription.Size = new Size(1224, 69);
groupBoxTaskDescription.TabIndex = 0;
groupBoxTaskDescription.TabStop = false;
groupBoxTaskDescription.Text = "Description";
//
// richTextBoxTaskDescription
//
richTextBoxTaskDescription.BackColor = SystemColors.Control;
richTextBoxTaskDescription.BorderStyle = BorderStyle.None;
richTextBoxTaskDescription.Dock = DockStyle.Fill;
richTextBoxTaskDescription.Location = new Point(3, 35);
richTextBoxTaskDescription.Name = "richTextBoxTaskDescription";
richTextBoxTaskDescription.ReadOnly = true;
richTextBoxTaskDescription.Size = new Size(1218, 31);
richTextBoxTaskDescription.TabIndex = 0;
richTextBoxTaskDescription.Text = "";
//
// groupBoxTaskComments // groupBoxTaskComments
// //
groupBoxTaskComments.Controls.Add(richTextBoxTaskComments); groupBoxTaskComments.Controls.Add(richTextBoxTaskComments);
groupBoxTaskComments.Dock = DockStyle.Fill; groupBoxTaskComments.Dock = DockStyle.Fill;
groupBoxTaskComments.Location = new Point(3, 78); groupBoxTaskComments.Location = new Point(3, 3);
groupBoxTaskComments.Name = "groupBoxTaskComments"; groupBoxTaskComments.Name = "groupBoxTaskComments";
groupBoxTaskComments.Size = new Size(1224, 222); groupBoxTaskComments.Size = new Size(1224, 297);
groupBoxTaskComments.TabIndex = 1; groupBoxTaskComments.TabIndex = 1;
groupBoxTaskComments.TabStop = false; groupBoxTaskComments.TabStop = false;
groupBoxTaskComments.Text = "Comments"; groupBoxTaskComments.Text = "Comments";
@ -380,9 +353,10 @@
richTextBoxTaskComments.Location = new Point(3, 35); richTextBoxTaskComments.Location = new Point(3, 35);
richTextBoxTaskComments.Name = "richTextBoxTaskComments"; richTextBoxTaskComments.Name = "richTextBoxTaskComments";
richTextBoxTaskComments.ReadOnly = true; richTextBoxTaskComments.ReadOnly = true;
richTextBoxTaskComments.Size = new Size(1218, 184); richTextBoxTaskComments.Size = new Size(1218, 259);
richTextBoxTaskComments.TabIndex = 1; richTextBoxTaskComments.TabIndex = 1;
richTextBoxTaskComments.Text = ""; richTextBoxTaskComments.Text = "";
richTextBoxTaskComments.LinkClicked += richTextBoxTaskComments_LinkClicked;
// //
// MainForm // MainForm
// //
@ -417,7 +391,6 @@
splitContainerTasks2.ResumeLayout(false); splitContainerTasks2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)dataGridViewProjectTasks).EndInit(); ((System.ComponentModel.ISupportInitialize)dataGridViewProjectTasks).EndInit();
tableLayoutPanelTasks2.ResumeLayout(false); tableLayoutPanelTasks2.ResumeLayout(false);
groupBoxTaskDescription.ResumeLayout(false);
groupBoxTaskComments.ResumeLayout(false); groupBoxTaskComments.ResumeLayout(false);
ResumeLayout(false); ResumeLayout(false);
PerformLayout(); PerformLayout();
@ -449,8 +422,6 @@
private SplitContainer splitContainerTasks2; private SplitContainer splitContainerTasks2;
private DataGridView dataGridViewProjectTasks; private DataGridView dataGridViewProjectTasks;
private TableLayoutPanel tableLayoutPanelTasks2; private TableLayoutPanel tableLayoutPanelTasks2;
private GroupBox groupBoxTaskDescription;
private RichTextBox richTextBoxTaskDescription;
private GroupBox groupBoxTaskComments; private GroupBox groupBoxTaskComments;
private RichTextBox richTextBoxTaskComments; private RichTextBox richTextBoxTaskComments;
} }

View File

@ -152,7 +152,14 @@ namespace trakker
} }
public void FillDataGridViewProjects(BindingSource projects) public void FillDataGridViewProjects(BindingSource projects)
{ {
int idx = 0;
if (dataGridViewProjects.CurrentRow != null)
{
idx = dataGridViewProjects.CurrentRow.Index;
}
//MessageBox.Show($"Project idx: {idx}", "Debug Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
dataGridViewProjects.DataSource = projects; dataGridViewProjects.DataSource = projects;
dataGridViewProjects.Rows[idx].Selected = true;
} }
public void InitDataGridViewProjects() public void InitDataGridViewProjects()
{ {
@ -292,21 +299,32 @@ namespace trakker
} }
}; };
dataGridViewClients.SelectionChanged += (s, e) => dataGridViewProjects.SelectionChanged += (s, e) =>
{ {
if (dataGridViewClients.SelectedRows.Count > 0) if (_ctrl == null) return; // Safety check to prevent null reference exceptions during initialization)
if (dataGridViewProjects.SelectedRows.Count > 0)
{ {
var selectedClient = dataGridViewClients.SelectedRows[0].DataBoundItem as Client; var selectedProject = dataGridViewProjects.SelectedRows[0].DataBoundItem as Project;
if (selectedClient != null) if (selectedProject != null)
{ {
// Handle the selected client as needed // Handle the selected project as needed
// MessageBox.Show($"Selected Client: {selectedClient.AddressStreet}", "Client Selected", MessageBoxButtons.OK, MessageBoxIcon.Information ); //MessageBox.Show($"Project ID: {selectedProject.ProjectId}, Selected Project: {selectedProject.ProjectName}", "Project Selected", MessageBoxButtons.OK, MessageBoxIcon.Information );
_ctrl.LoadTasks(selectedProject.ProjectId); // Load tasks for the selected project
InitProjectTasks();
} }
} }
}; };
} }
public void InitProjectTasks()
{
//dataGridViewProjectTasks.Rows.Clear();
//richTextBoxTaskComments.Text = string.Empty;
richTextBoxTaskComments.WordWrap = false;
richTextBoxTaskComments.ReadOnly = true;
}
public void InitTreeViewTasks() public void InitTreeViewTasks()
{ {
// Basic TreeView configuration // Basic TreeView configuration
@ -315,21 +333,33 @@ namespace trakker
treeViewTasks1.ShowLines = true; treeViewTasks1.ShowLines = true;
treeViewTasks1.ShowRootLines = true; treeViewTasks1.ShowRootLines = true;
treeViewTasks1.HideSelection = false; treeViewTasks1.HideSelection = false;
treeViewTasks1.FullRowSelect = true;
treeViewTasks1.EndUpdate(); treeViewTasks1.EndUpdate();
// When a tree node is clicked, fetch and show notebooks for that folder // When a tree node is clicked, fetch and show notebooks for that folder
treeViewTasks1.NodeMouseClick += (sender, e) => treeViewTasks1.NodeMouseClick += (sender, e) =>
{ {
PTaskFS? selectedNode = (PTaskFS?)e.Node.Tag ?? new PTaskFS(); TreeViewTasks1_NodeMouseClick(e.Node, e.Button);
if (selectedNode?.Parent == "/" || selectedNode?.GUID == "/")
{
_ctrl.LoadTasksRecursive(selectedNode.ProjectId, PTask.RecursiveRoot.PARENT_TASK_ID); // Load all tasks for the project when root node is clicked
return;
}
_ctrl.LoadTasksRecursive(selectedNode?.GUID ?? "/", PTask.RecursiveRoot.TASK_ID); // Load all tasks for the project when root node is clicked
}; };
} }
public void TreeViewTasks1_NodeMouseClick(TreeNode node, MouseButtons button = MouseButtons.Left)
{
if (node == null) return;
// Put all your NodeMouseClick logic here
treeViewTasks1.SelectedNode = node; // Usually what you want
node.EnsureVisible();
// ... your other code (open form, load data, etc.)
PTaskFS? selectedNode = (PTaskFS?)node.Tag ?? new PTaskFS();
if (selectedNode?.Parent == "/" || selectedNode?.GUID == "/")
{
_ctrl.LoadTasksRecursive(selectedNode.ProjectId, PTask.RecursiveRoot.PARENT_TASK_ID); // Load all tasks for the project when root node is clicked
return;
}
_ctrl.LoadTasksRecursive(selectedNode?.GUID ?? "/", PTask.RecursiveRoot.TASK_ID); // Load all tasks for the project when root node is clicked
}
public void FillTreeViewTasks(List<PTaskFS> items) public void FillTreeViewTasks(List<PTaskFS> items)
{ {
if (items == null) return; if (items == null) return;
@ -340,7 +370,7 @@ namespace trakker
// Root node // Root node
PTaskFS root = new(); PTaskFS root = new();
root.GUID = "/"; root.GUID = "/";
root.Node = "/Projects"; root.Node = "/Project";
root.Parent = string.Empty; root.Parent = string.Empty;
TreeNode rootNode = new TreeNode(root.Node) { Tag = root }; TreeNode rootNode = new TreeNode(root.Node) { Tag = root };
treeViewTasks1.Nodes.Add(rootNode); treeViewTasks1.Nodes.Add(rootNode);
@ -372,7 +402,7 @@ namespace trakker
{ {
var text = string.IsNullOrWhiteSpace(child.Node) ? "(unnamed)" : child.Node!.Trim(); var text = string.IsNullOrWhiteSpace(child.Node) ? "(unnamed)" : child.Node!.Trim();
var tn = new TreeNode(text) { Tag = child }; var tn = new TreeNode(text) { Tag = child };
//tn.Expand(); tn.Expand();
parentNode.Nodes.Add(tn); parentNode.Nodes.Add(tn);
// Recurse using this child's node text as the parent key // Recurse using this child's node text as the parent key
@ -383,9 +413,13 @@ namespace trakker
// // Start recursion from root key // // Start recursion from root key
AddChildren(rootNode, "/"); AddChildren(rootNode, "/");
//rootNode.ExpandAll(); rootNode.ExpandAll();
rootNode.Expand(); // Expand first level for better UX
treeViewTasks1.EndUpdate(); // End the update treeViewTasks1.EndUpdate(); // End the update
TreeNode node = rootNode.FirstNode;
TreeViewTasks1_NodeMouseClick(node, MouseButtons.Left);
//treeViewTasks1.SelectedNode = node;
//treeViewTasks1.Focus();
} }
private void addTaskSubtaskToolStripMenuItem_Click(object sender, EventArgs e) private void addTaskSubtaskToolStripMenuItem_Click(object sender, EventArgs e)
@ -649,6 +683,48 @@ namespace trakker
{ {
dataGridViewProjectTasks_SelectionChanged(s, e); dataGridViewProjectTasks_SelectionChanged(s, e);
}; };
dataGridViewProjectTasks.DoubleClick += (s, e) =>
{ // BCN
var projectIdx = dataGridViewProjects.SelectedRows[0].Index;
var taskIdx = dataGridViewProjectTasks.SelectedRows[0].Index;
var row = dataGridViewProjectTasks.SelectedRows[0];
if (row != null)
{
var task = dataGridViewProjectTasks.SelectedRows[0].DataBoundItem as PTask;
TaskForm dialog = new TaskForm(task!, _ctrl.GetLOV("task.status"), _ctrl.GetLOV("task.priority"));
DialogResult result = dialog.ShowDialog(this);
if (result == DialogResult.OK)
{
task = dialog.Task;
try
{
TaskData taskData = new TaskData(connectionString);
taskData.Upsert(task);
//_ctrl.LoadTasks(task.ProjectId ?? string.Empty); // Reload tasks to update the DataGridView with any changes
_ctrl.LoadProjects(); // Reload projects to update the DataGridView with any changes
_ctrl.LoadTasksRecursive(task.TaskId ?? string.Empty, PTask.RecursiveRoot.TASK_ID); // Reload tasks to update the tree view with any changes
dataGridViewProjects.ClearSelection();
if (projectIdx >= 0 && projectIdx < dataGridViewProjects.Rows.Count)
{
dataGridViewProjects.Rows[projectIdx].Selected = true;
}
dataGridViewProjectTasks.ClearSelection();
if (taskIdx >= 0 && taskIdx < dataGridViewProjectTasks.Rows.Count)
{
dataGridViewProjectTasks.Rows[taskIdx].Selected = true;
}
}
catch (Exception ex)
{
MessageBox.Show($"Error saving task: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
};
} }
public void dataGridViewProjectTasks_SelectionChanged(object? sender, EventArgs? e) public void dataGridViewProjectTasks_SelectionChanged(object? sender, EventArgs? e)
{ {
@ -658,7 +734,6 @@ namespace trakker
var selectedTask = dataGridViewProjectTasks.SelectedRows[0].DataBoundItem as PTask; var selectedTask = dataGridViewProjectTasks.SelectedRows[0].DataBoundItem as PTask;
if (selectedTask != null) if (selectedTask != null)
{ {
richTextBoxTaskDescription.Text = selectedTask.Description;
TaskData taskData = new TaskData(connectionString); TaskData taskData = new TaskData(connectionString);
List<PTaskComment> comments = taskData.GetComments(selectedTask.TaskId ?? string.Empty); List<PTaskComment> comments = taskData.GetComments(selectedTask.TaskId ?? string.Empty);
richTextBoxTaskComments.Clear(); richTextBoxTaskComments.Clear();
@ -671,9 +746,26 @@ namespace trakker
} }
public void FillDataGridViewProjectTasks(BindingSource tasks) public void FillDataGridViewProjectTasks(BindingSource tasks)
{ {
//dataGridViewProjectTasks.Rows.Clear();
dataGridViewProjectTasks.DataSource = tasks; dataGridViewProjectTasks.DataSource = tasks;
dataGridViewProjectTasks.Refresh(); //dataGridViewProjectTasks.Refresh();
} }
private void richTextBoxTaskComments_LinkClicked(object sender, LinkClickedEventArgs e)
{
try
{
// Open the URL in the default browser
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName = e.LinkText,
UseShellExecute = true
});
}
catch (Exception ex)
{
DialogExtensions.GenericError(String.Format($"Failed to open link: {ex.Message}"));
}
}
} }
} }

View File

@ -16,6 +16,7 @@ namespace trakker.Interfaces
void FillTreeViewTasks(List<PTaskFS> items); void FillTreeViewTasks(List<PTaskFS> items);
void InitTreeViewTasks(); void InitTreeViewTasks();
void InitDataGridViewProjectTasks(); void InitDataGridViewProjectTasks();
void InitProjectTasks();
void FillDataGridViewProjectTasks(BindingSource tasks); void FillDataGridViewProjectTasks(BindingSource tasks);
} }
} }

View File

@ -59,12 +59,14 @@ namespace trakker.Services
var x = project.Status; var x = project.Status;
} }
_view.FillDataGridViewProjects(new BindingSource { DataSource = projects }); _view.FillDataGridViewProjects(new BindingSource { DataSource = projects });
LoadTasks(); //LoadTasks();
} }
internal void LoadTasks() internal void LoadTasks(string projectId)
{ {
var dbo = new TaskData(_connectionString); var dbo = new TaskData(_connectionString);
_view.FillTreeViewTasks(dbo.GetFS()); _view.FillTreeViewTasks(dbo.GetFS(projectId));
_view.InitProjectTasks();
//_view.InitDataGridViewProjectTasks();
} }
internal void LoadTasksRecursive(string id, PTask.RecursiveRoot root) internal void LoadTasksRecursive(string id, PTask.RecursiveRoot root)
{ {