using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; using VEPROMS.CSLA.Library; using System.IO; using System.Text.RegularExpressions; using JR.Utils.GUI.Forms; using Volian.Base.Library; using System.Linq; namespace Volian.Controls.Library { public partial class DisplayHistory : UserControl { #region Events public event DisplayHistoryReportEvent ChronologyPrintRequest; public event DisplayHistoryReportEvent SummaryPrintRequest; private void OnChronologyPrintRequest(DisplayHistoryReportEventArgs args) { if (ChronologyPrintRequest != null) ChronologyPrintRequest(this, args); } private void OnSummaryPrintRequest(DisplayHistoryReportEventArgs args) { if (SummaryPrintRequest != null) SummaryPrintRequest(this, args); } public event DisplayHistoryEvent HistorySelectionChanged; private void OnHistorySelectionChanged(DisplayHistoryEventArgs args) { if (HistorySelectionChanged != null) HistorySelectionChanged(this, args); } public event ItemRestoredHandler ItemRestored; private void OnItemRestored(ItemInfo restoredItemInfo) { if (ItemRestored != null) ItemRestored(restoredItemInfo); } public event AnnotationRestoredHandler AnnotationRestored; private void OnAnnotationRestored(AnnotationInfo restoredAnnotationInfo, ItemInfo currentItem) { if (AnnotationRestored != null) AnnotationRestored(restoredAnnotationInfo, currentItem); } #endregion private ContentAuditInfoList _ChronologyAuditList; private ContentAuditInfoList _SummaryAuditList; private AnnotationAuditInfoList _AnnotationList; private ProcedureInfo _MyProcedureInfo; public ProcedureInfo MyProcedureInfo { get { return _MyProcedureInfo; } set { if (DesignMode) return; // B2019-043 need to check if we are just saving changes to the user interface if (value is ProcedureInfo && _MyProcedureInfo is ProcedureInfo && value.ItemID == _MyProcedureInfo.ItemID) return; _MyProcedureInfo = value; if (value == null) return; SetRevDate(MyProcedureInfo.DTS); if (_MyProcedureInfo != null && RefreshRequired && lbChanges.Visible) WalkProcedure(); } } private void SetRevDate(DateTime dts) { MyRevDate = dts; RefreshRequired = true; } private ItemInfo _MyItemInfo; public ItemInfo MyItemInfo { get { return _MyItemInfo; } set { if (DesignMode) return; // B2019-043 need to check if we are just saving changes to the user interface if (value is ItemInfo && _MyItemInfo is ItemInfo && value.ItemID == _MyItemInfo.ItemID) return; _MyItemInfo = value; if (_MyItemInfo != null) { MyProcedureInfo = _MyItemInfo.MyProcedure; this.Visible = true; UpdateHistory(); if (this.lbChanges.Visible && RefreshRequired) WalkProcedure(); } else this.Visible = false; } } private EditItem _MyEditItem; public EditItem MyEditItem { get { return _MyEditItem; } set { if (DesignMode) return; // B2019-043 need to check if we are just saving changes to the user interface _MyEditItem = value; if (value != null) MyItemInfo = value.MyItemInfo; else MyItemInfo = null; } } public void RefreshList() { if (MyEditItem == null) this.Visible = false; if (this.Visible) { if (RefreshRequired) WalkProcedure(); UpdateHistory(); } } private int _ApplDisplayMode = -1; public int ApplDisplayMode { get { return _ApplDisplayMode; } set { if (MyProcedureInfo == null) return; _ApplDisplayMode = value; RefreshRequired = true; if (_ApplDisplayMode > 0) { MyProcedureInfo.MyProcedure.MyContent.RefreshContentDetails(); ProcedureConfig cfg = MyProcedureInfo.MyConfig as ProcedureConfig; cfg.SelectedSlave = value; if (cfg.Print_RevDate == null || cfg.Print_RevDate == string.Empty) SetRevDate(MyProcedureInfo.DTS); else SetRevDate(DateTime.Parse(cfg.Print_RevDate)); } else { if (MyProcedureInfo.MyDocVersion.DocVersionConfig.Unit_Count > 1) { DateTime minDts = DateTime.MaxValue; for (int j = 1; j <= MyProcedureInfo.MyDocVersion.DocVersionConfig.Unit_Count; j++) { ProcedureConfig cfg = MyProcedureInfo.MyConfig as ProcedureConfig; cfg.SelectedSlave = j; if (cfg.Print_RevDate != null && cfg.Print_RevDate != string.Empty) { if (DateTime.Parse(cfg.Print_RevDate) < minDts && DateTime.Parse(cfg.Print_RevDate) > MyProcedureInfo.DTS) minDts = DateTime.Parse(cfg.Print_RevDate); } else minDts = MyProcedureInfo.DTS; } SetRevDate(minDts); } else { ProcedureConfig cfg = MyProcedureInfo.MyConfig as ProcedureConfig; if (cfg.Print_RevDate == null || cfg.Print_RevDate == string.Empty) SetRevDate(MyProcedureInfo.DTS); else { DateTime revDate; if (!DateTime.TryParse(cfg.Print_RevDate, out revDate)) revDate = MyProcedureInfo.ChangeBarDate; // DateTime.Now; SetRevDate(revDate); //SetRevDate(DateTime.Parse(cfg.Print_RevDate)); } } } } } private DateTime _MyRevDate; public DateTime MyRevDate { get { return _MyRevDate; } set { _MyRevDate = value; } } private bool RefreshRequired = false; public DisplayHistory() { InitializeComponent(); myRTB.FormatFont = null; RefreshRequired = true; } private void lbChanges_VisibleChanged(object sender, System.EventArgs e) { if (ApplDisplayMode == -1) { ApplDisplayMode = 0; } if (lbChanges.Visible && RefreshRequired) WalkProcedure(); } private void lbChanges_SelectedIndexChanged(object sender, EventArgs e) { if (lbChanges.SelectedIndex > -1) { ContentAuditInfo cai = lbChanges.SelectedItem as ContentAuditInfo; if (cai != null) { // The following line was incorrectly showing a message stating that the item was deleted when it was not. //if (cai.DeleteStatus > 0 || (cai.DeleteStatus == 0 && cai.ActionWhen.Year == DateTime.MinValue.Year)) if (cai.DeleteStatus > 0) FlexibleMessageBox.Show("This item has been deleted.", "Deleted Item", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); else { try { OnHistorySelectionChanged(new DisplayHistoryEventArgs(cai.ItemID)); } // If the selected item is deleted display a message rather than crashing catch (Exception ex) { FlexibleMessageBox.Show("This item has been deleted.", "Deleted Item", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } } else { AnnotationAuditInfo aai = lbChanges.SelectedItem as AnnotationAuditInfo; OnHistorySelectionChanged(new DisplayHistoryEventArgs(aai.ItemID)); } } } private void UpdateHistory() { this.Cursor = Cursors.WaitCursor; //DateTime start = DateTime.Now; //Console.WriteLine(start); #region setup btnRestore.Enabled = false; myRTB.Clear(); //myRTB.LastRtf = string.Empty; myVFG.Clear(); myPicBox.Image = null; if (!tvAudits.IsDisposed) // fixes a crash that happend while debugging separate windows, have not been able to reproduce. left this IF check in just in case. - jsj 2-1-2018 tvAudits.Nodes.Clear(); if (MyItemInfo == null) { this.Cursor = Cursors.Default; return; } MyItemInfo.RefreshItemAnnotations(); #endregion //if (AnnotationOnly) //{ #region annotation deleted //annotation deleted by itemid TreeNode annotationDeleted = null; AnnotationAuditInfoList aail = AnnotationAuditInfoList.GetByItemID(MyItemInfo.ItemID); foreach (AnnotationAuditInfo aai in aail) { TreeNode tn = null; if (aai.DeleteStatus > 0) { if (annotationDeleted == null) annotationDeleted = tvAudits.Nodes.Add("Deleted Annotations"); if (tn == null) { AnnotationTypeInfo ati = AnnotationTypeInfo.Get(aai.TypeID); // B2023-066: Crash when trying to access a deleted annotation type (added the ati==null check) tn = annotationDeleted.Nodes.Add(ati == null ? "Deleted Annotation Type" : ati.Name); } TreeNode cn = tn.Nodes.Add(aai.ListString()); cn.Tag = aai; } } //end annotation deleted #endregion #region annotation changes //annotation change by annotationid TreeNode annotationHistory = null; if (MyItemInfo.ItemAnnotationCount > 0) { foreach (AnnotationInfo ai in MyItemInfo.ItemAnnotations) { TreeNode tn = null; aail = AnnotationAuditInfoList.GetByAnnotationID(ai.AnnotationID); foreach (AnnotationAuditInfo aai in aail) { if (aai.DTS != ai.DTS) { if (annotationHistory == null) annotationHistory = tvAudits.Nodes.Add("Annotation History"); if (tn == null) tn = annotationHistory.Nodes.Add(string.Format("{0} - {1}", ai.MyAnnotationType.Name, ai.SearchText)); TreeNode cn = tn.Nodes.Add(aai.ToString()); cn.Tag = aai; } } } } //end annotation change #endregion // return; //} #region content changes //content changes TreeNode contentHistory = null; if (MyItemInfo == null) return; ContentAuditInfoList cail = ContentAuditInfoList.Get(MyItemInfo.ContentID, MyItemInfo.MyProcedure.DTS); // ContentAuditInfoList cail = ContentAuditInfoList.GetChronology(MyItemInfo.MyProcedure.ItemID, MyItemInfo.ItemID, false); ContentInfo ci = ContentInfo.Get(MyItemInfo.ContentID); foreach (ContentAuditInfo cai in cail) { if (cai.DeleteStatus == 0) { if (cai.Type == 20008) { GridAuditInfoList gail = GridAuditInfoList.Get(cai.ContentID); foreach (GridAuditInfo gai in gail) { // B2022-038: Fix crash on restore of grid. If it doesn't have a ContentAuditID don't add to list (was causing a Null access // when restoring the change) if (gai.DeleteStatus == 0 && gai.ContentAuditID != 0) { if (contentHistory == null) contentHistory = tvAudits.Nodes.Add("Content Changes"); //contentHistory = tvAudits.Nodes.Add("Content History"); TreeNode tn = contentHistory.Nodes.Add(gai.ToString()); tn.Tag = gai; } } break; } // handle figures (images): else if (cai.Type == 20036 || cai.Type == 20037 || cai.Type == 20038 || cai.Type == 20039) { ImageAuditInfoList imail = ImageAuditInfoList.Get(cai.ContentID); foreach (ImageAuditInfo imai in imail) { if (imai.DeleteStatus == 0) { if (contentHistory == null) contentHistory = tvAudits.Nodes.Add("Content Changes"); TreeNode tn = contentHistory.Nodes.Add(imai.ToString()); tn.Tag = imai; } } break; } else if (cai.DTS != ci.DTS) { if (contentHistory == null) contentHistory = tvAudits.Nodes.Add("Content Changes"); //contentHistory = tvAudits.Nodes.Add("Content History"); TreeNode tn = contentHistory.Nodes.Add(cai.ListString()); tn.Tag = cai; } } } //end content changes #endregion #region items TreeNode deletedItems = null; TreeNode previousItem = null; TreeNode nextItem = null; TreeNode procedurePart = null; TreeNode sectionPart = null; TreeNode cautionPart = null; TreeNode notePart = null; TreeNode rnoPart = null; TreeNode stepPart = null; TreeNode tablePart = null; #endregion ItemAuditInfoList iail = ItemAuditInfoList.Get(MyItemInfo.ItemID); foreach (ItemAuditInfo iai in iail) { #region old style // switch (iai.Level) // { // #region previous item // case 0: //previous item // { // #region old style // //if (previousItem == null) // // previousItem = tvAudits.Nodes.Add("Deleted Previous Item"); //previousItem = tvAudits.Nodes.Add("Previous Item"); // //TreeNode tn = previousItem.Nodes.Add(iai.ToString()); // //tn.Tag = iai; // #endregion // #region new style // if (deletedItems == null) // deletedItems = tvAudits.Nodes.Add("Deleted Items"); // TreeNode tnn = deletedItems.Nodes.Add(iai.ToString()); // tnn.Tag = iai; // #endregion // break; // } // #endregion // #region next item // case 1: //next item // { // #region old style // //if (nextItem == null) // // nextItem = tvAudits.Nodes.Add("Deleted Next Item"); //nextItem = tvAudits.Nodes.Add("Next Item"); // //TreeNode tn = nextItem.Nodes.Add(iai.ToString()); // //tn.Tag = iai; // #endregion // #region new style // if (deletedItems == null) // deletedItems = tvAudits.Nodes.Add("Deleted Items"); // TreeNode tnn = deletedItems.Nodes.Add(iai.ToString()); // tnn.Tag = iai; // #endregion // break; // } // #endregion // case 2: //parts // { // #region old style // //PartAuditInfoList pail = null; // //pail = PartAuditInfoList.GetByDeleteStatus(iai.DeleteStatus); // //if (pail.Count == 0) // // pail = PartAuditInfoList.GetByItemID(iai.ItemID); // //foreach (PartAuditInfo pai in pail) // //{ // // if (pai.ContentID == MyItemInfo.ContentID) // // { // // switch (pai.FromType) // // { // // #region procedure part // // case 1: //procedures // // { // // if (procedurePart == null) // // procedurePart = tvAudits.Nodes.Add("Deleted Procedures"); //procedurePart = tvAudits.Nodes.Add("Procedures"); // // TreeNode tn = procedurePart.Nodes.Add(iai.ToString()); // // tn.Tag = iai; // // break; // // } // // #endregion // // #region section part // // case 2: //sections // // { // // if (sectionPart == null) // // sectionPart = tvAudits.Nodes.Add("Deleted Sections"); //sectionPart = tvAudits.Nodes.Add("Sections"); // // TreeNode tn = sectionPart.Nodes.Add(iai.ToString()); // // tn.Tag = iai; // // break; // // } // // #endregion // // #region caution part // // case 3: //cautions // // { // // if (cautionPart == null) // // cautionPart = tvAudits.Nodes.Add("Deleted Cautions"); //cautionPart = tvAudits.Nodes.Add("Cautions"); // // TreeNode tn = cautionPart.Nodes.Add(iai.ToString()); // // tn.Tag = iai; // // break; // // } // // #endregion // // #region note part // // case 4: //notes // // { // // if (notePart == null) // // notePart = tvAudits.Nodes.Add("Deleted Notes"); //notePart = tvAudits.Nodes.Add("Notes"); // // TreeNode tn = notePart.Nodes.Add(iai.ToString()); // // tn.Tag = iai; // // break; // // } // // #endregion // // #region rno part // // case 5: //rnos // // { // // if (rnoPart == null) // // rnoPart = tvAudits.Nodes.Add("Deleted RNOs"); //rnoPart = tvAudits.Nodes.Add("RNOs"); // // TreeNode tn = rnoPart.Nodes.Add(iai.ToString()); // // tn.Tag = iai; // // break; // // } // // #endregion // // #region step part // // case 6: //steps // // { // // if (stepPart == null) // // stepPart = tvAudits.Nodes.Add("Deleted Steps"); //stepPart = tvAudits.Nodes.Add("Steps"); // // TreeNode tn = stepPart.Nodes.Add(iai.ToString()); // // tn.Tag = iai; // // break; // // } // // #endregion // // #region table part // // case 7: //tables // // { // // if (tablePart == null) // // tablePart = tvAudits.Nodes.Add("Deleted Tables"); //tablePart = tvAudits.Nodes.Add("Tables"); // // TreeNode tn = tablePart.Nodes.Add(iai.ToString()); // // tn.Tag = iai; // // break; // // } // // #endregion // // } // // } // //} // #endregion // #region new style // if (deletedItems == null) // deletedItems = tvAudits.Nodes.Add("Deleted Items"); // TreeNode tnn = deletedItems.Nodes.Add(iai.ToString()); // tnn.Tag = iai; // #endregion // break; // } //} #endregion #region new style // B2023-117 if DeleteStatus is zero,don't try to get Audit Info List if (iai.DeleteStatus == 0) continue; if (deletedItems == null) deletedItems = tvAudits.Nodes.Add("Deleted Items"); string strR = null; // see if a deleted procedure, from itemaudit, get contentaudit ContentAuditInfoList lDelC = ContentAuditInfoList.GetByDeleteStatus(iai.DeleteStatus); foreach (ContentAuditInfo delC in lDelC) { if (delC.Type >= 0 && delC.Type < 1000) { int indx = delC.Config.IndexOf("DelProcReason"); if (indx >= 0 && delC.Config.Length > indx + 15) // 15 accounts for 'DelProcReason = "' { string reason = delC.Config.Substring(indx + 15); if (reason != null && reason.Length > 0) { indx = reason.IndexOf("\""); if (indx > 0) strR = reason.Substring(0, reason.IndexOf("\"")); } break; } } } TreeNode tnn = deletedItems.Nodes.Add(iai.ToString() + "; Reason: " + strR); tnn.Tag = iai; #endregion } //Console.WriteLine("UpdateHistory: {0} seconds",TimeSpan.FromTicks(DateTime.Now.Ticks - start.Ticks).TotalSeconds); this.Cursor = Cursors.Default; } // B2020-156: If time is at midnight, only check date. private bool CompareDateOrDateTime(DateTime dt1, DateTime dt2) { if (dt1.TimeOfDay == TimeSpan.Zero || dt2.TimeOfDay == TimeSpan.Zero) { if (dt1.Date > dt2.Date) return true; return false; } if (dt1 > dt2) return true; return false; } private void WalkProcedure() { //return; this.ParentForm.Cursor = Cursors.WaitCursor; Application.DoEvents(); //DateTime start = DateTime.Now; //Console.WriteLine(start); lbChanges.Items.Clear(); if (MyProcedureInfo == null) { this.ParentForm.Cursor = Cursors.Default; btnViewSummaryReport.Enabled = btnViewChronologyReport.Enabled = cbSumExcludeAnn.Enabled = DT_SumAsOf.Enabled = lbChanges.Items.Count > 0; return; } ContentAuditInfoList cail2; ContentAuditInfoList cail3; AnnotationAuditInfoList aail2; if (ApplDisplayMode > 0) { cail2 = ContentAuditInfoList.GetChronologyByUnit(MyProcedureInfo.ItemID, MyProcedureInfo.ItemID, false, ApplDisplayMode, MyProcedureInfo.ChangeBarDate); cail3 = ContentAuditInfoList.GetSummaryByUnit(MyProcedureInfo.ItemID, MyProcedureInfo.ItemID, false, ApplDisplayMode, MyProcedureInfo.ChangeBarDate); aail2 = AnnotationAuditInfoList.GetChronologyByUnit(MyProcedureInfo.ItemID, MyProcedureInfo.ItemID, ApplDisplayMode, MyProcedureInfo.ChangeBarDate); } else { cail2 = ContentAuditInfoList.GetChronology(MyProcedureInfo.ItemID, MyProcedureInfo.ItemID, false, MyProcedureInfo.ChangeBarDate); cail3 = ContentAuditInfoList.GetSummary(MyProcedureInfo.ItemID, MyProcedureInfo.ItemID, false, MyProcedureInfo.ChangeBarDate); aail2 = AnnotationAuditInfoList.GetChronology(MyProcedureInfo.ItemID, MyProcedureInfo.ItemID, MyProcedureInfo.ChangeBarDate); } //Console.WriteLine("WalkProcedure cail2: {0} seconds", TimeSpan.FromTicks(DateTime.Now.Ticks - start.Ticks).TotalSeconds); _ChronologyAuditList = cail2; _SummaryAuditList = cail3; //Console.WriteLine("WalkProcedure aail2: {0} seconds", TimeSpan.FromTicks(DateTime.Now.Ticks - start.Ticks).TotalSeconds); _AnnotationList = aail2; foreach (ContentAuditInfo cai in cail2) { // B2020-156: When procedure title is changed, it does not print in Summary/Chronolgy of changes. // Need to only check the date (not the date/time) for some procedures, the original item was listed // in the list box and should not be because some MyRevDate's did not have time included. if (CompareDateOrDateTime(cai.DTS, MyRevDate) || cai.ActionWhen > MyRevDate) { string itemTitle = FixPath(cai.Path); lbChanges.Items.Add(cai); } } foreach (AnnotationAuditInfo aai in aail2) { string stepnum = string.Empty; foreach (ContentAuditInfo cai in cail2) { if (cai.ContentID == aai.IContentID) { stepnum = FixPath(cai.Path); break; } } if (stepnum == string.Empty) { ItemInfo iii = aai.MyItemInfo; if (iii != null) stepnum = FixPath(iii.SearchPath); } if (aai.DTS > MyRevDate) lbChanges.Items.Add(aai); } //Console.WriteLine("WalkProcedure fini: {0} seconds", TimeSpan.FromTicks(DateTime.Now.Ticks - start.Ticks).TotalSeconds); this.ParentForm.Cursor = Cursors.Default; btnViewSummaryReport.Enabled = btnViewChronologyReport.Enabled = cbSumExcludeAnn.Enabled = DT_SumAsOf.Enabled = lbChanges.Items.Count > 0; RefreshRequired = false; return; } private static string FixPath(string path) { string itemTitle = Regex.Replace(path, "^..+?\\u0007", ""); itemTitle = itemTitle.Replace("\x11", itemTitle[0] == '\x11' ? "" : " - ").Replace(@"\u8209?", "-").Replace(@"\u9586?", @"\"); return itemTitle; } private void btnViewChronologyReport_Click(object sender, EventArgs e) { RefreshList(); //if (lbChanges.Items.Count > 0) //{ //jcb added 20120425 to suppress annotations in report //jcb commented out 20130409 per bug C2012-022 //_AnnotationList = AnnotationAuditInfoList.GetChronology(0, 0, MyProcedureInfo.ChangeBarDate); //added setting selected slave in order for reports to replace unit number,etc jcb 20101010 MyItemInfo.MyProcedure.MyDocVersion.DocVersionConfig.SelectedSlave = ApplDisplayMode; // OnChronologyPrintRequest(new DisplayHistoryReportEventArgs(Volian.Base.Library.VlnSettings.TemporaryFolder + @"\MyChronology.pdf", MyItemInfo.MyProcedure, _ChronologyAuditList, _AnnotationList)); OnChronologyPrintRequest(new DisplayHistoryReportEventArgs(string.Format(@"{0}\{1} Chronology of Changes.pdf", Volian.Base.Library.VlnSettings.TemporaryFolder, MyItemInfo.MyProcedure.PDFNumber), MyItemInfo.MyProcedure, _ChronologyAuditList, _AnnotationList)); //} } private void btnViewSummaryReport_Click(object sender, EventArgs e) { RefreshList(); //if (lbChanges.Items.Count > 0) //{ //jcb added 20120425 to suppress annotations in report //jcb commented out 20130409 per bug C2012-022 //_AnnotationList = AnnotationAuditInfoList.GetChronology(0, 0, MyProcedureInfo.ChangeBarDate); //added setting selected slave in order for reports to replace unit number,etc jcb 20101010 MyItemInfo.MyProcedure.MyDocVersion.DocVersionConfig.SelectedSlave = ApplDisplayMode; var dhr = new DisplayHistoryReportEventArgs(string.Format(@"{0}\{1} Summary of Changes.pdf", Volian.Base.Library.VlnSettings.TemporaryFolder, MyItemInfo.MyProcedure.PDFNumber), MyItemInfo.MyProcedure, null, null); //C2024- 038 - Summary of Changes report generation enhancements //check if need to modify // _SummaryAuditList if (DT_SumAsOf.Checked) dhr.AuditList = FilterSummaryByDate(_SummaryAuditList, DT_SumAsOf.Value); else dhr.AuditList = _SummaryAuditList; //C2024- 038 - Summary of Changes report generation enhancements // if Exclude Annotations Checked // send an empty list instead of //_AnnotationList if (cbSumExcludeAnn.Checked) dhr.AnnotationList = new AnnotationAuditInfoList(null); else if (DT_SumAsOf.Checked) dhr.AnnotationList = FilterSummaryByDate_Annotations(_AnnotationList, DT_SumAsOf.Value); else { dhr.AnnotationList = _AnnotationList; } OnSummaryPrintRequest(dhr); } //C2024- 038 - Summary of Changes report generation enhancements //modify _SummaryAuditList //to limit to a specific date private ContentAuditInfoList FilterSummaryByDate(ContentAuditInfoList summaryAuditList, DateTime value) { List slst = summaryAuditList.Clone().ToList(); //Grab the first change to each item before the date and set that to the AsOf date foreach (ContentAuditInfo firstbeforedate in slst.GroupBy(x => x.ItemID).Select(x => x.OrderByDescending(y => y.DTS).FirstOrDefault(d => d.DTS < value))) { if (firstbeforedate != null && firstbeforedate.ActionWhat != "Deleted") { firstbeforedate.ActionWhat = $"As Of: {value.ToShortDateString()}"; } } //remove all items before the date we are checking against //note that for deleted - sometimes the DTS is not correct and //need to use the ActionWhen slst.RemoveAll(x => x.DTS < value && !x.ActionWhat.StartsWith("As Of:") && (x.ActionWhat != "Deleted" || (x.ActionWhen < x.DTS ? x.DTS : x.ActionWhen) < value)); //remove all items where first text matches the last text //unless it was added after the date we are checking against //or the last item is a deletion that occurred after //the date we are checking against var itms = slst.Select(x => x.ItemID).Distinct().ToList(); foreach (int itmID in itms) { ContentAuditInfo first = slst.Where(i => i.ItemID == itmID).OrderBy(y => y.DTS).FirstOrDefault(); ContentAuditInfo last = slst.Where(i => i.ItemID == itmID).OrderByDescending(y => y.DTS).FirstOrDefault(); if (first != null && last != null && first.DTS < value && (last.ActionWhat != "Deleted" || (last.ActionWhen < last.DTS ? last.DTS : last.ActionWhen) < value) && ItemInfo.ConvertToDisplayText(first.Text) == ItemInfo.ConvertToDisplayText(last.Text)) slst.RemoveAll(x => x.ItemID == itmID); } return new ContentAuditInfoList(slst); } //C2024- 038 - Summary of Changes report generation enhancements //modify _SummaryAuditList //to limit to a specific date private AnnotationAuditInfoList FilterSummaryByDate_Annotations(AnnotationAuditInfoList annotationAuditList, DateTime value) { return new AnnotationAuditInfoList(annotationAuditList.Where(x => x.DTS >= value).ToList()); } private void btnRefresh_Click(object sender, EventArgs e) { RefreshList(); } private void btnRestore_Click(object sender, EventArgs e) { MyEditItem.SaveContents(); TreeNode tn = tvAudits.SelectedNode; if (tn.Tag is ContentAuditInfo) { ContentAuditInfo cai = tn.Tag as ContentAuditInfo; // if original equation is restored, don't allow it because it is empty: if ((cai.Type > 20999 && cai.Type < 21010) && cai.ActionWhat.ToUpper() == "ORIGINAL") { FlexibleMessageBox.Show(this, "Cannot restore original empty or new equation.", "Warning on restore", MessageBoxButtons.OK); return; } if (FlexibleMessageBox.Show(this, "Do you want to restore this content change?", "Confirm Content Change Restore", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes) { ROFstInfo myRoFst = null; // B2017-118 If No ROFST don't crash if (MyItemInfo.MyDocVersion.DocVersionAssociations != null) myRoFst = MyItemInfo.MyDocVersion.DocVersionAssociations[0].MyROFst; if (myRoFst != null) myRoFst.ROTableUpdate += new ROFstInfoROTableUpdateEvent(myRoFst_ROTableUpdate); ContentInfo ci = ContentInfo.RestoreContent(cai, myRoFst); if (myRoFst != null) myRoFst.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(myRoFst_ROTableUpdate); RefreshRequired = true; UpdateHistory(); MyItemInfo.RefreshConfig(); // B2017-209: see if the restore has invalid enhanced data, i.e. the source step that it 'links to' does not exist. // Note that this is only applicable when restoring an enhanced step if its linked source step is deleted because // the enhanced (background/deviation/etc) cannot be deleted unless they are unlinked first. if (MyItemInfo.IsEnhancedStep) { // get id for step that is linked & see if it exists - if not, clear the enhanced config data StepConfig sc = MyItemInfo.MyConfig as StepConfig; ItemInfo iexists = ItemInfo.Get(sc.MyEnhancedDocuments[0].ItemID); if (iexists == null) MyItemInfo.RemoveEnhancedFromConfig(true); } myRTB.Clear(); myVFG.Clear(); MyEditItem.SetAllTabs(); MyItemInfo.UpdateTransitionText(); MyItemInfo.UpdateROText(); } } if (tn.Tag is ItemAuditInfo) { ItemAuditInfo iai = tn.Tag as ItemAuditInfo; if (FlexibleMessageBox.Show(this, string.Format("Do you want to restore this {0}?", iai.ItemType), string.Format("Confirm {0} Restore", iai.ItemType), MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes) { //Console.WriteLine("DisplayHistory.btnRestore_Click @ {0}", DateTime.Now); ItemInfo ii = null; if (iai.Level == 2) { ROFstInfo myRoFst = null; // B2017-118 If No ROFST don't crash if (MyItemInfo.MyDocVersion.DocVersionAssociations != null) myRoFst = MyItemInfo.MyDocVersion.DocVersionAssociations[0].MyROFst; if (myRoFst != null) myRoFst.ROTableUpdate += new ROFstInfoROTableUpdateEvent(myRoFst_ROTableUpdate); ii = MyItemInfo.RestoreItem(iai, myRoFst); if (myRoFst != null) myRoFst.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(myRoFst_ROTableUpdate); //_MyEditItem.AddChild((E_FromType)fromtype, contenttype); //ii.ItemParts[0].FromType //ii.MyContent.Type EditItem nextItem = MyEditItem.GetNextItem((E_FromType)ii.ItemParts[0].FromType, ii); //MyEditItem.AddChild(ii.MyContent.Text, (E_FromType)ii.ItemParts[0].FromType, (int)ii.MyContent.Type, null); if (ii.IsStep) ii = StepInfo.Get(ii.ItemID); else if (ii.IsSection) ii = SectionInfo.Get(ii.ItemID); else if (ii.IsProcedure) ii = ProcedureInfo.Get(ii.ItemID); if (nextItem != null) { switch (nextItem.MyChildRelation) { case ChildRelation.None: break; case ChildRelation.After: MyEditItem.AddChildAfter(ii, nextItem); break; case ChildRelation.Before: MyEditItem.AddChildBefore(ii, nextItem); break; case ChildRelation.RNO: MyEditItem.AddChildRNO(ii, nextItem); break; default: break; } } else { switch ((E_FromType)ii.ItemParts[0].FromType) { case E_FromType.Caution: MyEditItem.AddChildBefore(ii, nextItem); break; case E_FromType.Note: MyEditItem.AddChildBefore(ii, nextItem); break; case E_FromType.Procedure: MyEditItem.AddChildAfter(ii, nextItem); break; case E_FromType.RNO: MyEditItem.AddChildRNO(ii, nextItem); break; case E_FromType.Section: MyEditItem.AddChildAfter(ii, nextItem); break; case E_FromType.Step: MyEditItem.AddChildAfter(ii, nextItem); break; case E_FromType.Table: MyEditItem.AddChildAfter(ii, nextItem); break; case E_FromType.SupInfo: MyEditItem.AddChildSupInfo(ii, nextItem); break; default: MyEditItem.AddChildAfter(ii, nextItem); break; } } } else { ROFstInfo myRoFst = null; // B2017-118 If No ROFST don't crash if (MyItemInfo.MyDocVersion.DocVersionAssociations != null) myRoFst = MyItemInfo.MyDocVersion.DocVersionAssociations[0].MyROFst; if (myRoFst != null) myRoFst.ROTableUpdate += new ROFstInfoROTableUpdateEvent(myRoFst_ROTableUpdate); ii = MyItemInfo.RestoreSibling(iai, myRoFst); if (myRoFst != null) myRoFst.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(myRoFst_ROTableUpdate); if (ii.IsStep) ii = StepInfo.Get(ii.ItemID); else if (ii.IsSection) ii = SectionInfo.Get(ii.ItemID); else if (ii.IsProcedure) ii = ProcedureInfo.Get(ii.ItemID); EditItem nextItem = iai.Level == 0 ? MyEditItem : MyEditItem.MyNextEditItem; switch (MyEditItem.MyChildRelation) { case ChildRelation.None: break; case ChildRelation.After: MyEditItem.ActiveParent.AddChildAfter(ii, nextItem); break; case ChildRelation.Before: MyEditItem.ActiveParent.AddChildBefore(ii, nextItem); break; case ChildRelation.RNO: MyEditItem.ActiveParent.AddChildRNO(ii, nextItem); break; case ChildRelation.SupInfo: MyEditItem.ActiveParent.AddChildSupInfo(ii, nextItem); break; default: break; } ii.UpdateTransitionText(); ii.UpdateROText(); } if (MyEditItem.MyPreviousEditItem != null) MyEditItem.MyPreviousEditItem.SetAllTabs(); else MyEditItem.SetAllTabs(); RefreshRequired = true; UpdateHistory(); myRTB.Clear(); myVFG.Clear(); } } if (tn.Tag is AnnotationAuditInfo) { AnnotationAuditInfo aai = tn.Tag as AnnotationAuditInfo; if (FlexibleMessageBox.Show(this, "Do you want to restore this annotation?", "Confirm Annotation Restore", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes) { AnnotationInfo ai = AnnotationInfo.RestoreAnnotation(aai); // B2023-072: Don't crash if annotation type was deleted for the restore annotation if (ai == null) { FlexibleMessageBox.Show(this, "Annotation Type was deleted, cannot restore Annotation Type\r\nCopy text from window in Change Details and paste into new annotation to restore the text.", "Annotation Type Deleted", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } OnAnnotationRestored(ai, ai.MyItem); RefreshRequired = true; UpdateHistory(); myRTB.Clear(); myVFG.Clear(); } } if (tn.Tag is GridAuditInfo) { GridAuditInfo gai = tn.Tag as GridAuditInfo; if (FlexibleMessageBox.Show(this, "Do you want to restore this table?", "Confirm Table Restore", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes) { ContentAuditInfo cai = ContentAuditInfo.Get(gai.ContentAuditID); ROFstInfo myRoFst = null; // B2017-118 If No ROFST don't crash if (MyItemInfo.MyDocVersion.DocVersionAssociations != null) myRoFst = MyItemInfo.MyDocVersion.DocVersionAssociations[0].MyROFst; if (myRoFst != null) myRoFst.ROTableUpdate += new ROFstInfoROTableUpdateEvent(myRoFst_ROTableUpdate); ContentInfo ci = ContentInfo.RestoreContent(cai, myRoFst); if (myRoFst != null) myRoFst.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(myRoFst_ROTableUpdate); RefreshRequired = true; UpdateHistory(); myRTB.Clear(); myVFG.Clear(); } } if (tn.Tag is ImageAuditInfo) { ImageAuditInfo iai = tn.Tag as ImageAuditInfo; if (FlexibleMessageBox.Show(this, "Do you want to restore this image?", "Confirm Image Restore", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes) { ContentInfo ci = ContentInfo.RestoreImage(iai); RefreshRequired = true; UpdateHistory(); myRTB.Clear(); myVFG.Clear(); myPicBox.Image = null; // myPicBox is the PictureBox that shows the selected figure } } } List myRoFst_ROTableUpdate(object sender, ROFstInfoROTableUpdateEventArgs args) { return VlnFlexGrid.ROTableUpdate(sender, args); } private static UserInfo _MyUserInfo = null; public static UserInfo MyUserInfo { get { return _MyUserInfo; } set { _MyUserInfo = value; } } private void DisplayTagRTF(TreeNode tn) { if (tn.Tag != null) { if (tn.Tag is GridAuditInfo) { btnRestore.Enabled = UserInfo.CanEdit(MyUserInfo, MyProcedureInfo.MyDocVersion);//CanRestore(); GridAuditInfo gai = tn.Tag as GridAuditInfo; myPicBox.Visible = false; myVFG.Visible = true; myVFG.BringToFront(); panel1.Invalidate(new Rectangle(0, 0, myVFG.Width + 4, 4)); panel1.Invalidate(new Rectangle(0, 0, 4, myVFG.Height + 4)); myRTB.Visible = false; panel1.Visible = false; using (StringReader sr = new StringReader(gai.Data)) { myVFG.ReadXml(sr); sr.Close(); } panel1.Visible = true; return; } if (tn.Tag is ImageAuditInfo) { btnRestore.Enabled = UserInfo.CanEdit(MyUserInfo, MyProcedureInfo.MyDocVersion); ImageAuditInfo iai = tn.Tag as ImageAuditInfo; myVFG.Visible = false; myRTB.Visible = false; myPicBox.Visible = true; myPicBox.BringToFront(); panel1.Invalidate(new Rectangle(0, 0, myPicBox.Width + 4, 4)); panel1.Invalidate(new Rectangle(0, 0, 4, myPicBox.Height + 4)); panel1.Visible = false; ImageInfo imgin = ImageInfo.Get(iai.ContentID); // check if image data was compressed, i.e. config stores original size: ImageConfig imgCfg = new ImageConfig(imgin); byte[] imgData = iai.Data; if (imgCfg.Image_DataSize > 0) imgData = ROImageInfo.Decompress(imgData, imgCfg.Image_DataSize); MemoryStream ms = new MemoryStream(imgData); myPicBox.Image = System.Drawing.Image.FromStream(ms); myPicBox.Width = Math.Max(myPicBox.Image.Width, panel1.Width); myPicBox.Height = Math.Max(myPicBox.Image.Height, 200); panel1.Visible = true; return; } if (tn.Tag is ContentAuditInfo) { btnRestore.Enabled = UserInfo.CanEdit(MyUserInfo, MyProcedureInfo.MyDocVersion);//CanRestore(); myVFG.Clear(); ContentAuditInfo cai = tn.Tag as ContentAuditInfo; GridAuditInfoList gail = GridAuditInfoList.Get(cai.ContentID); if (gail.Count > 0) { foreach (GridAuditInfo gai in gail) { if (gai.DTS == cai.DTS) { myVFG.Visible = true; myVFG.BringToFront(); myRTB.Visible = false; using (StringReader sr = new StringReader(gai.Data)) { myVFG.ReadXml(sr); sr.Close(); } return; } } } else { myRTB.Visible = true; myRTB.BringToFront(); myVFG.Visible = false; // myRTB.Font = new Font("Arial", 12, FontStyle.Regular); // myRTB.Text = cai.Text; //myRTB.SetupRichText("bozo", MyItemInfo.FormatStepData == null ? MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font : MyItemInfo.FormatStepData.Font); //myRTB.LastRtf = string.Empty; myRTB.SetupRichText(cai.Text, MyItemInfo.FormatStepData == null ? MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font : MyItemInfo.FormatStepData.Font); } } if (tn.Tag is ItemAuditInfo) { btnRestore.Enabled = UserInfo.CanEdit(MyUserInfo, MyProcedureInfo.MyDocVersion);//CanRestore(); ItemAuditInfo iai = tn.Tag as ItemAuditInfo; ContentAuditInfoList cail = ContentAuditInfoList.Get(iai.ContentID); foreach (ContentAuditInfo cai in cail) { if (cai.DeleteStatus == iai.DeleteStatus) { //myRTB.Font = new Font("Arial", 12, FontStyle.Regular); //myRTB.Text = cai.Text; myRTB.SetupRichText(cai.Text, MyItemInfo.FormatStepData == null ? MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font : MyItemInfo.FormatStepData.Font); } } } if (tn.Tag is AnnotationAuditInfo) { btnRestore.Enabled = UserInfo.CanEdit(MyUserInfo, MyProcedureInfo.MyDocVersion);//CanRestore(); AnnotationAuditInfo iai = tn.Tag as AnnotationAuditInfo; myRTB.Font = new Font("Arial", 12, FontStyle.Regular); myRTB.Rtf = iai.RtfText; //myRTB.Rtf = iai.RtfText; } } else { btnRestore.Enabled = false; myRTB.Clear(); myVFG.Clear(); } } private void tvAudits_AfterSelect(object sender, TreeViewEventArgs e) { DisplayTagRTF(e.Node); } private void DisplayHistory_Resize(object sender, EventArgs e) { tvAudits.Height = ((tcpDetail.Height - btnRestore.Height) / 4) * 3; } public void RefreshChangeList() { myTimer.Enabled = false; myTimer.Enabled = true; } // B2019-161 When tracking timing time this action private static VolianTimer _TimeActivity = new VolianTimer("DisplayHistory myTimer_Tick", 974); private void myTimer_Tick(object sender, System.EventArgs e) { _TimeActivity.Open(); myTimer.Enabled = false; if (this.lbChanges.Visible) this.tabControl1.SelectedTab = tabItem2; UpdateHistory(); RefreshRequired = true; _TimeActivity.Close(); } } public delegate void ItemRestoredHandler(ItemInfo restoredItemInfo); public delegate void AnnotationRestoredHandler(AnnotationInfo restoredAnnotationInfo, ItemInfo currentItem); public delegate void DisplayHistoryReportEvent(object sender, DisplayHistoryReportEventArgs args); public delegate void DisplayHistoryEvent(object sender, DisplayHistoryEventArgs args); public class DisplayHistoryReportEventArgs { private string _ReportName; public string ReportTitle { get { return _ReportName; } set { _ReportName = value; } } private ProcedureInfo _ProcedureInfo; public ProcedureInfo ProcedureInfo { get { return _ProcedureInfo; } set { _ProcedureInfo = value; } } private ContentAuditInfoList _AuditList; public ContentAuditInfoList AuditList { get { return _AuditList; } set { _AuditList = value; } } private AnnotationAuditInfoList _AnnotationList; public AnnotationAuditInfoList AnnotationList { get { return _AnnotationList; } set { _AnnotationList = value; } } public DisplayHistoryReportEventArgs(string reportName, ProcedureInfo procedureInfo, ContentAuditInfoList auditList, AnnotationAuditInfoList annotationList) { _ReportName = reportName; _ProcedureInfo = procedureInfo; _AuditList = auditList; _AnnotationList = annotationList; } } public class DisplayHistoryEventArgs { private int _ItemID; public int ItemID { get { return _ItemID; } set { _ItemID = value; } } public DisplayHistoryEventArgs(int itemID) { _ItemID = itemID; } } }