diff --git a/PROMS/VEPROMS User Interface/frmBatchRefresh.cs b/PROMS/VEPROMS User Interface/frmBatchRefresh.cs index 429c1244..c1027b1c 100644 --- a/PROMS/VEPROMS User Interface/frmBatchRefresh.cs +++ b/PROMS/VEPROMS User Interface/frmBatchRefresh.cs @@ -24,7 +24,10 @@ namespace VEPROMS private bool IsAdministratorUser = false; //C2020-035 used to control what Set Amins can do // C2017-030 - new Admin Tools user interface // pass in session info to constructor - public frmBatchRefresh(SessionInfo sessionInfo) + + private frmVEPROMS _veProms; + + public frmBatchRefresh(SessionInfo sessionInfo, frmVEPROMS veProms) { InitializeComponent(); _MySessionInfo = sessionInfo; @@ -36,7 +39,10 @@ namespace VEPROMS { AdminToolType = (E_AdminToolType)4; if (swDeleteFolder.Value) + { ResetDelTV(true); + setupProgessSteps1(); + } else ResetDelTV(false); } @@ -101,6 +107,8 @@ namespace VEPROMS private Dictionary myProcedures = new Dictionary(); private Dictionary myDocVersions = new Dictionary(); + private Dictionary myFolders = new Dictionary(); + private void frmBatchRefresh_Load(object sender, EventArgs e) { IsClosing = false;//B2017-221 Allow the batch dialog to close when waiting to process. @@ -143,6 +151,7 @@ namespace VEPROMS //myTreeNodePath = new List(); myTV.Nodes.Clear(); myDocVersions.Clear(); + myFolders.Clear(); FolderInfo fi = FolderInfo.GetTop(); TreeNode tn = myTV.Nodes.Add(fi.Name); tn.Tag = fi; @@ -166,44 +175,21 @@ namespace VEPROMS if (fi.ChildFolderCount > 0) { - if (noProcs) - { - LoadBottomLevelFolders(fi, myTVdel); - } - else - { - TreeNode tn = new TreeNode(fi.Name); - tn.Tag = fi; - tn.StateImageIndex = -1; // Hide the checkbox for the root node - LoadChildFolders(fi, tn, noProcs); - myTVdel.Nodes.Add(tn); - } + TreeNode tn = new TreeNode(fi.Name); + tn.Tag = fi; + tn.StateImageIndex = -1; // Hide the checkbox for the root node + LoadChildFolders(fi, tn, noProcs); + myTVdel.Nodes.Add(tn); } if (myTVdel.SelectedNode != null) myTVdel.SelectedNode.Expand(); - this.Cursor = Cursors.Default; - //btnFixLinks.Enabled = false; - //this.Cursor = Cursors.WaitCursor; - ////myTreeNodePath = new List(); - //myTVdel.Nodes.Clear(); - //myDocVersions.Clear(); - //FolderInfo fi = FolderInfo.GetTop(); - //TreeNode tn = myTVdel.Nodes.Add(fi.Name ); - //tn.Tag = fi; - //if (fi.ChildFolderCount > 0) - //{ - // if (noProcs) - // { - // LoadBottomLevelFolders(fi, myTVdel); - // } - // else - // LoadChildFolders(fi, tn, noProcs); - //} - //if (myTVdel.SelectedNode != null) - // myTVdel.SelectedNode.Expand(); - //this.Cursor = Cursors.Default; + //Expand if folders + if (noProcs) + myTVdel.ExpandAll(); + + this.Cursor = Cursors.Default; } // B2021-060 Higher level folders where being removed from the tree even if there was a child folder that containe a working draft set @@ -215,10 +201,13 @@ namespace VEPROMS { TreeNode tnc = tn.Nodes.Add(fic.Name); tnc.Tag = fic; + if (fic.ChildFolderCount > 0) + { if (LoadChildFolders(fic, tnc, noProcs)) loadedChildWorkingDraft = true; - // B2020-114 and C2020-035 only show folders the Set Admin can access + } + if (fic.FolderDocVersionCount > 0) { if (!LoadDocVersions(fic, tnc, noProcs)) @@ -226,40 +215,27 @@ namespace VEPROMS else loadedWorkingDraft = true; } - } - if (loadedChildWorkingDraft) loadedWorkingDraft = true; // B2021-060 if child folder working draft loaded set loadedWorkingDraft - if (tn.Parent != null && !loadedWorkingDraft) - tn.Remove(); - return loadedWorkingDraft; - } - /// - /// Load only bottom layer of folders into treenode. - /// - /// - /// - private void LoadBottomLevelFolders(FolderInfo fi, TreeView treeView) - { - foreach (FolderInfo fic in fi.SortedChildFolders) - { - if (fic.ChildFolderCount > 0) - { - // Recursively call for child folders - LoadBottomLevelFolders(fic, treeView); - } else { - if (fic.Name != "PROMS") - { - - - - // If the folder is a bottom-level folder (no child folders), add it directly to the TreeView - TreeNode tnc = treeView.Nodes.Add(fic.Name); - tnc.Tag = fic; - } + // Add the folder to the dictionary + if (!myFolders.ContainsKey(tnc)) + myFolders.Add(tnc, fic); } } + + if (loadedChildWorkingDraft) + { + loadedWorkingDraft = true; + } + + if (tn.Parent != null && !loadedWorkingDraft) + { + tn.Remove(); + } + + return loadedWorkingDraft; } + private bool LoadDocVersions(FolderInfo fic, TreeNode tnc, bool noProcs) { bool rtnval = false; @@ -1276,6 +1252,76 @@ namespace VEPROMS } } } + //After check model to select and deselect nodes on the delete and annotation tree. + private void myTV_AfterCheck_DelAnn(object sender, TreeViewEventArgs e) + { + if (e.Action != TreeViewAction.Unknown) + { + if (e.Node.Nodes.Count > 0) + { + CheckChildNodes_DelAnn(e.Node, e.Node.Checked); + } + } + + if (e.Node.Checked) + { + // Ensure child nodes follow the parent node's state + CheckChildNodes_DelAnn(e.Node, e.Node.Checked); + } + else + { + // Automatically deselect parent nodes if current node is unchecked + if (swDeleteFolder.Value) + DiselectParentNodes_DelAnn(e.Node); + } + + btnFixLinks.Enabled = AtLeastOneNodeChecked_DelAnn(); // Ensure button is enabled based on custom logic + } + private void DiselectParentNodes_DelAnn(TreeNode node) + { + TreeNode parent = node.Parent; + while (parent != null) + { + parent.Checked = false; + parent = parent.Parent; + } + } + private void DiselectChildNodes_DelAnn(TreeNodeCollection children) + { + foreach (TreeNode child in children) + { + child.Checked = false; + DiselectChildNodes_DelAnn(child.Nodes); + } + } + private void CheckChildNodes_DelAnn(TreeNode treeNode, bool isChecked) + { + foreach (TreeNode tn in treeNode.Nodes) + { + tn.Checked = isChecked; + + if (tn.Nodes.Count > 0) + CheckChildNodes_DelAnn(tn, isChecked); + } + } + private bool AtLeastOneNodeChecked_DelAnn() + { + foreach (TreeNode node in myTV.Nodes) + { + if (node.Checked || AnyChildNodeChecked_DelAnn(node)) + return true; + } + return false; + } + private bool AnyChildNodeChecked_DelAnn(TreeNode node) + { + foreach (TreeNode childNode in node.Nodes) + { + if (childNode.Checked || AnyChildNodeChecked_DelAnn(childNode)) + return true; + } + return false; + } private ProgressBarItem _ProgressBar = null; @@ -1466,8 +1512,20 @@ namespace VEPROMS break; case E_AdminToolType.Delete: - splitContainer3.Panel2Collapsed = true; - progressSteps1.Visible = false; + if (swDeleteFolder.Value) + { + splitContainer3.Panel2Collapsed = false; + progressSteps1.Items.Add(siOrphDatRecs); + lblAdmToolProgressType.Text = "Repairing: "; + progressSteps1.Visible = true; + progressSteps1.Refresh(); + } + else + { + lblAdmToolProgressType.Text = ""; + splitContainer3.Panel2Collapsed = true; + progressSteps1.Visible = false; + } break; } } @@ -1669,6 +1727,7 @@ namespace VEPROMS //C2024-005 Delete Annotations, Delete Folders private void swDeleteAnnotations_ValueChanged(object sender, EventArgs e) { + setupProgessSteps1(); swDeleteFolder.Value = !swDeleteAnnotations.Value; if (swDeleteFolder.Value) ResetDelTV(true); @@ -1678,6 +1737,7 @@ namespace VEPROMS private void swDeleteFolder_ValueChanged(object sender, EventArgs e) { + setupProgessSteps1(); swDeleteAnnotations.Value = !swDeleteFolder.Value; if (swDeleteFolder.Value) ResetDelTV(true); @@ -1691,67 +1751,54 @@ namespace VEPROMS txtResults.Clear(); txtProcess.Clear(); - if (swDeleteFolder.Value) { - //TODO process deletions of folders - txtProcess.AppendText("Deleting Folders..."); + if (FlexibleMessageBox.Show(this, "You sure you want to remove the selected folders and their contents?", "Confirm Folder Deletion", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + txtProcess.AppendText("Deleting Folders..."); - //List pil = new List(); - //foreach (TreeNode tn in myProcedures.Keys) - // if (tn.Checked) - // pil.Add(myProcedures[tn]); + //Load Selected Folders with docversions + List dvil = new List(); + foreach (TreeNode tn in myDocVersions.Keys) + if (tn.Checked) + dvil.Add(myDocVersions[tn]); - ////Load Selected Folders - Dictionary folderData = new Dictionary(); + //Load Selected Folders with docversions + List ef = new List(); + foreach (TreeNode tn in myFolders.Keys) - //List Flist = new List(); - //foreach (TreeNode tn in myDocVersions.Keys) - // if (tn.Checked) - // Flist.Add(); + if (tn.Checked) + ef.Add(myFolders[tn]); - //List dvil = new List(); - //foreach (TreeNode tn in myDocVersions.Keys) - // if (tn.Checked) - // dvil.Add(myDocVersions[tn]); - - //foreach (TreeNode tn in myTVdel.Nodes) - //{ - // if (tn.Checked) - // { - // var itemInfo = myProcedures[tn]; - // folderData.Add(itemInfo.ItemID, itemInfo.DisplayText); - // } - //} - - //ProcessDelete(dvil); + ProcessDelete(dvil, ef); + } } else { - // Write progress status - txtProcess.AppendText("Deleting Annotations..." + Environment.NewLine); + // Write progress status + txtProcess.AppendText("Deleting Annotations..."); - // Create a list of procedures the user selected + // Create a list of procedures the user selected List pil = new List(); foreach (TreeNode tn in myProcedures.Keys) if (tn.Checked) pil.Add(myProcedures[tn]); - // Create a list of doc versions the user selected + // Create a list of doc versions the user selected List dvil = new List(); foreach (TreeNode tn in myDocVersions.Keys) if (tn.Checked) dvil.Add(myDocVersions[tn]); frmAnnotationsCleanup frmAnnoDel = new frmAnnotationsCleanup(this, pil, dvil); - + frmAnnoDel.ShowDialog(); } } - private void ProcessDelete(List foldersToDelete) + private void ProcessDelete(List foldersToDelete, List emptyFoldersToDelete) { DateTime pStart = DateTime.Now; txtProcess.AppendText(Environment.NewLine); @@ -1760,11 +1807,12 @@ namespace VEPROMS foreach (var kvp in foldersToDelete) { - int itemID = (int)kvp.ItemID; - string folderName = kvp.Name; + //Gather folder information + FolderInfo fi = (FolderInfo)kvp.ActiveParent; + int itemID = (int)fi.FolderID; + string folderName = fi.Name; // Perform the deletion operation - // Assume DeleteFolderByID is a method that deletes the folder by its ItemID bool deletionSuccessful = DeleteFolderByID(itemID); // Update txtProcess with the progress @@ -1778,13 +1826,60 @@ namespace VEPROMS } txtProcess.AppendText(Environment.NewLine); } + + + //Delete non working info folders. + foreach (var kvp in emptyFoldersToDelete) + { + //Gather folder information + FolderInfo fi = (FolderInfo)kvp; + int itemID = (int)fi.FolderID; + string folderName = fi.Name; + + // Perform the deletion operation + bool deletionSuccessful = DeleteFolderByID(itemID); + + // Update txtProcess with the progress + if (deletionSuccessful) + { + txtProcess.AppendText($"Successfully deleted folder: {folderName} (ID: {itemID})"); + } + else + { + txtProcess.AppendText($"Failed to delete folder: {folderName} (ID: {itemID})"); + } + txtProcess.AppendText(Environment.NewLine); + } + + //Run Repair + int prgStpIdx = -1; + StepProgress(++prgStpIdx, 50); + PurgeDisconnectedItems(); // Orphan Items + StepProgress(prgStpIdx, 100); + + //rebuild + ResetDelTV(true); + + MessageBox.Show("Folder Deletion Completed", "Delete Folders"); + ClearStepProgress(); } - // Example deletion method - private bool DeleteFolderByID(int itemID) + + private bool DeleteFolderByID(int folderID) { - // Implement your folder deletion logic here - // Return true if deletion was successful, false otherwise - return true; // Placeholder + try + { + //Delete + Folder.DeleteFolderAdmin(folderID); + + //update treeview UI via veProms + _veProms.tv_FolderDelete(folderID); + + return true; + } + catch + { + return false; + } } public List RetrieveChkAnnotations() diff --git a/PROMS/VEPROMS User Interface/frmVEPROMS.cs b/PROMS/VEPROMS User Interface/frmVEPROMS.cs index 3290cd6c..e6861d29 100644 --- a/PROMS/VEPROMS User Interface/frmVEPROMS.cs +++ b/PROMS/VEPROMS User Interface/frmVEPROMS.cs @@ -254,6 +254,21 @@ namespace VEPROMS tc.RefreshItem(myItemInfo); } + public void tv_FolderDelete(int folderId) + { + // Create an instance of the event args if needed + var args = new vlnTreeFolderDeleteEventArgs(folderId); + + // Trigger the deletion using the event arguments + tv.RemoveFolder(args.FolderId); + + } + private bool Tv_DeleteFolder(object sender, vlnTreeFolderDeleteEventArgs args) + { + tv.RemoveFolder(args.FolderId); + return true; + } + private E_UCFImportOptions _UCFImportOptionsFromSettings; public frmVEPROMS() @@ -474,6 +489,7 @@ namespace VEPROMS tv.NodeNew += new vlnTreeViewEvent(tv_NodeNew); tv.OpenItem += new vlnTreeViewItemInfoEvent(tv_OpenItem); tv.TabDisplay += new StepPanelTabDisplayEvent(tc_PanelTabDisplay); + tv.DeleteFolder += new vlnTreeViewItemInfoDeleteFolderEvent(Tv_DeleteFolder); tv.DeleteItemInfo += new vlnTreeViewItemInfoDeleteEvent(tv_DeleteItemInfo); tv.InsertItemInfo += new vlnTreeViewItemInfoInsertEvent(tv_InsertItemInfo); tv.NodeInsert += new vlnTreeViewEvent(tv_NodeInsert); @@ -2741,7 +2757,7 @@ namespace VEPROMS void btnAdministrativeTools_Click(object sender, EventArgs e) { - frmBatchRefresh frm = new frmBatchRefresh(MySessionInfo); + frmBatchRefresh frm = new frmBatchRefresh(MySessionInfo, this); frm.ProgressBar = bottomProgBar; frm.ShowDialog(this); } diff --git a/PROMS/VEPROMS.CSLA.Library/Generated/Folder.cs b/PROMS/VEPROMS.CSLA.Library/Generated/Folder.cs index e6f8fdbd..e2b73a00 100644 --- a/PROMS/VEPROMS.CSLA.Library/Generated/Folder.cs +++ b/PROMS/VEPROMS.CSLA.Library/Generated/Folder.cs @@ -1433,6 +1433,31 @@ namespace VEPROMS.CSLA.Library throw new DbCslaException("Folder.Remove", ex); } } + + [Transactional(TransactionalTypes.TransactionScope)] + public static void DeleteFolderAdmin(int folderID) + { + if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] Folder.Remove", 0); + try + { + using (SqlConnection cn = Database.VEPROMS_SqlConnection) + { + using (SqlCommand cm = cn.CreateCommand()) + { + cm.CommandType = CommandType.StoredProcedure; + cm.CommandTimeout = Database.SQLTimeout; + cm.CommandText = "deleteFolderAdmin"; + cm.Parameters.AddWithValue("@FolderID", folderID); + cm.ExecuteNonQuery(); + } + } + } + catch (Exception ex) + { + if (_MyLog.IsErrorEnabled) _MyLog.Error("Folder.Remove", ex); + throw new DbCslaException("Folder.Remove", ex); + } + } #endregion #region Exists public static bool Exists(int folderID) diff --git a/PROMS/Volian.Controls.Library/vlnTreeView.Designer.cs b/PROMS/Volian.Controls.Library/vlnTreeView.Designer.cs index 605c0232..203fb267 100644 --- a/PROMS/Volian.Controls.Library/vlnTreeView.Designer.cs +++ b/PROMS/Volian.Controls.Library/vlnTreeView.Designer.cs @@ -1,36 +1,36 @@ namespace Volian.Controls.Library { - partial class vlnTreeView - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; + partial class vlnTreeSectionInfoEventArgs + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } - #region Component Designer generated code + #region Component Designer generated code - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - components = new System.ComponentModel.Container(); - } + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } - #endregion - } + #endregion + } } diff --git a/PROMS/Volian.Controls.Library/vlnTreeView.cs b/PROMS/Volian.Controls.Library/vlnTreeView.cs index dff305ce..ec520546 100644 --- a/PROMS/Volian.Controls.Library/vlnTreeView.cs +++ b/PROMS/Volian.Controls.Library/vlnTreeView.cs @@ -27,6 +27,7 @@ namespace Volian.Controls.Library public delegate bool vlnTreeViewBoolEvent(object sender, vlnTreeEventArgs args); public delegate bool vlnTreeViewItemInfoDeleteEvent(object sender, vlnTreeItemInfoEventArgs args); public delegate bool vlnTreeViewItemInfoInsertEvent(object sender, vlnTreeItemInfoInsertEventArgs args); + public delegate bool vlnTreeViewItemInfoDeleteFolderEvent(object sender, vlnTreeFolderDeleteEventArgs args); public delegate bool vlnTreeViewItemInfoPasteEvent(object sender, vlnTreeItemInfoPasteEventArgs args); public delegate TreeNode vlnTreeViewTreeNodeEvent(object sender, vlnTreeEventArgs args); public delegate DialogResult vlnTreeViewPropertyEvent(object sender, vlnTreePropertyEventArgs args); @@ -220,6 +221,15 @@ namespace Volian.Controls.Library } #endregion } + public class vlnTreeFolderDeleteEventArgs : EventArgs + { + public int FolderId { get; } + + public vlnTreeFolderDeleteEventArgs(int folderId) + { + FolderId = folderId; + } + } public enum E_InsertType {Before, After, Child}; public partial class vlnTreeItemInfoInsertEventArgs { @@ -427,6 +437,12 @@ namespace Volian.Controls.Library if (DeleteItemInfo != null) return DeleteItemInfo(sender, args); return false; } + public event vlnTreeViewItemInfoDeleteFolderEvent DeleteFolder; + private bool OnDeleteFolder(object sender, vlnTreeFolderDeleteEventArgs args) + { + if (DeleteItemInfo != null) return DeleteFolder(sender, args); + return false; + } public event vlnTreeViewItemInfoInsertEvent InsertItemInfo; private bool OnInsertItemInfo(object sender, vlnTreeItemInfoInsertEventArgs args) { @@ -3582,6 +3598,39 @@ namespace Volian.Controls.Library } return false; } + public void RemoveFolder(int folderId) + { + TreeNode nodeToRemove = FindNodeById(folderId, this.Nodes); + if (nodeToRemove != null) + { + // Perform the removal logic + nodeToRemove.Remove(); // This removes the node from its parent + } + } + private TreeNode FindNodeById(int folderId, TreeNodeCollection nodes) + { + foreach (TreeNode node in nodes) + { + VETreeNode vetNode = node as VETreeNode; + if (vetNode != null) + { + FolderInfo folderInfo = vetNode.VEObject as FolderInfo; + if (folderInfo != null && folderInfo.FolderID == folderId) + { + return node; + } + else + { + TreeNode foundNode = FindNodeById(folderId, node.Nodes); + if (foundNode != null) + { + return foundNode; + } + } + } + } + return null; + } private bool DeleteItemInfoAndChildren(ItemInfo ii) { DateTime dtStart = DateTime.Now;