ProblemsDockGrid.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Windows.Controls;
  6. using System.Windows.Media.Imaging;
  7. using com.healthmarketscience.jackcess.query;
  8. using Comal.Classes;
  9. using InABox.Clients;
  10. using InABox.Core;
  11. using InABox.DynamicGrid;
  12. using InABox.Wpf;
  13. using InABox.WPF;
  14. namespace PRSDesktop;
  15. public class ProblemsDockGrid : DynamicDataGrid<Problems>
  16. {
  17. protected override void Init()
  18. {
  19. base.Init();
  20. HiddenColumns.Add(x=>x.Problem.Notes);
  21. HiddenColumns.Add(x=>x.Problem.AssignedTo.Code);
  22. ActionColumns.Add(new DynamicImageColumn(TypeImage)
  23. {
  24. Position = DynamicActionColumnPosition.Start,
  25. Filters = IMAGES.Keys.Select(x=>x.Name.Split('.').Last()).ToArray(),
  26. GetFilterExpression = (col) => TypeExpression(col),
  27. });
  28. ActionColumns.Add(new DynamicTextColumn(GetLastNote) { Position = DynamicActionColumnPosition.End, Width = 0, HeaderText = "Issues" });
  29. ActionColumns.Add(new DynamicTextColumn(GetAssignedTo) { Position = DynamicActionColumnPosition.End, Width = 100, HeaderText="Assigned To", Alignment = Alignment.MiddleCenter});
  30. ActionColumns.Add(new DynamicMenuColumn(ProblemMenu) { Position = DynamicActionColumnPosition.End });
  31. AddButton("Add Note", PRSDesktop.Resources.notification.AsBitmapImage(), AddNote);
  32. AddButton("Assign To", PRSDesktop.Resources.employee.AsBitmapImage(), AssignTo);
  33. AddButton("Mark Resolved", PRSDesktop.Resources.delete.AsBitmapImage(), MarkResolved,
  34. position: DynamicGridButtonPosition.Right);
  35. }
  36. private string TypeExpression(DynamicActionColumn column)
  37. {
  38. return column.CreateFilterExpression("Type") ?? "";
  39. }
  40. private bool TypeFilter(CoreRow row, string[] filter)
  41. {
  42. string typename = row.Get<Problems, string>(x => x.Type);
  43. return filter.Contains(typename);
  44. }
  45. private object? GetAssignedTo(CoreRow? row) => row?.Get<Problems, string>(x => x.Problem.AssignedTo.Code);
  46. private object? GetLastNote(CoreRow? row) => row?.Get<Problems, string[]>(x => x.Problem.Notes).LastOrDefault();
  47. protected override void DoReconfigure(DynamicGridOptions options)
  48. {
  49. base.DoReconfigure(options);
  50. options.FilterRows = true;
  51. options.MultiSelect = true;
  52. }
  53. protected override DynamicGridColumns LoadColumns()
  54. {
  55. var result = new DynamicGridColumns();
  56. result.Add<Problems, string>(x => x.Code, 150, "Code", "", Alignment.MiddleLeft);
  57. result.Add<Problems, string>(x => x.Description, 0, "Description", "", Alignment.MiddleLeft);
  58. return result;
  59. }
  60. private static readonly Dictionary<Type, BitmapImage?> IMAGES = new()
  61. {
  62. { typeof(Bill), PRSDesktop.Resources.bill.AsBitmapImage() },
  63. { typeof(Activity), PRSDesktop.Resources.assignments.AsBitmapImage() },
  64. { typeof(ProductStyle), PRSDesktop.Resources.palette.AsBitmapImage() },
  65. { typeof(Product), PRSDesktop.Resources.product.AsBitmapImage() },
  66. { typeof(CostSheet), PRSDesktop.Resources.costsheet.AsBitmapImage() },
  67. { typeof(Kit), PRSDesktop.Resources.kit.AsBitmapImage() },
  68. { typeof(JobBillOfMaterialsItem), PRSDesktop.Resources.box_sml.AsBitmapImage() },
  69. { typeof(JobRequisitionItem), PRSDesktop.Resources.requisition.AsBitmapImage() },
  70. { typeof(ManufacturingPacket), PRSDesktop.Resources.factory.AsBitmapImage() },
  71. };
  72. private BitmapImage? TypeImage(CoreRow? row)
  73. {
  74. var _type = row?.Get<Problems, string>(x => x.Type) ?? "";
  75. var _key = IMAGES.Keys.FirstOrDefault(x => string.Equals(x.Name.Split('.').Last(), _type));
  76. return _key != null
  77. ? IMAGES[_key]
  78. : null;
  79. }
  80. private string? TypeText(CoreRow? row)
  81. {
  82. return row?.Get<Problems, string>(x => x.Type) ?? "";
  83. }
  84. private void ProblemMenu(DynamicMenuColumn menu, CoreRow? row)
  85. {
  86. menu.AddItem("Add Note", null, AddNote);
  87. menu.AddItem("Assign To...", null, AssignTo);
  88. menu.AddSeparator();
  89. menu.AddItem("Edit Item", null, EditItem);
  90. menu.AddSeparator();
  91. menu.AddItem("Mark as Resolved", null, MarkResolved);
  92. }
  93. private Type? GetType(CoreRow? row)
  94. {
  95. var _name = row?.Get<Problems, string>(x => x.Type) ?? "";
  96. var _type = IMAGES.Keys.FirstOrDefault(x => string.Equals(x.Name.Split('.').Last(), _name));
  97. return _type;
  98. }
  99. private IProblems<ManagedProblem>? GetItem(CoreRow? row)
  100. {
  101. var _type = GetType(row);
  102. if (_type == null)
  103. return null;
  104. var _id = row.Get<Problems, Guid>(x => x.ID);
  105. var item = ClientFactory.CreateClient(_type).Query(
  106. Filter.Create(_type, "ID", Operator.IsEqualTo, _id),
  107. Columns.Local(_type),
  108. null
  109. ).Rows.FirstOrDefault()?.ToObject(_type) as IProblems<ManagedProblem>;
  110. return item;
  111. }
  112. private void AddNote(CoreRow[] rows)
  113. {
  114. var _items = rows.Select(GetItem).Where(x => x != null).ToArray();
  115. if (!_items.Any())
  116. return;
  117. var _note = "";
  118. if (TextBoxDialog.Execute("Add Problem Note", ref _note))
  119. {
  120. Dictionary<Type, List<IProblems<ManagedProblem>>> _updates = new();
  121. foreach (var _item in _items)
  122. {
  123. if (_item == null)
  124. continue;
  125. var _notes = _item.Problem.Notes?.ToList() ?? new List<string>();
  126. _notes.Add(_note);
  127. _item.Problem.Notes = _notes.ToArray();
  128. var _type = _item.GetType();
  129. if (!_updates.ContainsKey(_type))
  130. _updates[_type] = new List<IProblems<ManagedProblem>>();
  131. _updates[_type].Add(_item);
  132. }
  133. Progress.ShowModal("Adding Notes", progress =>
  134. {
  135. foreach (var _update in _updates)
  136. {
  137. progress.Report($"Adding note to {_update.Value.Count} {new Inflector.Inflector(new CultureInfo("en")).Pluralize(_update.Key.Name.Split('.').Last()).SplitCamelCase()}");
  138. ClientFactory.CreateClient(_update.Key).Save(_update.Value, "Added Isse note");
  139. }
  140. });
  141. Refresh(false, true);
  142. }
  143. }
  144. private bool AddNote(Button button, CoreRow[] rows)
  145. {
  146. AddNote(rows);
  147. return false;
  148. }
  149. private void AddNote(CoreRow? row)
  150. {
  151. if (row == null)
  152. return;
  153. AddNote([row]);
  154. }
  155. private void MarkResolved(CoreRow?[] rows)
  156. {
  157. var _items = rows.Select(GetItem).Where(x => x != null).ToArray();
  158. if (!_items.Any())
  159. return;
  160. Dictionary<Type, List<IProblems<ManagedProblem>>> _updates = new();
  161. foreach (var _item in _items)
  162. {
  163. if (_item == null)
  164. continue;
  165. _item.Problem.Resolved = DateTime.Now;
  166. var _type = _item.GetType();
  167. if (!_updates.ContainsKey(_type))
  168. _updates[_type] = new List<IProblems<ManagedProblem>>();
  169. _updates[_type].Add(_item);
  170. }
  171. Progress.ShowModal("Resolving items", progress =>
  172. {
  173. foreach (var _update in _updates)
  174. {
  175. progress.Report($"Resolving {_update.Value.Count} {new Inflector.Inflector(new CultureInfo("en")).Pluralize(_update.Key.Name.Split('.').Last()).SplitCamelCase()}");
  176. ClientFactory.CreateClient(_update.Key).Save(_update.Value, "Issue marked as resolved");
  177. }
  178. });
  179. Refresh(false, true);
  180. }
  181. private void MarkResolved(CoreRow? row)
  182. {
  183. if (row == null)
  184. return;
  185. MarkResolved([row]);
  186. }
  187. private bool MarkResolved(Button button, CoreRow[] rows)
  188. {
  189. if (MessageWindow.ShowYesNo("Mark Selected Issues as resolved?","Confirm"))
  190. MarkResolved(rows);
  191. return false;
  192. }
  193. private void AssignTo(CoreRow[] rows)
  194. {
  195. var _items = rows.Select(GetItem).ToArray();
  196. if (!_items.Any())
  197. return;
  198. var _dlg = new MultiSelectDialog<Employee>(LookupFactory.DefineFilter<Employee>(), null, false);
  199. if (_dlg.ShowDialog())
  200. {
  201. Dictionary<Type, List<IProblems<ManagedProblem>>> _updates = new();
  202. foreach (var _item in _items)
  203. {
  204. if (_item == null)
  205. continue;
  206. _item.Problem.AssignedTo.ID = _dlg.IDs().FirstOrDefault();
  207. var _type = _item.GetType();
  208. if (!_updates.ContainsKey(_type))
  209. _updates[_type] = new List<IProblems<ManagedProblem>>();
  210. _updates[_type].Add(_item);
  211. }
  212. Progress.ShowModal("Reassigning items", progress =>
  213. {
  214. foreach (var _update in _updates)
  215. {
  216. progress.Report($"Reassigning {_update.Value.Count} {new Inflector.Inflector(new CultureInfo("en")).Pluralize(_update.Key.Name.Split('.').Last()).SplitCamelCase()}");
  217. ClientFactory.CreateClient(_update.Key).Save(_update.Value, "Reassigning Problem");
  218. }
  219. });
  220. Refresh(false, true);
  221. }
  222. }
  223. private bool AssignTo(Button button, CoreRow[] rows)
  224. {
  225. AssignTo(rows);
  226. return false;
  227. }
  228. private void AssignTo(CoreRow? row)
  229. {
  230. if (row != null)
  231. return;
  232. AssignTo([ row ]);
  233. }
  234. protected override void DoDoubleClick(object sender, DynamicGridCellClickEventArgs args)
  235. {
  236. base.DoDoubleClick(sender, args);
  237. if (args.Row == null)
  238. return;
  239. EditItem(args.Row);
  240. }
  241. private void EditItem(CoreRow? row)
  242. {
  243. var _type = GetType(row);
  244. if (_type == null)
  245. return;
  246. var _item = GetItem(row);
  247. if (_item == null)
  248. return;
  249. var _grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), _type);
  250. if (_grid.EditItems([ _item ], null, false, this))
  251. Refresh(false,true);
  252. }
  253. }