Browse Source

Merge remote-tracking branch 'origin/frank' into kenric

# Conflicts:
#	prs.desktop/Panels/Jobs/DocumentSets/JobDocumentSetFolderTree.cs
#	prs.desktop/Panels/Jobs/JobRequisitionGrid.cs
Kenric Nugteren 2 years ago
parent
commit
ea244c1d0c

+ 3 - 0
prs.classes/Entities/Job/DocumentSet/JobDocumentSetMileStoneLink.cs

@@ -7,6 +7,9 @@ namespace Comal.Classes
     {
         [NullEditor]
         public override Guid ID { get; set; }
+        
+        [NullEditor]
+        public JobDocumentSetLink DocumentSet { get; set; }
 
         [EditorSequence(1)]
         public JobDocumentSetMileStoneTypelink Type { get; set; }

+ 2 - 2
prs.desktop/Panels/Jobs/DocumentSets/JobDocumentSetFolderTree.cs

@@ -19,9 +19,9 @@ namespace PRSDesktop
         public JobDocumentSetFolderTree() : base()
         {
             Options.AddRange(DynamicTreeOption.Add, DynamicTreeOption.Edit, DynamicTreeOption.Delete);
-
-            OnContextMenuOpening += JobDocumentSetFolderTree_OnContextMenuOpening;
             MaxRowHeight = 30D;
+            OnContextMenuOpening += JobDocumentSetFolderTree_OnContextMenuOpening;
+
         }
 
         private void JobDocumentSetFolderTree_OnContextMenuOpening(DynamicTreeNode node, ContextMenu menu)

+ 5 - 1
prs.desktop/Panels/Jobs/DocumentSets/JobDocumentSetMileStoneGrid.cs

@@ -1,11 +1,15 @@
+using System.Linq;
+using com.sun.org.apache.xpath.@internal.operations;
 using Comal.Classes;
 using InABox.Core;
 using InABox.DynamicGrid;
+using Microsoft.Office.Interop.Outlook;
 
 namespace PRSDesktop
 {
     public class JobDocumentSetMileStoneGrid : DynamicDataGrid<JobDocumentSetMileStone>
     {
+
         public JobDocumentSetMileStoneGrid() : base()
         {
             OnCustomiseEditor += OnOnCustomiseEditor;
@@ -15,7 +19,7 @@ namespace PRSDesktop
         {
             if (string.Equals(column.ColumnName, "Issued") || string.Equals(column.ColumnName, "Closed"))
                 editor.Editable = Security.IsAllowed<CanEditJobDocumentSetMileStoneDates>() ? Editable.Enabled : Editable.Disabled;
-
         }
+        
     }
 }

+ 1 - 0
prs.desktop/Panels/Jobs/DocumentSets/JobDocumentSetTree.xaml

@@ -170,6 +170,7 @@
             ItemsSourceChanged="TreeGrid_OnItemsSourceChanged"
             SelectionChanged="TreeGrid_OnSelectionChanged"
             CurrentCellActivated="TreeGrid_OnCurrentCellActivated"
+            CellDoubleTapped="TreeGrid_OnCellDoubleTapped"
         >
             <Syncfusion:SfTreeGrid.StackedHeaderRows>
                 <Syncfusion:StackedHeaderRow x:Name="stackedHeaderRow" />

+ 161 - 17
prs.desktop/Panels/Jobs/DocumentSets/JobDocumentSetTree.xaml.cs

@@ -2,25 +2,21 @@ using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.ComponentModel;
-using System.Data;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
-using System.Reflection;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Documents;
 using System.Windows.Forms;
-using System.Windows.Forms.VisualStyles;
 using System.Windows.Input;
 using System.Windows.Media;
 using Comal.Classes;
-using H.Pipes.Extensions;
 using InABox.Clients;
 using InABox.Core;
 using InABox.DynamicGrid;
 using InABox.WPF;
-using Microsoft.Office.Interop.Outlook;
+using Syncfusion.Data.Extensions;
 using Syncfusion.UI.Xaml.Grid;
 using Syncfusion.UI.Xaml.TreeGrid;
 using Syncfusion.UI.Xaml.TreeGrid.Helpers;
@@ -132,6 +128,11 @@ namespace PRSDesktop
         {
             return new ObservableCollection<DocumentSetNode>(_nodes.Where(x => x.Parent.Equals(id) && (x.ID != id)));
         }
+  
+        public DocumentSetNode? GetNode(Guid id)
+        {
+            return _nodes.FirstOrDefault(x => x.ID == id);
+        }
         
     }
 
@@ -205,6 +206,7 @@ namespace PRSDesktop
         private bool _flatlist = false;
         private bool _includeretired = false;
 
+        private DocumentSetNodes _documentsets = null;
         
         public JobDocumentSetTree()
         {
@@ -222,8 +224,12 @@ namespace PRSDesktop
         
         public void Refresh()
         {
+
             using (new WaitCursor())
             {
+                var scrollviewer = WPFUtils.FindVisualChildren<ScrollViewer>(treeGrid).FirstOrDefault();
+                var verticalOffset = scrollviewer != null ? scrollviewer.VerticalOffset : 0;
+                var horizontalOffset = treeGrid.SelectedItem != null ? scrollviewer.HorizontalOffset : 0;
                 treeGrid.ItemsSource = null;
 
                 var setfilter = new Filter<JobDocumentSet>(x => x.Job.ID).IsEqualTo(JobID);
@@ -354,14 +360,18 @@ namespace PRSDesktop
                     }
                 }
 
-                var documentsets = new DocumentSetNodes(columns);
+                _documentsets = new DocumentSetNodes(columns);
 
                 foreach (var setrow in Data.Rows)
                 {
+                    
+                    
                     Guid setid = setrow.Get<JobDocumentSet, Guid>(x => x.ID);
                     Guid parentid = _flatlist ? Guid.Empty : setrow.Get<JobDocumentSet, Guid>(x => x.Parent.ID);
 
-                    var node = documentsets.Add(setid, parentid);
+                    var node = _documentsets.Add(setid, parentid);
+                    
+                    
                     JobDocumentSetDescriptionBlock desc = new JobDocumentSetDescriptionBlock()
                     {
                         ID = setid,
@@ -416,12 +426,17 @@ namespace PRSDesktop
                     }
                 }
 
-                ConfigureColumns(documentsets);
+                ConfigureColumns(_documentsets);
 
                 ConfigureStackedHeader();
 
-                treeGrid.ItemsSource = documentsets.Nodes;
-                DocumentCount.Content = $"{documentsets.Nodes.Count} {(documentsets.Nodes.Count > 1 ? "Records" : "Record")}";
+                treeGrid.ItemsSource = _documentsets.Nodes;
+                DocumentCount.Content = $"{_documentsets.Nodes.Count} {(_documentsets.Nodes.Count > 1 ? "Records" : "Record")}";
+                if (scrollviewer != null)
+                {
+                    scrollviewer.ScrollToVerticalOffset(verticalOffset);
+                    scrollviewer.ScrollToHorizontalOffset(horizontalOffset);
+                }
             }
 
         }
