using System; using System.Collections.Generic; using System.Data; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Forms; using com.sun.tools.@internal.ws.processor.model; using Comal.Classes; using InABox.Clients; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF; using Syncfusion.Data.Extensions; using Syncfusion.UI.Xaml.Grid; using Syncfusion.UI.Xaml.Grid.Helpers; using HorizontalAlignment = System.Windows.HorizontalAlignment; using MessageBox = System.Windows.MessageBox; using OpenFileDialog = Microsoft.Win32.OpenFileDialog; using UserControl = System.Windows.Controls.UserControl; namespace PRSDesktop { public class MileStoneBlock { public Guid ID { get; set; } public String Revision { get; set; } public JobDocumentSetMileStoneStatus Status { get; set; } public DateTime Date { get; set; } public System.Drawing.Color Color { get; set; } } public class MileStoneConverter : IValueConverter { public object Convert(object value, Type t, object parameter, CultureInfo culture) { try { if (value == null) return ""; var block = Serialization.Deserialize(value.ToString()); if (String.Equals(parameter, "ID")) return block.ID; if (String.Equals(parameter, "Revision")) return String.IsNullOrWhiteSpace(block.Revision) ? "--" : String.Format("Rev {0}",block.Revision); if (String.Equals(parameter, "Status")) return block.Status.ToString().SplitCamelCase(); if (String.Equals(parameter, "Date")) return String.Format("{0:dd MMM yy}", block.Date); if (String.Equals(parameter, "Color")) return "Red"; //ImageUtils.ColorToString(block.Color); return parameter.ToString(); } catch (Exception e) { return e.Message; } } public object ConvertBack(object value, Type t, object parameter, CultureInfo culture) { return value.Equals(false) ? DependencyProperty.UnsetValue : parameter; } } public partial class JobDocumentSetGrid : UserControl { private struct MileStone { public Guid TypeID { get; set; } public CoreRow Row { get; set; } } private struct MileStoneType { public String Code { get; set; } public String Description { get; set; } public Dictionary> SetMileStones { get; set; } public List Columns { get; set; } } public Guid JobID { get; set; } public Guid FolderID { get; set; } private Dictionary _types = null; private CoreTable _milestones = null; private CoreTable _documentSets = null; private CoreTable _files = null; public JobDocumentSetGrid() { InitializeComponent(); AddImage.Source = PRSDesktop.Resources.add.AsBitmapImage(); EditImage.Source = PRSDesktop.Resources.pencil.AsBitmapImage(); DeleteImage.Source = PRSDesktop.Resources.delete.AsBitmapImage(); } private Dictionary _statuscolors = new Dictionary() { { JobDocumentSetMileStoneStatus.InProgress, System.Drawing.Color.LightYellow }, { JobDocumentSetMileStoneStatus.OnHold, System.Drawing.Color.Silver }, { JobDocumentSetMileStoneStatus.InfoRequired, System.Drawing.Color.Silver }, { JobDocumentSetMileStoneStatus.Submitted, System.Drawing.Color.Orange }, { JobDocumentSetMileStoneStatus.Approved, System.Drawing.Color.LightGreen }, { JobDocumentSetMileStoneStatus.Rejected, System.Drawing.Color.Gray }, { JobDocumentSetMileStoneStatus.Cancelled, System.Drawing.Color.Gray }, }; public void Refresh() { var setfilter = new Filter(x => x.Job.ID).IsEqualTo(JobID); if (FolderID != Guid.Empty) setfilter = setfilter.And(x => x.Folder.ID).IsEqualTo(FolderID); MultiQuery query = new MultiQuery(); query.Add( setfilter, new Columns(x=>x.ID) .Add(x=>x.Code) .Add(x=>x.Description) ); var milestonefilter = new Filter(x => x.DocumentSet.Job.ID).IsEqualTo(JobID); if (FolderID != Guid.Empty) milestonefilter = milestonefilter.And(x => x.DocumentSet.Folder.ID).IsEqualTo(FolderID); query.Add( milestonefilter, new Columns(x => x.ID) .Add(x=>x.DocumentSet.ID) .Add(x => x.Type.ID) .Add(x => x.Type.Code) .Add(x => x.Status) .Add(x => x.Revision) .Add(x => x.Submitted) .Add(x => x.Closed) ); if (_types == null) { query.Add( null, new Columns(x => x.ID) .Add(x => x.Code) .Add(x => x.Description), new SortOrder(x => x.Sequence) ); } query.Query(); _documentSets = query.Get(); _milestones = query.Get(); if (_types == null) { _types = query.Get().ToDictionary( x => x.ID, r => new MileStoneType() { Code = r.Get(c => c.Code), Description = r.Get(c => c.Description), SetMileStones = new Dictionary>(), Columns = new List() } ); } else { foreach (var typeid in _types.Keys) _types[typeid].SetMileStones.Clear(); } var documentsets = new DataTable(); documentsets.Columns.Add("ID", typeof(Guid)); documentsets.Columns.Add("Code", typeof(String)); documentsets.Columns.Add("Description", typeof(String)); var milestones = _milestones.ToLookup( x => x.DocumentSet.ID, r => new MileStone() { TypeID = r.Get(c => c.Type.ID), Row = r } ); foreach (var milestone in milestones) { foreach (var entry in milestone) { if (!_types[entry.TypeID].SetMileStones.ContainsKey(milestone.Key)) _types[entry.TypeID].SetMileStones[milestone.Key] = new List(); if (_hidesuperceded) _types[entry.TypeID].SetMileStones[milestone.Key].Clear(); _types[entry.TypeID].SetMileStones[milestone.Key].Add(entry.Row); } } foreach (var typeid in _types.Keys) { int count = 1; foreach (var setkey in _types[typeid].SetMileStones.Keys) count = Math.Max(count,_types[typeid].SetMileStones[setkey].Count); for (int i = 1; i <= count; i++) { String column = String.Format("{0}_{1}", _types[typeid].Code, i); documentsets.Columns.Add(column, typeof(String)); _types[typeid].Columns.Add(column); } } foreach (var setrow in _documentSets.Rows) { Guid setid = setrow.Get(x => x.ID); var datarow = documentsets.Rows.Add(); datarow["ID"] = setid; datarow["Code"] = setrow.Get(c => c.Code); datarow["Description"] = setrow.Get(c => c.Description); foreach (var typeid in _types.Keys) { if (_types[typeid].SetMileStones.TryGetValue(setid, out var rows)) { int i = 1; foreach (var row in rows) { MileStoneBlock block = new MileStoneBlock(); block.ID = row.Get(c => c.ID); block.Revision = row.Get(c => c.Revision); block.Status = row.Get(c => c.Status); block.Date = row.Get(c => c.Closed); if (block.Date.IsEmpty()) block.Date = row.Get(c => c.Submitted); block.Color = _statuscolors[block.Status]; datarow[String.Format("{0}_{1}", _types[typeid].Code, i)] = Serialization.Serialize(block); i++; } } } } dataGrid.ItemsSource = null; stackedHeaderRow.StackedColumns.Clear(); stackedHeaderRow.StackedColumns.Add(new StackedColumn() { ChildColumns = "ID,Code,Description", HeaderText = "Document Register" }); foreach (var typeid in _types.Keys) { stackedHeaderRow.StackedColumns.Add(new StackedColumn() { ChildColumns = String.Join(",", _types[typeid].Columns), HeaderText = _types[typeid].Code }); } dataGrid.ItemsSource = documentsets; } private void DataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e) { e.Column.HorizontalHeaderContentAlignment = HorizontalAlignment.Center; if (String.Equals(e.Column.MappingName, "ID")) e.Column.Width = 0; else if (String.Equals(e.Column.MappingName, "Code")) e.Column.Width = 120; else if (String.Equals(e.Column.MappingName, "Description")) { e.Column.ColumnSizer = GridLengthUnitType.Star; e.Column.MinimumWidth = 200; } else { var mapping = e.Column.MappingName; e.Column = new GridTemplateColumn() { CellTemplate = FindResource("milestoneTemplate") as DataTemplate, MappingName = mapping, SetCellBoundValue = true }; e.Column.HeaderText = " "; //mapping.Split('_').Last(); e.Column.Width = 80; } //throw new NotImplementedException(); } private void DataGrid_OnQueryRowHeight(object sender, QueryRowHeightEventArgs e) { if (e.RowIndex == 0) { e.Height = 30; e.Handled = true; } } private void DataGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e) { var tag = (e.OriginalSource as FrameworkElement).Tag; if (tag == null) { e.Handled = true; return; } MileStoneMenu.Items.Clear(); Guid.TryParse(tag.ToString(), out Guid id); var milestone = _milestones.Rows.FirstOrDefault(r => r.Get(c => c.ID) == id); if (milestone == null) { Guid setid = (Guid)(dataGrid.SelectedItem as DataRowView).Row["ID"]; var column = dataGrid.GetSelectedCells().First().Column.MappingName; var typeid = _types.FirstOrDefault(x => x.Value.Columns.Contains(column)).Key; var openmilestones = _milestones.Rows.Any(r => Guid.Equals(r.Get(c => c.DocumentSet.ID), setid) && Guid.Equals(r.Get(c => c.Type.ID), typeid) && r.Get(c=>c.Closed).IsEmpty() ); if (openmilestones) { e.Handled = true; return; } MenuItem newmilestone = new MenuItem() { Header = "New Milestone", Tag = typeid }; newmilestone.Click += (o, args) => { CreateMileStone(setid, typeid); }; MileStoneMenu.Items.Add(newmilestone); return; } var status = milestone.Get(c => c.Status); MenuItem setstatus = new MenuItem() { Header = "Change Status" }; foreach (JobDocumentSetMileStoneStatus newstatus in Enum.GetValues(typeof(JobDocumentSetMileStoneStatus))) { if (newstatus != status) { MenuItem setstatus2 = new MenuItem() { Header = newstatus.ToString().SplitCamelCase() }; setstatus2.Click += (o, args) => { ChangeMileStoneStatus(milestone, newstatus); }; setstatus.Items.Add(setstatus2); } } MileStoneMenu.Items.Add(setstatus); MenuItem editmilestone = new MenuItem() { Header = "Edit MileStone" }; editmilestone.Click += (o, args) => { EditMileStone(milestone); }; MileStoneMenu.Items.Add(editmilestone); var closed = milestone.Get(c => c.Closed); if (closed.IsEmpty()) { MenuItem upload = new MenuItem() { Header = "Upload Files" }; upload.Click += (o, args) => { UploadFiles(milestone); }; MileStoneMenu.Items.Add(upload); } MileStoneMenu.Items.Add(new Separator()); MenuItem download = new MenuItem() { Header = "Download Files" }; download.SubmenuOpened += (o, e) => { var files = new Client().Query( new Filter(x => x.EntityLink.ID).IsEqualTo(id), new Columns(x => x.ID) .Add(x => x.DocumentLink.FileName) .Add(x => x.DocumentLink.ID), new SortOrder(x => x.DocumentLink.FileName) ); foreach (var row in files.Rows) { MenuItem downloadone = new MenuItem() { Header = row.Get(x=>x.DocumentLink.FileName), Tag = row.Get(x=>x.DocumentLink.ID) }; downloadone.Click += (sender, args) => { DownloadFiles(milestone, new Guid[] { (Guid)downloadone.Tag }); }; download.Items.Insert(download.Items.Count-1,downloadone); } if (files.Rows.Any()) { download.Items.Insert(download.Items.Count-1,new Separator()); (download.Items[download.Items.Count - 1] as MenuItem).Tag = files.ExtractValues(x => x.DocumentLink.ID, true).ToArray(); (download.Items[download.Items.Count-1] as MenuItem).IsEnabled = true; } }; MenuItem downloadall = new MenuItem() { Header = "Download All", IsEnabled = false }; downloadall.Click += (sender, args) => { DownloadFiles(milestone, (Guid[])downloadall.Tag); }; download.Items.Add(downloadall); MileStoneMenu.Items.Add(download); Guid newsetid = (Guid)(dataGrid.SelectedItem as DataRowView).Row["ID"]; var newcolumn = dataGrid.GetSelectedCells().First().Column.MappingName; var newtypeid = _types.FirstOrDefault(x => x.Value.Columns.Contains(newcolumn)).Key; var newopenmilestones = _milestones.Rows.Any(r => Guid.Equals(r.Get(c => c.DocumentSet.ID), newsetid) && Guid.Equals(r.Get(c => c.Type.ID), newtypeid) && r.Get(c=>c.Closed).IsEmpty() ); if (!newopenmilestones) { MileStoneMenu.Items.Add(new Separator()); MenuItem newmilestone2 = new MenuItem() { Header = "New Milestone", Tag = newtypeid }; newmilestone2.Click += (o, args) => { CreateMileStone(newsetid, newtypeid); }; MileStoneMenu.Items.Add(newmilestone2); } MileStoneMenu.Items.Add(new Separator()); MenuItem delete = new MenuItem { Header = "Delete MileStone" }; delete.Click += (o, args) => DeleteMileStone(milestone); MileStoneMenu.Items.Add(delete); } private void DownloadFiles(CoreRow row, Guid[] ids) { var status = row.Get(c => c.Status); var stage = row.Get(c => c.Type.Code); var revision = row.Get(c => c.Revision); String tag = String.Format(" - {0}{1} ({2})", stage, String.IsNullOrWhiteSpace(revision) ? "" : " - Rev " + revision, status.ToString().SplitCamelCase()); FolderBrowserDialog dlg = new FolderBrowserDialog(); if (dlg.ShowDialog() == DialogResult.OK) { Progress.ShowModal("Downloading Files", (progress) => { var files = new Client().Query( new Filter(x => x.ID).InList(ids) ); foreach (var row in files.Rows) { string filename = row.Get(c => c.FileName); string extension = Path.GetExtension(filename); string basefilename = Path.GetFileNameWithoutExtension(filename); filename = String.Format("{0}{1}{2}", basefilename, tag, extension); filename = Path.Combine(dlg.SelectedPath, filename); File.WriteAllBytes(filename, row.Get(c => c.Data)); } }); } } private void UploadFiles(CoreRow row) { Guid id = row.Get(c => c.ID); OpenFileDialog dlg = new OpenFileDialog(); dlg.Filter = "PDF Files (*.pdf)|*.pdf"; dlg.Multiselect = true; if ((dlg.ShowDialog() == true) && (dlg.FileNames.Length > 0)) { Progress.ShowModal("Uploading Files", (progress) => { List documents = new List(); foreach (var file in dlg.FileNames) { var data = File.ReadAllBytes(file); documents.Add( new Document() { FileName = Path.GetFileName(file).ToLower(), Data = data, CRC = CoreUtils.CalculateCRC(data), TimeStamp = new FileInfo(file).LastWriteTime } ); } new Client().Save(documents.ToArray(), "Uploaded by User"); progress.Report("Updating Links"); List links = new List(); foreach (var document in documents) { var link = new JobDocumentSetMileStoneFile(); link.EntityLink.ID = id; link.DocumentLink.ID = document.ID; links.Add(link); } new Client().Save(links, "Uploaded By User"); }); MessageBox.Show(String.Format("{0} files uploaded", dlg.FileNames.Length)); } } private void CreateMileStone(Guid setid, Guid typeid) { JobDocumentSetMileStone milestone = new JobDocumentSetMileStone(); milestone.DocumentSet.ID = setid; milestone.Type.ID = typeid; milestone.Status = JobDocumentSetMileStoneStatus.InProgress; var grid = new JobDocumentSetMileStoneGrid(); if (grid.EditItems(new[] { milestone})) Refresh(); } private void ChangeMileStoneStatus(CoreRow row, JobDocumentSetMileStoneStatus newstatus) { var milestone = row.ToObject(); milestone.Status = newstatus; new Client().Save(milestone, "Changed Status to " + newstatus.ToString().SplitCamelCase()); Refresh(); } private void EditMileStone(CoreRow row) { var milestone = new Client().Query( new Filter(x => x.ID).IsEqualTo(row.Get(x => x.ID)) ).Rows.FirstOrDefault()?.ToObject(); var grid = new JobDocumentSetMileStoneGrid(); if (grid.EditItems(new[] { milestone })) Refresh(); } private void DeleteMileStone(CoreRow row) { var milestone = row.ToObject(); new Client().Delete(milestone,"Deleted by User"); Refresh(); } private void Add_OnClick(object sender, RoutedEventArgs e) { JobDocumentSet set = new JobDocumentSet(); set.Job.ID = JobID; set.Folder.ID = FolderID; var grid = new DynamicDataGrid(); if (grid.EditItems(new[] { set })) Refresh(); } private void Edit_OnClick(object sender, RoutedEventArgs e) { Guid setid = (Guid)(dataGrid.SelectedItem as DataRowView).Row["ID"]; var set = new Client().Query( new Filter(x => x.ID).IsEqualTo(setid) ).Rows.FirstOrDefault()?.ToObject(); var grid = new DynamicDataGrid(); if (grid.EditItems(new[] { set })) Refresh(); } private void Delete_OnClick(object sender, RoutedEventArgs e) { Guid setid = (Guid)(dataGrid.SelectedItem as DataRowView).Row["ID"]; var set = new JobDocumentSet() { ID = setid }; new Client().Delete(set, "Deleted By User"); Refresh(); } private bool _hidesuperceded = false; private void HideRejected_OnClick(object sender, RoutedEventArgs e) { _hidesuperceded = !_hidesuperceded; HideSupercededLabel.Content = _hidesuperceded ? "Show All" : "Last Only"; Refresh(); } } }