ScheduleItemGrid.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Media.Imaging;
  7. using Comal.Classes;
  8. using InABox.Clients;
  9. using InABox.Core;
  10. using InABox.DynamicGrid;
  11. using InABox.WPF;
  12. using Microsoft.Win32;
  13. using Syncfusion.Linq;
  14. using Button = System.Windows.Controls.Button;
  15. using MessageBox = System.Windows.MessageBox;
  16. using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
  17. using SaveFileDialog = Microsoft.Win32.SaveFileDialog;
  18. namespace PRS.Shared
  19. {
  20. internal class ScheduleItemGrid : DynamicDataGrid<Schedule>
  21. {
  22. private readonly BitmapImage disabled = PRS.Shared.Resources.disabled.AsBitmapImage();
  23. private readonly BitmapImage tick = PRS.Shared.Resources.tick.AsBitmapImage();
  24. protected override void Init()
  25. {
  26. base.Init();
  27. ActionColumns.Add(new DynamicTickColumn<Schedule, bool>(x => x.Active, tick, tick, disabled, CheckClick));
  28. HiddenColumns.Add(x => x.Active);
  29. HiddenColumns.Add(x => x.Title);
  30. HiddenColumns.Add(x => x.DocumentClass);
  31. AddButton("Export", PRS.Shared.Resources.download.AsBitmapImage(), SaveSchedules);
  32. AddButton("Import", PRS.Shared.Resources.upload.AsBitmapImage(), LoadSchedules);
  33. }
  34. protected override void DoReconfigure(DynamicGridOptions options)
  35. {
  36. base.DoReconfigure(options);
  37. options.RecordCount = true;
  38. options.SelectColumns = true;
  39. options.MultiSelect = true;
  40. }
  41. public CoreTable Schedules { get; set; }
  42. public Type DocumentType { get; set; }
  43. public Guid DocumentID { get; set; }
  44. private bool LoadSchedules(Button sender, CoreRow[] rows)
  45. {
  46. if (rows.Length != 1)
  47. {
  48. MessageBox.Show("Please select only one row to process");
  49. return false;
  50. }
  51. var row = rows.First();
  52. var dlg = new OpenFileDialog();
  53. dlg.Filter = "PRS Schedule Files (*.schedule)|*.schedule";
  54. if (dlg.ShowDialog() == true)
  55. {
  56. Progress.Show("");
  57. var json = File.ReadAllText(dlg.FileName);
  58. Schedule[] schedules = { };
  59. try
  60. {
  61. schedules = Serialization.Deserialize<Schedule[]>(json);
  62. }
  63. catch
  64. {
  65. Progress.Close();
  66. MessageBox.Show("[" + Path.GetFileName(dlg.FileName) + "] is not a valid schedule file!");
  67. return false;
  68. }
  69. if (!schedules.Any())
  70. {
  71. Progress.Close();
  72. MessageBox.Show("[" + Path.GetFileName(dlg.FileName) + "] does not contain any schedules!");
  73. return false;
  74. }
  75. foreach (var schedule in schedules)
  76. {
  77. schedule.DocumentID = DocumentID;
  78. schedule.DocumentClass = DocumentType.EntityName();
  79. schedule.ID = Guid.Empty;
  80. schedule.Active = false;
  81. schedule.DueDate = DateTime.MinValue;
  82. }
  83. new Client<Schedule>().Save(schedules, "Imported from [" + Path.GetFileName(dlg.FileName) + "]");
  84. Progress.Close();
  85. MessageBox.Show(string.Format("{0} schedules loaded from [{1}]", schedules.Length, Path.GetFileName(dlg.FileName)));
  86. }
  87. return true;
  88. }
  89. private bool SaveSchedules(Button sender, CoreRow[] rows)
  90. {
  91. if (rows.Any())
  92. {
  93. MessageBox.Show("Please select at least one schedule before Exporting!");
  94. return false;
  95. }
  96. var names = new List<string>();
  97. rows.ForEach(r => names.Add(r.Get<Schedule, string>(c => c.Title)));
  98. var filename = DocumentType.Name + " (" + string.Join(" + ", names) + ")";
  99. Path.GetInvalidFileNameChars().ForEach(c => filename = filename.Replace(c.ToString(), ""));
  100. Path.GetInvalidPathChars().ForEach(c => filename = filename.Replace(c.ToString(), ""));
  101. var dlg = new SaveFileDialog();
  102. dlg.Filter = "PRS Schedule Files (*.schedule)|*.schedule";
  103. dlg.FileName = filename + ".schedule";
  104. dlg.AddExtension = false;
  105. if (dlg.ShowDialog() == true)
  106. {
  107. Progress.Show("");
  108. Filter<Schedule> filter = null;
  109. foreach (var schedule in SelectedRows)
  110. if (filter == null)
  111. filter = new Filter<Schedule>(x => x.ID).IsEqualTo(schedule.Get<Schedule, Guid>(x => x.ID));
  112. else
  113. filter = filter.Or(x => x.ID).IsEqualTo(schedule.Get<Schedule, Guid>(x => x.ID));
  114. var schedules = new Client<Schedule>().Load(filter);
  115. foreach (var schedule in schedules)
  116. {
  117. schedule.DocumentID = DocumentID;
  118. schedule.DocumentClass = DocumentType.EntityName();
  119. schedule.ID = Guid.Empty;
  120. schedule.Active = false;
  121. schedule.DueDate = DateTime.MinValue;
  122. }
  123. var json = Serialization.Serialize(schedules);
  124. File.WriteAllText(dlg.FileName + ".schedule", json);
  125. Progress.Close();
  126. MessageBox.Show(string.Format("{0} schedules saved to [{1}]", SelectedRows.Length, Path.GetFileName(dlg.FileName)));
  127. }
  128. return false;
  129. }
  130. private bool CheckClick(CoreRow row)
  131. {
  132. var Due = row.Get<Schedule, DateTime>(x => x.DueDate);
  133. if (Due.Equals(DateTime.MinValue))
  134. {
  135. MessageBox.Show("Schedule must have a due date!");
  136. return false;
  137. }
  138. using (var client = new Client<Schedule>())
  139. {
  140. var schedule = client.Query(
  141. new Filter<Schedule>(x => x.ID).IsEqualTo(row.Get<Schedule, Guid>(x => x.ID)),
  142. Columns.Required<Schedule>().Add(x => x.Active))
  143. .ToObjects<Schedule>().First();
  144. schedule.Active = !schedule.Active;
  145. client.Save(schedule, schedule.Active ? "Activated Schedule" : "Disabled Schedule");
  146. }
  147. return true;
  148. }
  149. protected override void Reload(
  150. Filters<Schedule> criteria, Columns<Schedule> columns, ref SortOrder<Schedule>? sort,
  151. CancellationToken token, Action<CoreTable?, Exception?> action)
  152. {
  153. criteria.Add(new Filter<Schedule>(x => x.DocumentID).IsEqualTo(DocumentID));
  154. sort = new SortOrder<Schedule>(x => x.DueDate);
  155. base.Reload(criteria, columns, ref sort, token, action);
  156. }
  157. public override Schedule CreateItem()
  158. {
  159. if(DocumentType is null)
  160. {
  161. throw new Exception("Cannot create item when DocumentType is null.");
  162. }
  163. var schedule = base.CreateItem();
  164. schedule.DocumentClass = DocumentType.EntityName();
  165. schedule.DocumentID = DocumentID;
  166. if (DocumentType == typeof(CustomModule) || DocumentType == typeof(ScheduledScript))
  167. schedule.ScheduleType = ScheduleType.None;
  168. return schedule;
  169. }
  170. public override void SaveItem(Schedule item)
  171. {
  172. if(DocumentType is not null)
  173. {
  174. item.DocumentClass = DocumentType.EntityName();
  175. }
  176. else
  177. {
  178. if (string.IsNullOrWhiteSpace(item.DocumentClass))
  179. {
  180. throw new Exception("Cannot save item when DocumentType is null.");
  181. }
  182. }
  183. base.SaveItem(item);
  184. }
  185. protected override void DoReconfigureEditors(DynamicEditorGrid grid, Schedule[] items)
  186. {
  187. base.DoReconfigureEditors(grid, items);
  188. var frequency = grid.FindEditor("Frequency");
  189. if (frequency != null)
  190. {
  191. var freq = (int)frequency.GetValue("Frequency");
  192. var period = grid.FindEditor("Period");
  193. period?.SetEnabled(freq > 0);
  194. var due = grid.FindEditor("DueDate");
  195. due?.SetEnabled(freq > 0);
  196. }
  197. var threshold = grid.FindEditor("Threshold");
  198. if (threshold != null)
  199. {
  200. var thresh = (int)threshold.GetValue("Threshold");
  201. var trigger = grid.FindEditor("Trigger");
  202. trigger?.SetEnabled(thresh > 0);
  203. var next = grid.FindEditor("DueThreshold");
  204. next?.SetEnabled(thresh > 0);
  205. }
  206. var scheduleTypeEditor = grid.FindEditor("ScheduleType");
  207. if(scheduleTypeEditor != null)
  208. {
  209. var scheduleType = (ScheduleType)scheduleTypeEditor.GetValue("ScheduleType");
  210. var taskTypeEditor = grid.FindEditor(nameof(Schedule.KanbanType));
  211. taskTypeEditor?.SetEnabled(scheduleType == ScheduleType.Task);
  212. }
  213. }
  214. protected override Dictionary<string, object?> EditorValueChanged(IDynamicEditorForm editor, Schedule[] items, string name, object value)
  215. {
  216. return base.EditorValueChanged(editor, items, name, value);
  217. }
  218. protected override BaseEditor? GetEditor(object item, DynamicGridColumn column)
  219. {
  220. var types = new List<Type> { typeof(CustomModule), typeof(ScheduledScript), typeof(Employee), typeof(Equipment) };
  221. var columns = new List<string> { "ScheduleType" };
  222. var schedule = (Schedule)item;
  223. var documentType = schedule.DocumentType();
  224. if (documentType == typeof(CustomModule) || documentType == typeof(ScheduledScript))
  225. columns.AddRange(new[]
  226. {
  227. "Description", "LeadTime", "EmployeeLink.ID", "ManagerLink.ID", "Report.ID", "Threshold", "Trigger", "DueThreshold", "Rollover",
  228. "QAForm"
  229. });
  230. else if (documentType == typeof(Employee))
  231. columns.AddRange(new[] { "Description", "EmployeeLink.ID", "Threshold", "Trigger", "DueThreshold" });
  232. else if (documentType == typeof(Customer))
  233. columns.AddRange(new[] { "Threshold", "Trigger", "DueThreshold" });
  234. if (types.Contains(documentType) && columns.Contains(column.ColumnName))
  235. return new NullEditor();
  236. return base.GetEditor(item, column);
  237. }
  238. public override DynamicEditorPages LoadEditorPages(Schedule item)
  239. {
  240. var pages = base.LoadEditorPages(item);
  241. foreach (var page in pages.ToArray())
  242. {
  243. if (page is IDynamicOneToManyGrid<Schedule, Kanban> && item.ScheduleType != ScheduleType.Task)
  244. pages = new DynamicEditorPages(pages.Where(x => x != page));
  245. else if (page is IDynamicOneToManyGrid<Schedule, Job> && item.ScheduleType != ScheduleType.Job)
  246. pages = new DynamicEditorPages(pages.Where(x => x != page));
  247. }
  248. return pages;
  249. }
  250. protected override void DefineLookups(ILookupEditorControl sender, Schedule[] items, bool async = true)
  251. {
  252. base.DefineLookups(sender, items, async);
  253. }
  254. }
  255. }