@@ -534,14 +549,20 @@ namespace PRSDesktop
             {
 
                 var document = treeGrid.SelectedItem as DocumentSetNode;
-                
 
+
+                MenuItem edit = new MenuItem();
+                edit.Header = "Edit Document Set";
+                edit.Click += (o, args) => { EditDocumentSets(new Guid[] { document.ID }); };
+                MileStoneMenu.Items.Add(edit);
+
+                MileStoneMenu.Items.Add(new Separator());
+                
                 MenuItem addchild = new MenuItem();
                 addchild.Header = "Add Child";
                 addchild.Click += (o,args) => { AddChildDocument(document); };
                 MileStoneMenu.Items.Add(addchild);
-
-
+                
                 var documents = treeGrid.SelectedItems.Select(x => (x as DocumentSetNode));
                 MenuItem movetofolder = new MenuItem();
                 movetofolder.Header = "Move To Folder";
@@ -581,6 +602,7 @@ namespace PRSDesktop
                 );
                 if (openmilestones)
                     canCreateNewMileStones = false;
+                
             }
             
             if (canCreateNewMileStones)
@@ -988,9 +1010,43 @@ namespace PRSDesktop
             }
         }
 
+        private Dictionary<Guid, JobDocumentSetMileStone> GetPreviousMileStones(Guid[] setids, Guid typeid)
+        {
+            var result = new Dictionary<Guid, JobDocumentSetMileStone>();
+            foreach (var setid in setids)
+            {
+                var typeindex = _types.Keys.IndexOf(typeid);
+                JobDocumentSetMileStone? last = null;
+                while ((last == null) && (typeindex > 0))
+                {
+                    last = _milestones.Rows.LastOrDefault(r =>
+                            (r.Get<JobDocumentSetMileStone, Guid>(c => c.DocumentSet.ID) == setid) &&
+                            (r.Get<JobDocumentSetMileStone, Guid>(c => c.Type.ID) == _types.Keys.ToArray()[typeindex]))
+                        ?.ToObject<JobDocumentSetMileStone>();
+                    typeindex--;
+                }
+
+                if (last != null)
+                    result[setid] = last;
+
+            }
+            return result;
+        }
+
         private void CreateMileStone(Guid[] setids, Guid typeid, DateTime duedate)
         {
-            List<JobDocumentSetMileStone> updates = new List<JobDocumentSetMileStone>();
+            bool bCopy = false;
+            var lastmilestones = GetPreviousMileStones(setids, typeid);
+            if (lastmilestones.Any(x => x.Value.Attachments > 0))
+            {
+                var confirm = MessageBox.Show("Do you wish to copy the files from the previous milestones?", "Copy Files",
+                    MessageBoxButton.YesNoCancel);
+                if (confirm == MessageBoxResult.Cancel)
+                    return;
+                bCopy = confirm == MessageBoxResult.Yes;
+            }
+
+            Dictionary<JobDocumentSetMileStone,JobDocumentSetMileStoneFile[]> updates = new Dictionary<JobDocumentSetMileStone, JobDocumentSetMileStoneFile[]>();
             foreach (var setid in setids)
             {
                 JobDocumentSetMileStone milestone = new JobDocumentSetMileStone();
@@ -998,10 +1054,55 @@ namespace PRSDesktop
                 milestone.Type.ID = typeid;
                 milestone.Status = JobDocumentSetMileStoneStatus.NotStarted;
                 milestone.Due = duedate;
-                updates.Add(milestone);
+
+                JobDocumentSetMileStoneFile[] files = new JobDocumentSetMileStoneFile[] { };
+                if (bCopy && lastmilestones.TryGetValue(setid, out var lastmilestone))
+                {
+                    if (lastmilestone.Attachments > 0)
+                    {
+                        files = new Client<JobDocumentSetMileStoneFile>().Query(
+                            new Filter<JobDocumentSetMileStoneFile>(x => x.EntityLink.ID).InList(lastmilestone.ID),
+                            new Columns<JobDocumentSetMileStoneFile>(x=>x.EntityLink.DocumentSet.ID)
+                                .Add(x => x.DocumentLink.FileName)
+                                .Add(x => x.DocumentLink.ID),
+                            new SortOrder<JobDocumentSetMileStoneFile>(x => x.DocumentLink.FileName)
+                        ).Rows.Select(r=>r.ToObject<JobDocumentSetMileStoneFile>()).ToArray();                        
+                    }
+                }
+                
+                updates[milestone] = files;
             }
             var grid = new JobDocumentSetMileStoneGrid();
-            if (grid.EditItems(updates.ToArray()))
+            grid.OnAfterSave += (editor, items) =>
+            {
+                if (updates.Keys.Count == 1)
+                    return;
+                List<JobDocumentSetMileStoneFile> fileupdates = new List<JobDocumentSetMileStoneFile>();
+                foreach (var milestone in updates.Keys)
+                {
+                    foreach (var file in updates[milestone])
+                    {
+                        file.EntityLink.ID = milestone.ID;
+                        fileupdates.Add(file);
+                    }
+                }
+
+                if (fileupdates.Any())
+                    new Client<JobDocumentSetMileStoneFile>().Save(fileupdates,"");
+            };
+
+            if (grid.EditItems(updates.Keys.ToArray(), (t) =>
+                {
+                    if ((t == typeof(JobDocumentSetMileStoneFile)) && (updates.Keys.Count == 1))
+                    {
+                        CoreTable result = new CoreTable();
+                        result.LoadColumns(typeof(JobDocumentSetMileStoneFile));
+                        result.LoadRows(updates[updates.Keys.First()]);
+                        return result;
+                    }
+                    return null;
+                }, true)
+            )
                 Refresh();
         }
 
