ScanGrid.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. using Comal.Classes;
  2. using InABox.Clients;
  3. using InABox.Core;
  4. using InABox.DynamicGrid;
  5. using InABox.WPF;
  6. using Syncfusion.Pdf;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. using System.Windows;
  14. using System.Windows.Controls;
  15. namespace PRSDesktop
  16. {
  17. public class ScanGrid : DynamicDataGrid<Scan>
  18. {
  19. private List<ScanTag>? _tags;
  20. private Button? ExplodeBtn;
  21. public delegate void SelectAppliesTo(string appliesTo);
  22. public event SelectAppliesTo? OnSelectAppliesTo;
  23. public ScanGrid()
  24. {
  25. Options.BeginUpdate()
  26. .AddRange(DynamicGridOption.MultiSelect, DynamicGridOption.DragSource, DynamicGridOption.FilterRows)
  27. .Remove(DynamicGridOption.ImportData)
  28. .EndUpdate();
  29. if (Security.CanEdit<Scan>() || Security.IsAllowed<CanSetupScanTags>())
  30. {
  31. ActionColumns.Add(new DynamicMenuColumn(MenuBuild, null));
  32. }
  33. if (Security.CanEdit<Scan>())
  34. {
  35. ExplodeBtn = AddButton("Explode", null, Explode_Click);
  36. }
  37. if (Security.IsAllowed<CanSetupScanTags>())
  38. {
  39. AddButton("Setup Tags", null, SetupTags_Click);
  40. }
  41. HiddenColumns.Add(x => x.Tag.ID);
  42. HiddenColumns.Add(x => x.Tag.AppliesTo);
  43. HiddenColumns.Add(x => x.Document.ID);
  44. }
  45. protected override void SelectItems(CoreRow[]? rows)
  46. {
  47. base.SelectItems(rows);
  48. if(ExplodeBtn is not null)
  49. {
  50. ExplodeBtn.Visibility = rows is not null && rows.Any() ? Visibility.Visible : Visibility.Collapsed;
  51. }
  52. }
  53. private bool Explode_Click(Button button, CoreRow[] rows)
  54. {
  55. Guid tagID = Guid.Empty;
  56. foreach(var row in rows)
  57. {
  58. var rowTag = row.Get<Scan, Guid>(x => x.Tag.ID);
  59. if (tagID == Guid.Empty)
  60. {
  61. tagID = rowTag;
  62. }
  63. else if(rowTag != tagID)
  64. {
  65. tagID = Guid.Empty;
  66. break;
  67. }
  68. }
  69. var docIDs = rows.Select(x => x.Get<Scan, Guid>(x => x.Document.ID)).ToArray();
  70. var docs = new Client<Document>()
  71. .Query(
  72. new Filter<Document>(x => x.ID).InList(docIDs),
  73. new Columns<Document>(x => x.ID).Add(x => x.Data).Add(x => x.FileName))
  74. .ToObjects<Document>().ToDictionary(x => x.ID, x => x);
  75. var pages = new List<DocumentManipulationWindow.Page>();
  76. string filename = "";
  77. foreach(var docID in docIDs)
  78. {
  79. if(docs.TryGetValue(docID, out var doc))
  80. {
  81. filename = doc.FileName;
  82. var ms = new MemoryStream(doc.Data);
  83. var pdfDoc = DocumentManipulationWindow.RenderToPDF(doc.FileName, ms);
  84. foreach(var page in DocumentManipulationWindow.SplitIntoPages(doc.FileName, pdfDoc))
  85. {
  86. pages.Add(page);
  87. }
  88. }
  89. }
  90. if(ShowDocumentWindow(pages, filename, tagID))
  91. {
  92. // ShowDocumentWindow already saves new scans, so we just need to get rid of the old ones.
  93. DeleteItems(rows);
  94. return true;
  95. }
  96. return false;
  97. }
  98. private bool SetupTags_Click(System.Windows.Controls.Button button, CoreRow[] rows)
  99. {
  100. var list = new MasterList(typeof(ScanTag));
  101. if (list.ShowDialog() == true)
  102. return true;
  103. return false;
  104. }
  105. public static List<ScanTag> GetVisibleScanTagList()
  106. {
  107. var tags = new Client<ScanTag>().Query().ToList<ScanTag>();
  108. var tagsList = new List<ScanTag>();
  109. foreach (var tag in tags)
  110. {
  111. var entity = CoreUtils.GetEntityOrNull(tag.AppliesTo);
  112. if (entity is null || Security.CanView(entity))
  113. {
  114. var tagHasEmployee = new Client<ScanTagDistributionEmployee>()
  115. .Query(
  116. new Filter<ScanTagDistributionEmployee>(x => x.Tag.ID).IsEqualTo(tag.ID)
  117. .And(x => x.Employee.ID).IsEqualTo(App.EmployeeID),
  118. new Columns<ScanTagDistributionEmployee>(x => x.ID))
  119. .Rows.Any();
  120. if (tagHasEmployee)
  121. {
  122. tagsList.Add(tag);
  123. }
  124. }
  125. }
  126. return tagsList;
  127. }
  128. private List<ScanTag> GetVisibleTags()
  129. {
  130. _tags ??= GetVisibleScanTagList();
  131. return _tags;
  132. }
  133. private void MenuBuild(DynamicMenuColumn column, CoreRow? row)
  134. {
  135. if (row is null) return;
  136. if (Security.CanEdit<Scan>() || Security.IsAllowed<CanSetupScanTags>())
  137. {
  138. var changeTag = column.AddItem("Change Tag", null, null);
  139. changeTag.AddItem("(No Tag)", null, new Tuple<CoreRow, ScanTag?>(row, null), SetTag_Click);
  140. foreach (var tag in GetVisibleTags())
  141. {
  142. changeTag.AddItem(tag.Name, null, new Tuple<CoreRow, ScanTag?>(row, tag), SetTag_Click);
  143. }
  144. }
  145. if (Security.CanEdit<Scan>())
  146. {
  147. var processed = row.Get<Scan, bool>(x => x.Processed);
  148. column.AddItem(processed ? "Mark as not processed" : "Mark as processed", null, Process_Click);
  149. }
  150. if(OnSelectAppliesTo is not null)
  151. {
  152. column.AddItem("Go to Document", null, Document_Click);
  153. }
  154. }
  155. private void Document_Click(CoreRow? row)
  156. {
  157. if (row is null) return;
  158. OnSelectAppliesTo?.Invoke(row.Get<Scan, string>(x => x.Tag.AppliesTo));
  159. }
  160. private void SetTag_Click(Tuple<CoreRow, ScanTag?> obj)
  161. {
  162. var scan = obj.Item1.ToObject<Scan>();
  163. scan.Tag.ID = obj.Item2?.ID ?? Guid.Empty;
  164. SaveItem(scan);
  165. Refresh(false, true);
  166. }
  167. private void Process_Click(CoreRow? row)
  168. {
  169. if (row is null) return;
  170. var scan = row.ToObject<Scan>();
  171. if (!scan.Processed && MessageBox.Show("Doing this will remove this scan from the list. Do you wish to continue?", "Confirm", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
  172. {
  173. return;
  174. }
  175. scan.Processed = !scan.Processed;
  176. SaveItem(scan);
  177. Refresh(false, true);
  178. }
  179. protected override void OnRowsDragStart(CoreRow[] rows)
  180. {
  181. var table = new CoreTable();
  182. table.Columns.Add(new CoreColumn { ColumnName = "ID", DataType = typeof(Guid) });
  183. foreach(var row in rows)
  184. {
  185. var newRow = table.NewRow();
  186. newRow.Set<Document, Guid>(x => x.ID, row.Get<Scan, Guid>(x => x.Document.ID));
  187. table.Rows.Add(newRow);
  188. }
  189. DragTable(typeof(Document), table);
  190. }
  191. public void UploadDocument(string filename, byte[] data, Guid tagID)
  192. {
  193. var document = new Document
  194. {
  195. FileName = filename,
  196. CRC = CoreUtils.CalculateCRC(data),
  197. TimeStamp = DateTime.Now,
  198. Data = data
  199. };
  200. new Client<Document>().Save(document, "");
  201. var scan = new Scan();
  202. scan.Document.ID = document.ID;
  203. scan.Tag.ID = tagID;
  204. new Client<Scan>().Save(scan, "");
  205. Dispatcher.Invoke(() =>
  206. {
  207. Refresh(false, true);
  208. });
  209. }
  210. private static PdfDocumentBase CombinePages(IEnumerable<DocumentManipulationWindow.Page> pages)
  211. {
  212. var document = new PdfDocument();
  213. foreach (var page in pages)
  214. {
  215. document.ImportPage(page.Pdf, page.PageIndex);
  216. }
  217. return document;
  218. }
  219. public bool ShowDocumentWindow(List<DocumentManipulationWindow.Page> pages, string filename, Guid tagID)
  220. {
  221. var window = new DocumentManipulationWindow(pages, filename, tagID);
  222. if (window.ShowDialog() == true)
  223. {
  224. Progress.ShowModal("Uploading Files", (progress) =>
  225. {
  226. foreach (var group in window.Groups)
  227. {
  228. progress.Report($"Uploading '{group.FileName}'");
  229. var doc = CombinePages(group.Pages);
  230. byte[] data;
  231. using (var ms = new MemoryStream())
  232. {
  233. doc.Save(ms);
  234. data = ms.ToArray();
  235. }
  236. UploadDocument(group.FileName, data, group.TagID);
  237. }
  238. });
  239. return true;
  240. }
  241. return false;
  242. }
  243. protected override void DoAdd()
  244. {
  245. ShowDocumentWindow(new(), "", Guid.Empty);
  246. }
  247. protected override void GenerateColumns(DynamicGridColumns columns)
  248. {
  249. columns.Add<Scan, string>(x => x.Document.FileName, 0, "Filename", "", InABox.Core.Alignment.MiddleLeft);
  250. columns.Add<Scan, string>(x => x.Tag.Name, 100, "Tag", "", InABox.Core.Alignment.MiddleLeft);
  251. }
  252. protected override void Reload(Filters<Scan> criteria, Columns<Scan> columns, ref SortOrder<Scan>? sort, Action<CoreTable?, Exception?> action)
  253. {
  254. criteria.Add(new Filter<Scan>(x => x.Processed).IsEqualTo(false));
  255. var tagFilter = new Filter<Scan>(x => x.Tag.ID).InList(GetVisibleTags().Select(x => x.ID).ToArray());
  256. if (Security.IsAllowed<CanSetupScanTags>())
  257. {
  258. tagFilter.Or(x => x.Tag.ID).IsEqualTo(Guid.Empty);
  259. }
  260. criteria.Add(tagFilter);
  261. base.Reload(criteria, columns, ref sort, action);
  262. }
  263. }
  264. }