|
@@ -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 });
|
|
|
+ }
|
|
|
}
|
|
|
}
|