@@ -1308,6 +1409,11 @@ namespace PRSDesktop
 
             Guid[] setIDs = treeGrid.SelectedItems.Select(x => (x as DocumentSetNode).ID).ToArray();
 
+            EditDocumentSets(setIDs);
+        }
+
+        private void EditDocumentSets(Guid[] setIDs)
+        {
             var sets = new Client<JobDocumentSet>().Query(
                 new Filter<JobDocumentSet>(x => x.ID).InList(setIDs)
             ).Rows.Select(x => x.ToObject<JobDocumentSet>()).ToArray();
@@ -1324,7 +1430,38 @@ namespace PRSDesktop
                     editor.Editable = AreaVisible ? Editable.Enabled : Editable.Hidden;
             };
             if (grid.EditItems(sets))
-                Refresh();
+                UpdateNodes(sets);
+        }
+
+        private void UpdateNodes(IEnumerable<JobDocumentSet> sets)
+        {
+            if (_documentsets == null)
+                return;
+            foreach (var set in sets)
+            {
+                var node = _documentsets.GetNode(set.ID);
+                if (node != null)
+                {
+                    JobDocumentSetDescriptionBlock desc = new JobDocumentSetDescriptionBlock()
+                    {
+                        ID = set.ID,
+                        Code = set.Code,
+                        Description = set.Description,
+                    };
+                    node.Description = Serialization.Serialize(desc);
+
+                    JobDocumentSetDetailsBlock dets = new JobDocumentSetDetailsBlock()
+                    {
+                        ID = set.ID,
+                        Date = set.Date,
+                        Size = set.Size,
+                        Scale = set.Scale,
+                        Employee = set.Employee.Name
+                    };
+                    node.Details = Serialization.Serialize(dets);
+                }
+            }
+            
         }
 
         private void HideRejected_OnClick(object sender, RoutedEventArgs e)
