EquipmentPlanner.xaml.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Linq;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Data;
  9. using System.Windows.Input;
  10. using System.Windows.Media;
  11. using System.Windows.Media.Imaging;
  12. using Comal.Classes;
  13. using InABox.Clients;
  14. using InABox.Configuration;
  15. using InABox.Core;
  16. using InABox.DynamicGrid;
  17. using InABox.WPF;
  18. using Syncfusion.UI.Xaml.Grid;
  19. using Syncfusion.UI.Xaml.Grid.Helpers;
  20. using Syncfusion.Windows.Shared;
  21. using MultiQuery = InABox.Core.MultiQuery;
  22. using SelectionChangedEventArgs = System.Windows.Controls.SelectionChangedEventArgs;
  23. namespace PRSDesktop
  24. {
  25. public class EquipmentPlannerValue
  26. {
  27. public Guid ID { get; set; }
  28. public Brush Background { get; set; }
  29. public Brush Foreground { get; set; }
  30. public String Text { get; set; }
  31. private String _color = "";
  32. public String Color
  33. {
  34. get { return _color; }
  35. set
  36. {
  37. _color = value;
  38. var color = String.IsNullOrWhiteSpace(value) ? Colors.Transparent : (Color)ColorConverter.ConvertFromString(value);
  39. Background = new SolidColorBrush(color) { Opacity = 0.8 };
  40. Foreground = new SolidColorBrush(ImageUtils.GetForegroundColor(color)) { Opacity = 0.8 };
  41. }
  42. }
  43. }
  44. public class EquipmentResourceModel : Model<EquipmentResourceModel,Equipment>
  45. {
  46. public String? Code { get; }
  47. public BitmapImage? Image { get; set; }
  48. public EquipmentActivity[] Activities { get; private set; }
  49. public EquipmentResourceModel(CoreRow row, BitmapImage? image, EquipmentActivity[] activities) : base(row)
  50. {
  51. Activities = activities;
  52. Code = Get(c => c.Code);
  53. Image = image;
  54. }
  55. public override Columns<Equipment> GetColumns()
  56. {
  57. return InABox.Core.Columns.None<Equipment>().Add(c => c.ID)
  58. .Add(c => c.Code)
  59. .Add(c=>c.GroupLink.ID);
  60. }
  61. }
  62. public class TimeSlot
  63. {
  64. public TimeSpan From { get; set; }
  65. public TimeSpan To { get; set; }
  66. public TimeSlot(TimeSpan from, TimeSpan to)
  67. {
  68. From = from;
  69. To = to;
  70. }
  71. public override string ToString()
  72. {
  73. return $"{From:HH\\:mm}";
  74. }
  75. }
  76. public partial class EquipmentPlanner : UserControl
  77. {
  78. private enum Suppress
  79. {
  80. This
  81. }
  82. private EquipmentResourceModel[] _equipment = new EquipmentResourceModel[] { };
  83. private JobModel[] _jobs = new JobModel[] { };
  84. private CoreFilterDefinitions _jobfilters = new CoreFilterDefinitions();
  85. public event LoadSettings<EquipmentPlannerProperties> LoadSettings;
  86. public event SaveSettings<EquipmentPlannerProperties> SaveSettings;
  87. private void DoLoadSettings()
  88. {
  89. Properties = LoadSettings?.Invoke(this) ?? new EquipmentPlannerProperties();
  90. _jobfilters = new GlobalConfiguration<CoreFilterDefinitions>("Job").Load();
  91. }
  92. private void DoSaveSettings()
  93. {
  94. SaveSettings?.Invoke(this, Properties);
  95. }
  96. public EquipmentPlannerProperties Properties { get; set; }
  97. public EquipmentPlanner()
  98. {
  99. using (new EventSuppressor(Suppress.This))
  100. InitializeComponent();
  101. }
  102. private Filter<Job>? GetJobFilter()
  103. {
  104. var jobfilter = _jobfilters.FirstOrDefault(x => String.Equals(x.Name, Properties.JobFilter));
  105. return !String.IsNullOrWhiteSpace(jobfilter?.Filter)
  106. ? Serialization.Deserialize<Filter<Job>>(jobfilter.Filter)
  107. : LookupFactory.DefineFilter<Job>();
  108. }
  109. public void Setup()
  110. {
  111. using (new EventSuppressor(Suppress.This))
  112. {
  113. DoLoadSettings();
  114. EquipmentSelector.Setup();
  115. EquipmentSelector.Settings = Properties.EquipmentSettings;
  116. EquipmentSelector.Selection = Properties.EquipmentSelection;
  117. FromDate.DateTime = DateTime.Today;
  118. ToDate.DateTime = DateTime.Today.AddYears(1);
  119. MultiQuery query = new MultiQuery();
  120. query.Add<Job>(
  121. GetJobFilter(),
  122. JobModel.Columns,
  123. new SortOrder<Job>(x => x.JobNumber)
  124. );
  125. query.Query();
  126. _jobs = query.Get<Job>().Rows.Select(r => new JobModel(r)).ToArray();
  127. JobFilter.ItemsSource = _jobfilters;
  128. JobFilter.SelectedValue = _jobfilters.FirstOrDefault(x => String.Equals(x.Name, Properties.JobFilter));
  129. }
  130. }
  131. public void Shutdown(CancelEventArgs? cancel)
  132. {
  133. }
  134. public void Refresh()
  135. {
  136. using (new WaitCursor())
  137. {
  138. _equipment = EquipmentSelector.GetEquipmentData((row, img, activities) => new EquipmentResourceModel(row, img, activities));
  139. var eqids = _equipment.Select(x => x.ID).ToArray();
  140. DateTime fromdate = FromDate.DateTime.HasValue ? FromDate.DateTime.Value.Date : DateTime.Today;
  141. DateTime todate = ToDate.DateTime.HasValue ? ToDate.DateTime.Value.Date : DateTime.Today.AddYears(1);
  142. MultiQuery query = new MultiQuery();
  143. query.Add<EquipmentAssignment>(
  144. new Filter<EquipmentAssignment>(x => x.Equipment.ID).InList(eqids)
  145. .And(x => x.Date).IsGreaterThanOrEqualTo(fromdate)
  146. .And(x => x.Date).IsLessThanOrEqualTo(todate),
  147. EquipmentAssignmentModel.Columns,
  148. new SortOrder<EquipmentAssignment>(x => x.Equipment.ID).ThenBy(x => x.Date).ThenBy(x => x.Booked.Duration, SortDirection.Descending)
  149. );
  150. query.Query();
  151. var assignments = query.Get<EquipmentAssignment>().Rows.Select(r => new EquipmentAssignmentModel(r)).ToArray();
  152. var data = new DataTable();
  153. data.Columns.Add("Date", typeof(DateTime));
  154. data.Columns.Add("From", typeof(TimeSpan));
  155. data.Columns.Add("To", typeof(TimeSpan));
  156. foreach (var equipment in _equipment)
  157. data.Columns.Add(equipment.ID.ToString(), typeof(object));
  158. for (var curdate = fromdate; curdate <= todate; curdate = curdate.AddDays(1))
  159. {
  160. foreach (var slot in Properties.TimeSlots)
  161. {
  162. var values = new List<object> { curdate, slot.From, slot.To };
  163. foreach (var equipment in _equipment)
  164. {
  165. var value = new EquipmentPlannerValue();
  166. var bOK = CheckAssignments(equipment, curdate, slot, assignments, value);
  167. //bOK = bOK || CheckRoster(employee, curdate, value);
  168. //bOK = bOK || CheckStandardLeave(leavevalue, value);
  169. //bOK = bOK || CheckLeaveRequest(employee, curdate, _leaverequests, value);
  170. values.Add(value);
  171. }
  172. data.Rows.Add(values.ToArray());
  173. }
  174. }
  175. dataGrid.ItemsSource = data;
  176. }
  177. }
  178. private bool CheckAssignments(EquipmentResourceModel equipment, DateTime curdate, TimeSlot slot, EquipmentAssignmentModel[] assignments, EquipmentPlannerValue value)
  179. {
  180. var assignment = assignments.FirstOrDefault(x => (x.EquipmentID == equipment.ID) && (x.Date == curdate.Date) && (x.BookedStart < slot.To) && (x.BookedFinish > slot.From));
  181. var bgColor = Properties.WorkDays.Contains(curdate.DayOfWeek)
  182. ? System.Drawing.Color.LightYellow
  183. : System.Drawing.Color.LightGray;
  184. value.Color = ImageUtils.ColorToString(bgColor);
  185. if (assignment == null)
  186. return false;
  187. value.ID = assignment.ID;
  188. value.Text = (value.ID != Guid.Empty) ? assignment?.JobNumber ?? "" : "XX";
  189. value.Color = ImageUtils.ColorToString(System.Drawing.Color.LightGreen);
  190. return true;
  191. }
  192. #region AutoGenerate Columns / Styling
  193. private class EquipmentResourcePlannerBackgroundConverter : AbstractConverter<EquipmentPlannerValue, Brush>
  194. {
  195. public override Brush Convert(EquipmentPlannerValue value) => value?.Background ?? new SolidColorBrush(Colors.LightYellow) { Opacity = 0.8 };
  196. }
  197. private class EquipmentResourcePlannerForegroundConverter : AbstractConverter<EquipmentPlannerValue, Brush>
  198. {
  199. public override Brush Convert(EquipmentPlannerValue value) => value?.Foreground ?? new SolidColorBrush(Colors.DimGray) { Opacity = 0.8 };
  200. }
  201. private class EquipmentResourcePlannerFontStyleConverter : AbstractConverter<EquipmentPlannerValue, FontStyle>
  202. {
  203. public override FontStyle Convert(EquipmentPlannerValue value) => FontStyles.Normal;
  204. }
  205. private class EquipmentResourcePlannerFontWeightConverter : AbstractConverter<EquipmentPlannerValue, FontWeight>
  206. {
  207. public override FontWeight Convert(EquipmentPlannerValue value) => FontWeights.Normal;
  208. }
  209. private class EquipmentResourcePlannerContentConverter : AbstractConverter<EquipmentPlannerValue, String?>
  210. {
  211. public override String? Convert(EquipmentPlannerValue value) => value?.Text;
  212. }
  213. private class DateFormatConverter : AbstractConverter<DateTime, String>
  214. {
  215. public String Format { get; private set; }
  216. public override string Convert(DateTime value)
  217. {
  218. return String.Format($"{{0:{Format}}}", value);
  219. }
  220. public DateFormatConverter(string format)
  221. {
  222. Format = format;
  223. }
  224. }
  225. private void DataGrid_AutoGeneratingColumn(object? sender, AutoGeneratingColumnArgs e)
  226. {
  227. e.Column.TextAlignment = TextAlignment.Center;
  228. e.Column.HorizontalHeaderContentAlignment = HorizontalAlignment.Center;
  229. e.Column.ColumnSizer = GridLengthUnitType.None;
  230. var value = (e.Column.ValueBinding as Binding)!;
  231. if (value.Path.Path.Equals("Date")) // && e.Column is GridDateTimeColumn dt)
  232. {
  233. if (dataGrid.Columns.FirstOrDefault() is GridTemplateColumn)
  234. e.Cancel = true;
  235. else
  236. {
  237. var col = new GridTemplateColumn();
  238. col.CellTemplate = TemplateGenerator.CreateDataTemplate(() =>
  239. {
  240. var stack = new StackPanel()
  241. {
  242. Orientation = Orientation.Vertical,
  243. VerticalAlignment = VerticalAlignment.Center,
  244. HorizontalAlignment = HorizontalAlignment.Stretch
  245. };
  246. var day = new Label()
  247. {
  248. HorizontalContentAlignment = HorizontalAlignment.Center
  249. };
  250. day.SetBinding(Label.ContentProperty, new Binding("Date") { Converter = new DateFormatConverter("dddd") });
  251. stack.Children.Add(day);
  252. var date = new Label()
  253. {
  254. HorizontalContentAlignment = HorizontalAlignment.Center
  255. };
  256. date.SetBinding(Label.ContentProperty, new Binding("Date") { Converter = new DateFormatConverter("dd MMM yy") });
  257. stack.Children.Add(date);
  258. return stack;
  259. });
  260. col.Width = 70;
  261. col.HeaderStyle = Resources["DateHeaderStyle"] as Style;
  262. col.HeaderText = "Date";
  263. col.AllowFocus = false;
  264. e.Column = col;
  265. }
  266. //dt.Width = 70;
  267. //dt.HeaderStyle = Resources["DateHeaderStyle"] as Style;
  268. //dt.AllowFocus = false;
  269. //dt.CustomPattern = "dd MMM yy";
  270. //dt.Pattern = DateTimePattern.CustomPattern;
  271. }
  272. else if (value.Path.Path.Equals("From") && e.Column is GridTimeSpanColumn ts)
  273. {
  274. ts.Width = Properties.TimeSlots.Length > 1 ? 50 : 0;
  275. ts.HeaderText = "Time";
  276. ts.HeaderStyle = Resources["TimeHeaderStyle"] as Style;
  277. ts.Format = "hh:mm";
  278. ts.AllowFocus = false;
  279. }
  280. else if (value.Path.Path.Equals("To"))
  281. {
  282. e.Column.Width = 0;
  283. e.Column.HeaderStyle = Resources["TimeHeaderStyle"] as Style;
  284. e.Column.AllowFocus = false;
  285. }
  286. else
  287. {
  288. var col = new GridTemplateColumn();
  289. col.CellTemplate = TemplateGenerator.CreateDataTemplate(() =>
  290. {
  291. var grid = new Grid()
  292. {
  293. VerticalAlignment = VerticalAlignment.Stretch,
  294. HorizontalAlignment = HorizontalAlignment.Stretch
  295. };
  296. grid.ColumnDefinitions.Add(new ColumnDefinition() {Width = new GridLength(1, GridUnitType.Star)});
  297. grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star)});
  298. grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto)});
  299. var job = new Label()
  300. {
  301. HorizontalContentAlignment = HorizontalAlignment.Center,
  302. VerticalContentAlignment = VerticalAlignment.Center
  303. };
  304. job.SetValue(Grid.ColumnProperty,0);
  305. job.SetValue(Grid.RowProperty,0);
  306. //day.SetBinding(Label.ContentProperty, new Binding("Date") { Converter = new DateFormatConverter("dddd") });
  307. grid.Children.Add(job);
  308. return grid;
  309. });
  310. col.Width = 80;
  311. col.HeaderStyle = Resources["ContentHeaderStyle"] as Style;
  312. col.AllowFocus = true;
  313. var style = new Style(typeof(GridCell));
  314. style.Setters.Add(new Setter(BackgroundProperty, new Binding(value.Path.Path) { Converter = new EquipmentResourcePlannerBackgroundConverter() }));
  315. style.Setters.Add(new Setter(ForegroundProperty, new Binding(value.Path.Path) { Converter = new EquipmentResourcePlannerForegroundConverter() }));
  316. col.CellStyle = style;
  317. col.HeaderText = (Guid.TryParse(value.Path.Path, out Guid id))
  318. ? _equipment.FirstOrDefault(x => String.Equals(x.ID, id))?.Code ?? value.Path.Path
  319. : value.Path.Path;
  320. e.Column = col;
  321. // var style = new Style(typeof(GridCell));
  322. // style.Setters.Add(new Setter(BackgroundProperty, new Binding(value.Path.Path) { Converter = new EquipmentResourcePlannerBackgroundConverter() }));
  323. // style.Setters.Add(new Setter(ForegroundProperty, new Binding(value.Path.Path) { Converter = new EquipmentResourcePlannerForegroundConverter() }));
  324. // style.Setters.Add(new Setter(FontStyleProperty, new Binding(value.Path.Path) { Converter = new EquipmentResourcePlannerFontStyleConverter() }));
  325. // style.Setters.Add(new Setter(FontWeightProperty, new Binding(value.Path.Path) { Converter = new EquipmentResourcePlannerFontWeightConverter() }));
  326. // e.Column.CellStyle = style;
  327. // e.Column.Width = 80;
  328. // e.Column.HeaderStyle = Resources["ContentHeaderStyle"] as Style;
  329. //
  330. // e.Column.HeaderText = (Guid.TryParse(value.Path.Path, out Guid id))
  331. // ? _equipment.FirstOrDefault(x => String.Equals(x.ID, id))?.Code ?? value.Path.Path
  332. // : value.Path.Path;
  333. //
  334. // e.Column.DisplayBinding = new Binding { Path = new PropertyPath(e.Column.MappingName), Converter = new EquipmentResourcePlannerContentConverter() };
  335. // //e.Column.ValueBinding = new Binding() { Path = new PropertyPath(e.Column.MappingName), Converter = new LeaveContentConverter() };
  336. // //e.Column.UseBindingValue = true;
  337. // e.Column.AllowFocus = true;
  338. }
  339. }
  340. #endregion
  341. private bool HasData()
  342. {
  343. foreach (var cell in dataGrid.GetSelectedCells())
  344. {
  345. if (!cell.IsDataRowCell)
  346. continue;
  347. var propertyCollection = dataGrid.View.GetPropertyAccessProvider();
  348. var cellValue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName);
  349. if (cellValue is EquipmentPlannerValue val && val.ID != Guid.Empty)
  350. return true;
  351. }
  352. return false;
  353. }
  354. private bool HasData(GridCellInfo cell)
  355. {
  356. if (!cell.IsDataRowCell)
  357. return false;
  358. var propertyCollection = dataGrid.View.GetPropertyAccessProvider();
  359. var cellValue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName);
  360. return cellValue is EquipmentPlannerValue val && val.ID != Guid.Empty;
  361. }
  362. private void DataGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
  363. {
  364. var vc = dataGrid.GetVisualContainer();
  365. var p = Mouse.GetPosition(vc);
  366. var rci = vc.PointToCellRowColumnIndex(p);
  367. if (rci.RowIndex < 1 || rci.ColumnIndex < 1)
  368. {
  369. e.Handled = true;
  370. return;
  371. }
  372. dataGrid.ContextMenu.Items.Clear();
  373. var bAssign = !HasData(dataGrid.CurrentCellInfo);
  374. var bClear = HasData();
  375. if (bAssign)
  376. {
  377. foreach (var job in _jobs)
  378. {
  379. var assign = new MenuItem
  380. {
  381. Header = job.Name,
  382. Tag = job
  383. };
  384. assign.Click += AssignJobClick;
  385. dataGrid.ContextMenu.Items.Add(assign);
  386. }
  387. }
  388. if (bClear && bAssign)
  389. dataGrid.ContextMenu.Items.Add(new Separator());
  390. if (bClear)
  391. {
  392. var clear = new MenuItem { Header = "Clear Assignments" };
  393. clear.Click += ClearJobClick;
  394. dataGrid.ContextMenu.Items.Add(clear);
  395. }
  396. }
  397. private void GetSelectionData(out DateTime from, out DateTime to, out Guid[] employees, out Guid[] assignments)
  398. {
  399. var emps = new List<Guid>();
  400. var items = new List<Guid>();
  401. from = DateTime.MaxValue;
  402. to = DateTime.MinValue;
  403. foreach (var cell in dataGrid.GetSelectedCells())
  404. {
  405. var binding = (cell.Column.ValueBinding as Binding)!;
  406. if (Guid.TryParse(binding.Path.Path, out var emp))
  407. if (!emps.Contains(emp))
  408. emps.Add(emp);
  409. var row = (cell.RowData as DataRowView)!;
  410. var date = (DateTime)row.Row.ItemArray.First()!;
  411. var fromtime = (TimeSpan)row.Row.ItemArray.Skip(1).First()!;
  412. var totime = (TimeSpan)row.Row.ItemArray.Skip(2).First()!;
  413. if (date.Add(fromtime) < from)
  414. from = date.Add(fromtime);
  415. if (date.Add(totime) > to)
  416. to = date.Add(totime);
  417. Guid itemid = (row[binding.Path.Path] as EquipmentPlannerValue).ID;
  418. if (itemid != Guid.Empty)
  419. items.Add(itemid);
  420. }
  421. employees = emps.ToArray();
  422. assignments = items.ToArray();
  423. }
  424. private void AssignJobClick(object sender, RoutedEventArgs e)
  425. {
  426. JobModel? job = (sender as MenuItem)?.Tag as JobModel;
  427. if (job == null)
  428. return;
  429. GetSelectionData(out var from, out var to, out var ids, out var assignments);
  430. var updates = new List<EquipmentAssignment>();
  431. foreach (var id in ids)
  432. {
  433. for (DateTime curdate = from.Date; curdate <= to.Date; curdate = curdate.AddDays(1))
  434. {
  435. var equipment = _equipment.FirstOrDefault(x => x.ID == id);
  436. if (equipment != null)
  437. {
  438. var assign = new EquipmentAssignment();
  439. assign.Date = curdate;
  440. assign.Booked.Start = curdate == from.Date ? from.TimeOfDay : Properties.TimeSlots.FirstOrDefault()?.From ?? TimeSpan.Zero;
  441. assign.Booked.Finish = curdate == to.Date ? to.TimeOfDay : Properties.TimeSlots.LastOrDefault()?.To ?? TimeSpan.FromDays(1).Subtract(TimeSpan.FromSeconds(1));
  442. assign.JobLink.ID = job.ID;
  443. assign.Equipment.ID = id;
  444. updates.Add(assign);
  445. }
  446. }
  447. }
  448. if (updates.Any())
  449. {
  450. using (new WaitCursor())
  451. {
  452. new Client<EquipmentAssignment>().Save(updates, "Assigned from Employee Resource Planner");
  453. Refresh();
  454. }
  455. }
  456. }
  457. private void ClearJobClick(object sender, RoutedEventArgs e)
  458. {
  459. GetSelectionData(out DateTime from, out DateTime to, out Guid[] ids, out Guid[] assignments);
  460. if (assignments.Any() && MessageBox.Show("Clear Assignments?", "Confirm", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
  461. {
  462. var deletes = assignments.Select(x => new EquipmentAssignment() { ID = x }).ToArray();
  463. using (new WaitCursor())
  464. {
  465. new Client<EquipmentAssignment>().Delete(deletes, "Deleted from Employee Resource Planner");
  466. Refresh();
  467. }
  468. }
  469. }
  470. public void Heartbeat(TimeSpan time)
  471. {
  472. }
  473. private void _equipment_OnSettingsChanged(object sender, EquipmentSelectorSettingsChangedArgs args)
  474. {
  475. Properties.EquipmentSettings = args.Settings;
  476. DoSaveSettings();
  477. }
  478. private void _equipment_OnSelectionChanged(object sender, EquipmentSelectorSelectionChangedArgs args)
  479. {
  480. Properties.EquipmentSelection = args.Selection;
  481. DoSaveSettings();
  482. Refresh();
  483. }
  484. private void DateTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  485. {
  486. if (EventSuppressor.IsSet(Suppress.This))
  487. return;
  488. Refresh();
  489. }
  490. private void JobFilter_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
  491. {
  492. if (EventSuppressor.IsSet(Suppress.This))
  493. return;
  494. var sel = JobFilter.SelectedValue as CoreFilterDefinition;
  495. Properties.JobFilter = sel?.Name ?? "";
  496. using (new WaitCursor())
  497. {
  498. DoSaveSettings();
  499. _jobs = new Client<Job>().Query(
  500. GetJobFilter(),
  501. JobModel.Columns,
  502. new SortOrder<Job>(x => x.JobNumber)
  503. ).Rows.Select(r => new JobModel(r)).ToArray();
  504. }
  505. }
  506. private void JobFilterButton_Click(object sender, RoutedEventArgs e)
  507. {
  508. var window = new DynamicGridFilterEditor(_jobfilters, typeof(Job));
  509. if (window.ShowDialog() == true)
  510. {
  511. new GlobalConfiguration<CoreFilterDefinitions>("Job").Save(_jobfilters);
  512. JobFilter.SelectedValue = _jobfilters.FirstOrDefault(x => String.Equals(x.Name, Properties.JobFilter));
  513. }
  514. }
  515. private void DataGrid_OnQueryCoveredRange(object? sender, GridQueryCoveredRangeEventArgs e)
  516. {
  517. if (Properties.TimeSlots.Length <= 1 || e.RowColumnIndex.RowIndex == 0)
  518. return;
  519. if (e.RowColumnIndex.ColumnIndex == 0)
  520. {
  521. var top = (((e.RowColumnIndex.RowIndex - 1) / Properties.TimeSlots.Length) * Properties.TimeSlots.Length) + 1;
  522. var bottom = top + Properties.TimeSlots.Length - 1;
  523. try
  524. {
  525. e.Range = new CoveredCellInfo(0, 0, top, bottom);
  526. }
  527. catch (Exception _exception)
  528. {
  529. System.Console.WriteLine(_exception);
  530. throw;
  531. }
  532. }
  533. else if (e.Record is DataRowView drv && e.RowColumnIndex.ColumnIndex > 1 && e.RowColumnIndex.ColumnIndex < drv.Row.ItemArray.Length && drv.Row.ItemArray[e.RowColumnIndex.ColumnIndex] is EquipmentPlannerValue epv)
  534. {
  535. if (epv.ID != Guid.Empty)
  536. {
  537. int iMin = int.MaxValue;
  538. int iMax = int.MinValue;
  539. var rows = drv.DataView.OfType<DataRowView>().ToArray();
  540. for (int i = 0; i < drv.DataView.Count; i++)
  541. {
  542. var test = drv.DataView[i].Row.ItemArray[e.RowColumnIndex.ColumnIndex] as EquipmentPlannerValue;
  543. if (test != null && test.ID == epv.ID)
  544. {
  545. if (i < iMin)
  546. iMin = i;
  547. if (i > iMax)
  548. iMax = i;
  549. }
  550. }
  551. e.Range = new CoveredCellInfo(e.RowColumnIndex.ColumnIndex, e.RowColumnIndex.ColumnIndex, iMin+1, iMax+1);
  552. }
  553. }
  554. e.Handled = true;
  555. }
  556. }
  557. }