@@ -1441,5 +1578,12 @@ namespace PRSDesktop
 
             
         }
+
+        private void TreeGrid_OnCellDoubleTapped(object? sender, TreeGridCellDoubleTappedEventArgs e)
+        {
+            var set = e.Record as DocumentSetNode;
+            if (set != null)
+                EditDocumentSets(new Guid[] { set.ID });
+        }
     }
 }

+ 16 - 35
prs.desktop/Panels/Jobs/JobRequisitionGrid.cs

@@ -29,12 +29,7 @@ namespace PRSDesktop
             HiddenColumns.Add(x => x.ID);
             HiddenColumns.Add(x => x.Job.ID);
             HiddenColumns.Add(x => x.Approved);
-
-            if (Security.IsAllowed<CanApproveJobRequisitions>())
-                _approve = AddButton("Approve", null, ApproveClick);
-
             _approve = AddButton("Approve", null, ApproveClick);
-
             _createtask = AddButton("Create Task", null, CreateTask);
         }
 
@@ -58,7 +53,7 @@ namespace PRSDesktop
             return false;
         }
 
-        protected override void SelectItems(CoreRow[]? rows)
+        protected override void SelectItems(CoreRow[] rows)
         {
             base.SelectItems(rows);
             if (rows?.Length == 1)
@@ -78,31 +73,18 @@ namespace PRSDesktop
             }
         }
 
-        private bool CreateTask(Button btn, CoreRow[] rows)
+        private bool CreateTask(System.Windows.Controls.Button btn, CoreRow[] rows)
         {
-            var row = rows.FirstOrDefault();
-
-            if (row is null)
+            if (!rows.Any())
             {
                 MessageBox.Show("Please select at least one row to add to Task!");
                 return false;
             }
-
             Progress.Show("Working");
-            var jobrequi = row.ToObject<JobRequisition>();
-
+            JobRequisition jobrequi = rows.FirstOrDefault().ToObject<JobRequisition>();
             Kanban kanban = new Kanban();
-            kanban.ManagerLink.ID = new Client<Employee>()
-                .Query(
-                    new Filter<Employee>(x => x.UserLink.UserID).IsEqualTo(ClientFactory.UserID),
-                    new Columns<Employee>(x => x.ID))
-                .Rows.FirstOrDefault()?.Get<Employee, Guid>(x => x.ID) ?? Guid.Empty;
-
-            string jobnumber = new Client<Job>()
-                .Query(
-                    new Filter<Job>(x => x.ID).IsEqualTo(JobID),
-                    new Columns<Job>(x => x.JobNumber))
-                .Rows.FirstOrDefault()?.Get<Job, string>(x => x.JobNumber) ?? "";
+            kanban.ManagerLink.ID = Guid.Parse(new Client<Employee>().Query(new Filter<Employee>(x => x.UserLink.UserID).IsEqualTo(ClientFactory.UserID), new Columns<Employee>(x => x.ID)).Rows.FirstOrDefault().Values[0].ToString());
+            string jobnumber = new Client<Job>().Query(new Filter<Job>(x => x.ID).IsEqualTo(JobID), new Columns<Job>(x => x.JobNumber)).Rows.FirstOrDefault().Values[0].ToString();
             kanban.JobLink.ID = JobID;
             kanban.Title = "New Job Requisition Raised for Ordering (Job " + jobnumber + " (" + jobrequi.Number + ")" + ")";
             kanban.Category = "Open";
@@ -120,27 +102,26 @@ namespace PRSDesktop
             var page = new KanbanGrid();
             page.OnAfterSave += (form, items) =>
             {
-                KanbanAfterSave(form, jobrequi, items);
+                KanbanAfterSave(form, items);
             };
             return page.EditItems(new[] { kanban });
         }
 
-        private void KanbanAfterSave(DynamicEditorForm form, JobRequisition jobRequisition, Kanban[] items)
+        private void KanbanAfterSave(DynamicEditorForm form, Kanban[] items)
         {
             Progress.Show("Saving documents");
-
-            CoreTable table = new Client<JobRequisitionDocument>()
-                .Query(
-                    new Filter<JobRequisitionDocument>(x => x.EntityLink.ID).IsEqualTo(jobRequisition.ID),
-                    new Columns<JobRequisitionDocument>(x => x.DocumentLink.ID, x => x.DocumentLink.FileName));
+            JobRequisition jobrequi = SelectedRows.FirstOrDefault().ToObject<JobRequisition>();
+            CoreTable table = new Client<JobRequisitionDocument>().Query(new Filter<JobRequisitionDocument>(x => x.EntityLink.ID).IsEqualTo(jobrequi.ID),
+                new Columns<JobRequisitionDocument>(x => x.DocumentLink.ID, x => x.DocumentLink.FileName));
             if (table.Rows.Any())
             {
                 List<KanbanDocument> docs = new List<KanbanDocument>();
                 foreach (CoreRow row in table.Rows)
                 {
                     KanbanDocument doc = new KanbanDocument();
-                    doc.DocumentLink.ID = row.Get<KanbanDocument, Guid>(x => x.DocumentLink.ID);
-                    doc.DocumentLink.FileName = row.Get<KanbanDocument, string>(x => x.DocumentLink.FileName);
+                    doc.DocumentLink.ID = Guid.Parse(row.Values[0].ToString());
+                    if (row.Values[1] != null)
+                        doc.DocumentLink.FileName = row.Values[1].ToString();
                     doc.EntityLink.ID = items[0].ID;
                     docs.Add(doc);
                 }
@@ -151,8 +132,8 @@ namespace PRSDesktop
 
         public Guid JobID { get; set; }
 
-        protected override void Reload(Filters<JobRequisition> criteria, Columns<JobRequisition> columns, ref SortOrder<JobRequisition>? sort,
-            Action<CoreTable?, Exception?> action)
+        protected override void Reload(Filters<JobRequisition> criteria, Columns<JobRequisition> columns, ref SortOrder<JobRequisition> sort,
+            Action<CoreTable, Exception> action)
         {
             if (!Security.IsAllowed<CanApproveJobRequisitions>())
                 criteria.Add(new Filter<JobRequisition>(x => x.Approved).IsNotEqualTo(DateTime.MinValue));