LeaveCalendar.xaml.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Diagnostics;
  5. using System.Diagnostics.CodeAnalysis;
  6. using System.Globalization;
  7. using System.Linq;
  8. using System.Threading.Tasks;
  9. using System.Windows;
  10. using System.Windows.Controls;
  11. using System.Windows.Data;
  12. using System.Windows.Input;
  13. using System.Windows.Media;
  14. using Comal.Classes;
  15. using InABox.Clients;
  16. using InABox.Configuration;
  17. using InABox.Core;
  18. using InABox.DynamicGrid;
  19. using InABox.WPF;
  20. using Microsoft.Win32;
  21. using NPOI.OpenXmlFormats.Wordprocessing;
  22. using PRS.Shared;
  23. using PRSDesktop.Grids;
  24. using Syncfusion.UI.Xaml.Grid;
  25. using Syncfusion.UI.Xaml.Grid.Converter;
  26. using Syncfusion.UI.Xaml.Grid.Helpers;
  27. using Syncfusion.Windows.Tools.Controls;
  28. using Syncfusion.XlsIO;
  29. using Activity = Comal.Classes.Activity;
  30. using Columns = InABox.Core.Columns;
  31. using SelectionChangedEventArgs = System.Windows.Controls.SelectionChangedEventArgs;
  32. namespace PRSDesktop;
  33. public class LeaveValue
  34. {
  35. public LeaveValue(Guid id, Guid employee, DateTime date, Guid activity, LeaveRequestStatus status, bool standard)
  36. {
  37. ID = id;
  38. Employee = employee;
  39. Date = date;
  40. Activity = activity;
  41. Status = status;
  42. Standard = standard;
  43. }
  44. public Guid ID { get; set; }
  45. public Guid Employee { get; set; }
  46. public DateTime Date { get; set; }
  47. public Guid Activity { get; set; }
  48. public LeaveRequestStatus Status { get; set; }
  49. public bool Standard { get; set; }
  50. }
  51. public class LeaveBackgroundConverter : IValueConverter
  52. {
  53. public Dictionary<Guid, Color>? Colors { get; set; }
  54. // Guid - EmployeeID
  55. // DateTime - Employee Start Date
  56. // DateTime - Employee Finish Date
  57. // EmployeeRoster[] Roster Data
  58. // DateTime - Roster Start
  59. public List<Tuple<Guid, DateTime, DateTime, EmployeeRosterItem[], DateTime>> Rosters { get; set; }
  60. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  61. {
  62. if(value is not LeaveValue val)
  63. return DependencyProperty.UnsetValue;
  64. if (val.ID == Guid.Empty)
  65. {
  66. var tuple = Rosters?.FirstOrDefault(x => x.Item1 == val.Employee);
  67. if (tuple == null)
  68. return new SolidColorBrush(System.Windows.Media.Colors.Red) { Opacity = 0.8 };
  69. if ( (!tuple.Item2.IsEmpty() && (tuple.Item2 > val.Date)) || (!tuple.Item3.IsEmpty() && (tuple.Item3 < val.Date)))
  70. return new SolidColorBrush(System.Windows.Media.Colors.LightGray) { Opacity = 0.8 };
  71. var roster = RosterUtils.GetRoster(tuple?.Item4, tuple?.Item5, val.Date);
  72. return (roster?.Enabled == true)
  73. ? roster?.Duration < 5.0F
  74. ? new System.Windows.Media.LinearGradientBrush(
  75. System.Windows.Media.Colors.LightYellow,
  76. System.Windows.Media.Colors.LightGray,
  77. 90.0F
  78. ) { Opacity = 0.8 }
  79. : new SolidColorBrush(System.Windows.Media.Colors.LightYellow) { Opacity = 0.8 }
  80. : new SolidColorBrush(System.Windows.Media.Colors.LightGray) { Opacity = 0.8 };
  81. }
  82. else
  83. {
  84. if (val.Status != LeaveRequestStatus.Approved)
  85. return new SolidColorBrush(System.Windows.Media.Colors.DimGray) { Opacity = 0.8 };
  86. if (Colors != null)
  87. if (Colors.ContainsKey(val.Activity))
  88. return new SolidColorBrush(Colors[val.Activity]) { Opacity = 0.5 };
  89. }
  90. return DependencyProperty.UnsetValue;
  91. }
  92. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  93. {
  94. throw new NotImplementedException();
  95. }
  96. }
  97. public class LeaveForegroundConverter : IValueConverter
  98. {
  99. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  100. {
  101. if (value is LeaveValue val
  102. && val.ID != Guid.Empty
  103. && val.Status != LeaveRequestStatus.Approved)
  104. {
  105. return new SolidColorBrush(Colors.LightGray);
  106. }
  107. return DependencyProperty.UnsetValue;
  108. }
  109. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  110. {
  111. throw new NotImplementedException();
  112. }
  113. }
  114. public class LeaveFontStyleConverter : IValueConverter
  115. {
  116. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  117. {
  118. if (value is LeaveValue val
  119. && val.ID != Guid.Empty
  120. && val.Status != LeaveRequestStatus.Approved)
  121. {
  122. return FontStyles.Italic;
  123. }
  124. return DependencyProperty.UnsetValue;
  125. }
  126. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  127. {
  128. throw new NotImplementedException();
  129. }
  130. }
  131. public class LeaveFontWeightConverter : IValueConverter
  132. {
  133. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  134. {
  135. return FontWeights.Bold;
  136. }
  137. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  138. {
  139. throw new NotImplementedException();
  140. }
  141. }
  142. public class LeaveContentConverter : IValueConverter
  143. {
  144. public Dictionary<Guid, string>? Abbreviations { get; set; }
  145. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  146. {
  147. if (value is not LeaveValue val)
  148. return DependencyProperty.UnsetValue;
  149. return Abbreviations?.ContainsKey(val.Activity) == true ? Abbreviations[val.Activity] : DependencyProperty.UnsetValue;
  150. }
  151. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  152. {
  153. throw new NotImplementedException();
  154. }
  155. }
  156. /// <summary>
  157. /// Interaction logic for LeaveCalendar.xaml
  158. /// </summary>
  159. public partial class LeaveCalendar : UserControl
  160. {
  161. private readonly CoreTable _activities;
  162. private readonly Dictionary<Guid, string> _activityCodes = new();
  163. private readonly Dictionary<Guid, Color> _activityColors = new();
  164. private readonly Dictionary<Guid, string> _employees = new();
  165. private readonly List<Tuple<Guid, DateTime, DateTime, EmployeeRosterItem[], DateTime>> _rosters = new();
  166. private readonly CoreTable _employeeteams;
  167. private LeaveSettings _settings;
  168. private readonly Dictionary<Guid, string> _teams = new();
  169. private bool bReady;
  170. private LeaveRequestGrid? lg;
  171. private StandardLeaveGrid? sg;
  172. public LeaveCalendar()
  173. {
  174. InitializeComponent();
  175. //dataGrid.ScrollMode = ScrollMode.Async;
  176. LoadSettings();
  177. StartDate.DateTime = DateTime.Today;
  178. EndDate.DateTime = DateTime.Today.AddYears(1);
  179. var setups = new MultiQuery();
  180. setups.Add<EmployeeTeam>(null, null, new SortOrder<EmployeeTeam>(x => x.TeamLink.Code).ThenBy(x => x.EmployeeLink.Name));
  181. setups.Add<Activity>(new Filter<Activity>(x => x.IsLeave).IsEqualTo(true));
  182. setups.Query();
  183. _employeeteams = setups.Get<EmployeeTeam>();
  184. _activities = setups.Get<Activity>();
  185. _teams = _employeeteams.ToDictionary<EmployeeTeam, Guid, string>(c => c.TeamLink.ID, c => c.TeamLink.Name);
  186. if (_teams.ContainsKey(Guid.Empty))
  187. _teams.Remove(Guid.Empty);
  188. var teams = _employeeteams.ToDictionary<EmployeeTeam, Guid, string>(c => c.TeamLink.ID, c => c.TeamLink.Name);
  189. teams[CoreUtils.FullGuid] = "Multiple Teams";
  190. Teams.ItemsSource = teams;
  191. Teams.SelectedValue = _settings.GroupID;
  192. ChangeSelectedTeams(_settings.GroupID);
  193. OnlyShowLeaveBox.IsChecked = _settings.OnlyShowLeave;
  194. SelectedTeams.ItemsSource = _teams;
  195. foreach (KeyValuePair<Guid, string> pair in SelectedTeams.Items)
  196. if (_settings.SelectedGroups.Contains(pair.Key))
  197. SelectedTeams.SelectedItems.Add(pair);
  198. LoadEmployees(false);
  199. foreach (var row in _activities.Rows)
  200. {
  201. var id = row.Get<Activity, Guid>(c => c.ID);
  202. var color = row.Get<Activity, string>(c => c.Color);
  203. if (!string.IsNullOrWhiteSpace(color))
  204. _activityColors[id] = (Color)ColorConverter.ConvertFromString(color);
  205. var code = Codify(row.Get<Activity, string>(c => c.Description));
  206. _activityCodes[id] = Codify(code);
  207. }
  208. var rosterstarts = _employeeteams.ToDictionary<EmployeeTeam, Guid, DateTime>(x => x.EmployeeLink.ID, x => x.EmployeeLink.RosterStart);
  209. var startdates = _employeeteams.ToDictionary<EmployeeTeam, Guid, DateTime>(x => x.EmployeeLink.ID, x => x.EmployeeLink.StartDate);
  210. var finishdates = _employeeteams.ToDictionary<EmployeeTeam, Guid, DateTime>(x => x.EmployeeLink.ID, x => x.EmployeeLink.FinishDate);
  211. var rosters = _employeeteams.ToDictionary<EmployeeTeam, Guid, String>(x => x.EmployeeLink.ID, x => x.EmployeeLink.Roster);
  212. foreach (var empid in startdates.Keys)
  213. {
  214. var startdate = startdates[empid];
  215. var finishdate = finishdates[empid];
  216. var roster = !String.IsNullOrWhiteSpace(rosters[empid])
  217. ? Serialization.Deserialize<List<EmployeeRosterItem>>(rosters[empid]).ToArray()
  218. : null;
  219. var rosterstart = rosterstarts[empid];
  220. _rosters.Add(new Tuple<Guid, DateTime, DateTime, EmployeeRosterItem[], DateTime>(empid, startdate, finishdate, roster, rosterstart));
  221. }
  222. bReady = true;
  223. }
  224. private static string Codify(string name)
  225. {
  226. if (string.IsNullOrWhiteSpace(name))
  227. return "??";
  228. var result = "";
  229. var comps = name.ToUpper().Split(' ');
  230. foreach (var comp in comps)
  231. if (comp.Any())
  232. result += comp.First();
  233. return string.IsNullOrWhiteSpace(result) ? "??" : result;
  234. }
  235. [MemberNotNull(nameof(_settings))]
  236. private void LoadSettings()
  237. {
  238. _settings = new UserConfiguration<LeaveSettings>().Load();
  239. if (!_settings.SelectedGroups.Any() && _settings.GroupID != Guid.Empty)
  240. _settings.SelectedGroups.Add(_settings.GroupID);
  241. if (_settings.ListSize == 0.0F)
  242. _settings.ListSize = 200.0F;
  243. }
  244. private void SaveSettings()
  245. {
  246. if (!bReady)
  247. return;
  248. try
  249. {
  250. _settings.GroupID = Teams.SelectedValue != null ? (Guid)Teams.SelectedValue : Guid.Empty;
  251. _settings.SelectedGroups.Clear();
  252. foreach (var sel in SelectedTeams.SelectedItems)
  253. {
  254. var grp = (KeyValuePair<Guid, string>)sel;
  255. _settings.SelectedGroups.Add(grp.Key);
  256. }
  257. _settings.SelectedEmployees.Clear();
  258. foreach (var sel in SelectedEmployees.SelectedItems)
  259. {
  260. var grp = (KeyValuePair<Guid, string>)sel;
  261. _settings.SelectedEmployees.Add(grp.Key);
  262. }
  263. if (EmployeeGrid.RowDefinitions[1].ActualHeight != 0.0F)
  264. _settings.ListSize = EmployeeGrid.RowDefinitions[1].ActualHeight;
  265. _settings.OnlyShowLeave = OnlyShowLeaveBox.IsChecked == true;
  266. }
  267. catch (Exception e)
  268. {
  269. Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
  270. }
  271. Task.Run(() => { new UserConfiguration<LeaveSettings>().Save(_settings); });
  272. }
  273. public void Refresh()
  274. {
  275. if (!bReady)
  276. return;
  277. using (new WaitCursor())
  278. {
  279. _employees.Clear();
  280. var crosstab = new List<LeaveValue>();
  281. MultiQuery query = new MultiQuery();
  282. var empfilter = new Filter<LeaveRequest>(x => x.EmployeeLink.ID).IsEqualTo(CoreUtils.FullGuid);
  283. foreach (var sel in SelectedEmployees.Items)
  284. {
  285. var emp = (KeyValuePair<Guid, string>)sel;
  286. if (SelectedEmployees.SelectedItems.Contains(emp))
  287. {
  288. empfilter = empfilter.Or(x => x.EmployeeLink.ID).IsEqualTo(emp.Key);
  289. _employees[emp.Key] = emp.Value;
  290. }
  291. }
  292. var start = StartDate.DateTime ?? DateTime.Today;
  293. var end = EndDate.DateTime ?? DateTime.Today.AddYears(1);
  294. var leavefilter = new Filter<LeaveRequest>(x => x.To).IsGreaterThanOrEqualTo(start)
  295. .And(x => x.From).IsLessThanOrEqualTo(end)
  296. .And(x => x.Status).IsNotEqualTo(LeaveRequestStatus.Rejected);
  297. leavefilter.Ands.Add(empfilter);
  298. query.Add<LeaveRequest>(
  299. leavefilter,
  300. Columns.None<LeaveRequest>().Add(x => x.ID)
  301. .Add(x => x.EmployeeLink.ID)
  302. .Add(x => x.From)
  303. .Add(x=>x.FromTime)
  304. .Add(x => x.To)
  305. .Add(x=>x.ToTime)
  306. .Add(x => x.LeaveType.ID)
  307. .Add(x => x.LeaveType.Description)
  308. .Add(x => x.Status)
  309. );
  310. query.Add<StandardLeave>(
  311. new Filter<StandardLeave>(x => x.To).IsGreaterThanOrEqualTo(start).And(x => x.From).IsLessThanOrEqualTo(end),
  312. Columns.None<StandardLeave>().Add(x => x.ID)
  313. .Add(x => x.From)
  314. .Add(x=>x.FromTime)
  315. .Add(x => x.To)
  316. .Add(x=>x.ToTime)
  317. .Add(x => x.LeaveType.ID)
  318. );
  319. query.Query();
  320. var leaverequests = query.Get<LeaveRequest>();
  321. var standardleaves = query.Get<StandardLeave>();
  322. // Set of Employee IDs so that we can restrict the columns only to employees with leave requests.
  323. var employeeSet = new HashSet<Guid>();
  324. foreach (var standardrow in standardleaves.Rows)
  325. {
  326. var id = standardrow.Get<StandardLeave, Guid>(x => x.ID);
  327. var actid = standardrow.Get<StandardLeave, Guid>(x => x.LeaveType.ID);
  328. var from = standardrow.Get<StandardLeave, DateTime>(x => x.From);
  329. from = from < start ? start : from;
  330. var to = standardrow.Get<StandardLeave, DateTime>(x => x.To);
  331. to = to > end ? end : to;
  332. for (var date = from; date <= to; date = date.AddDays(1))
  333. foreach (var empid in _employees.Keys)
  334. crosstab.Add(new LeaveValue(id, empid, date, actid, LeaveRequestStatus.Approved, true));
  335. }
  336. foreach (var leaverow in leaverequests.Rows)
  337. {
  338. var id = leaverow.Get<LeaveRequest, Guid>(x => x.ID);
  339. var empid = leaverow.Get<LeaveRequest, Guid>(x => x.EmployeeLink.ID);
  340. var actid = leaverow.Get<LeaveRequest, Guid>(x => x.LeaveType.ID);
  341. var status = leaverow.Get<LeaveRequest, LeaveRequestStatus>(x => x.Status);
  342. var from = leaverow.Get<LeaveRequest, DateTime>(x => x.From);
  343. from = from < start ? start : from;
  344. var to = leaverow.Get<LeaveRequest, DateTime>(x => x.To);
  345. to = to > end ? end : to;
  346. var totime = leaverow.Get<LeaveRequest, TimeSpan>(x => x.ToTime);
  347. for (var date = from; date < to.Add(totime); date = date.AddDays(1))
  348. {
  349. if(status == LeaveRequestStatus.InProgress || status == LeaveRequestStatus.Approved)
  350. {
  351. employeeSet.Add(empid);
  352. }
  353. crosstab.Add(new LeaveValue(id, empid, date, actid, status, false));
  354. }
  355. }
  356. if (_settings.OnlyShowLeave)
  357. {
  358. var toRemove = _employees.Keys.Where(x => !employeeSet.Contains(x));
  359. foreach(var employee in toRemove)
  360. {
  361. _employees.Remove(employee);
  362. }
  363. }
  364. var data = new DataTable();
  365. data.Columns.Add("Date", typeof(DateTime));
  366. foreach (var employee in _employees.Keys)
  367. data.Columns.Add(employee.ToString(), typeof(object));
  368. for (var date = start; date <= end; date = date.AddDays(1))
  369. {
  370. var values = new List<object> { date };
  371. foreach (var employee in _employees.Keys)
  372. {
  373. LeaveValue value = null;
  374. var roster = _rosters.FirstOrDefault(x => x.Item1 == employee);
  375. if (roster != null)
  376. {
  377. var curroster = RosterUtils.GetRoster(roster.Item4, roster.Item5, date);
  378. if (curroster?.Enabled == true)
  379. {
  380. value = crosstab.FirstOrDefault(x => x.Employee.Equals(employee) && x.Date.Equals(date) && x.Standard);
  381. if (value == null)
  382. value = crosstab.FirstOrDefault(x => x.Employee.Equals(employee) && x.Date.Equals(date) && !x.Standard);
  383. }
  384. }
  385. values.Add(value ?? new LeaveValue(Guid.Empty, employee, date, Guid.Empty, LeaveRequestStatus.InProgress, false));
  386. }
  387. data.Rows.Add(values.ToArray());
  388. }
  389. dataGrid.ItemsSource = data;
  390. }
  391. }
  392. private void DataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e)
  393. {
  394. e.Column.TextAlignment = TextAlignment.Center;
  395. e.Column.HorizontalHeaderContentAlignment = HorizontalAlignment.Center;
  396. e.Column.ColumnSizer = GridLengthUnitType.None;
  397. var value = (e.Column.ValueBinding as Binding)!;
  398. if (value.Path.Path.Equals("Date"))
  399. {
  400. e.Column.Width = 100;
  401. e.Column.HeaderStyle = Resources["DateHeaderStyle"] as Style;
  402. e.Column.AllowFocus = false;
  403. }
  404. else
  405. {
  406. var style = new Style(typeof(GridCell));
  407. style.Setters.Add(new Setter(BackgroundProperty,
  408. new Binding(value.Path.Path)
  409. {
  410. Converter = new LeaveBackgroundConverter
  411. {
  412. Colors = _activityColors,
  413. Rosters = _rosters
  414. }
  415. }));
  416. style.Setters.Add(new Setter(ForegroundProperty, new Binding(value.Path.Path) { Converter = new LeaveForegroundConverter() }));
  417. style.Setters.Add(new Setter(FontStyleProperty, new Binding(value.Path.Path) { Converter = new LeaveFontStyleConverter() }));
  418. style.Setters.Add(new Setter(FontWeightProperty, new Binding(value.Path.Path) { Converter = new LeaveFontWeightConverter() }));
  419. e.Column.CellStyle = style;
  420. e.Column.Width = 30;
  421. e.Column.HeaderStyle = Resources["ContentHeaderStyle"] as Style;
  422. e.Column.HeaderText = _employees[Guid.Parse(value.Path.Path)];
  423. e.Column.DisplayBinding = new Binding
  424. { Path = new PropertyPath(e.Column.MappingName), Converter = new LeaveContentConverter { Abbreviations = _activityCodes } };
  425. //e.Column.ValueBinding = new Binding() { Path = new PropertyPath(e.Column.MappingName), Converter = new LeaveContentConverter() };
  426. //e.Column.UseBindingValue = true;
  427. e.Column.AllowFocus = true;
  428. }
  429. }
  430. //private void DataGrid_FilterItemsPopulating(object sender, GridFilterItemsPopulatingEventArgs e)
  431. //{
  432. // e.FilterControl.FilterMode = FilterMode.AdvancedFilter;
  433. //}
  434. private void GetSelectionData(out DateTime from, out DateTime to, out Guid[] ids)
  435. {
  436. var emps = new List<Guid>();
  437. from = DateTime.MaxValue;
  438. to = DateTime.MinValue;
  439. foreach (var cell in dataGrid.GetSelectedCells())
  440. {
  441. var binding = (cell.Column.ValueBinding as Binding)!;
  442. if (Guid.TryParse(binding.Path.Path, out var emp))
  443. if (!emps.Contains(emp))
  444. emps.Add(emp);
  445. var row = (cell.RowData as DataRowView)!;
  446. var date = (DateTime)row.Row.ItemArray.First()!;
  447. if (date < from)
  448. from = date;
  449. if (date > to)
  450. to = date;
  451. }
  452. ids = emps.Any() ? emps.ToArray() : _employees.Keys.ToArray();
  453. }
  454. private bool HasData()
  455. {
  456. foreach (var cell in dataGrid.GetSelectedCells())
  457. {
  458. if (!cell.IsDataRowCell)
  459. continue;
  460. var propertyCollection = dataGrid.View.GetPropertyAccessProvider();
  461. var cellValue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName);
  462. if (cellValue is LeaveValue leaveValue && leaveValue.ID != Guid.Empty)
  463. return true;
  464. }
  465. return false;
  466. }
  467. private Guid[] GetLeaveIDs(bool standard)
  468. {
  469. List<Guid> result = new List<Guid>();
  470. foreach (var cell in dataGrid.GetSelectedCells())
  471. {
  472. if (cell.IsDataRowCell)
  473. {
  474. var propertyCollection = dataGrid.View.GetPropertyAccessProvider();
  475. var cellvalue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName) as LeaveValue;
  476. if (cellvalue != null && (cellvalue.ID != Guid.Empty) && (cellvalue.Standard == standard) && !result.Contains(cellvalue.ID))
  477. result.Add(cellvalue.ID);
  478. }
  479. }
  480. return result.ToArray();
  481. }
  482. private LeaveValue? GetData(GridCellInfo cell)
  483. {
  484. if (!cell.IsDataRowCell)
  485. return null;
  486. var propertyCollection = dataGrid.View.GetPropertyAccessProvider();
  487. var cellValue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName);
  488. return cellValue is LeaveValue leaveValue && leaveValue.ID != Guid.Empty ? leaveValue : null;
  489. }
  490. private bool HasData(GridCellInfo cell)
  491. {
  492. if (cell?.IsDataRowCell != true)
  493. return false;
  494. var propertyCollection = dataGrid.View.GetPropertyAccessProvider();
  495. var cellValue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName);
  496. return cellValue is LeaveValue leaveValue && leaveValue.ID != Guid.Empty;
  497. }
  498. private void CreateLeaveRequestClick(object sender, RoutedEventArgs e)
  499. {
  500. var activity = ((sender as MenuItem)!.Tag as Activity)!;
  501. GetSelectionData(out var from, out var to, out var ids);
  502. var leaves = new List<LeaveRequest>();
  503. foreach (var id in ids)
  504. {
  505. var leave = new LeaveRequest
  506. {
  507. From = from,
  508. To = to
  509. };
  510. leave.LeaveType.ID = activity.ID;
  511. leave.EmployeeLink.ID = id;
  512. leaves.Add(leave);
  513. }
  514. lg ??= new LeaveRequestGrid();
  515. if (lg.EditItems(leaves.ToArray()))
  516. {
  517. Progress.ShowModal("Checking Forms...", progress =>
  518. {
  519. List<LeaveRequestForm> updates = new List<LeaveRequestForm>();
  520. var table = new Client<ActivityForm>().Query(
  521. new Filter<ActivityForm>(x => x.Activity.ID).IsEqualTo(leaves.First().LeaveType.ID)
  522. .And(x => x.Form.AppliesTo)
  523. .IsEqualTo(typeof(LeaveRequest).EntityName().Split('.').Last())
  524. );
  525. foreach (var leave in leaves)
  526. {
  527. foreach (var row in table.Rows)
  528. {
  529. var activityform = row.ToObject<ActivityForm>();
  530. var leaveform = new LeaveRequestForm();
  531. leaveform.Parent.ID = leave.ID;
  532. leaveform.Form.ID = activityform.Form.ID;
  533. leaveform.Form.Synchronise(activityform.Form);
  534. var model =
  535. new DigitalFormDataModel<LeaveRequest, LeaveRequestLink, LeaveRequestForm>(leave, leaveform, []);
  536. leaveform.Description = model.EvaluateExpression(activityform.Form.DescriptionExpression) ?? activityform.Form.Description;
  537. updates.Add(leaveform);
  538. }
  539. }
  540. if (updates.Any())
  541. {
  542. progress.Report("Saving forms...");
  543. new Client<LeaveRequestForm>().Save(updates, "Created from Leave Calendar");
  544. }
  545. });
  546. Refresh();
  547. }
  548. }
  549. private void CreateStandardLeaveClick(object sender, RoutedEventArgs e)
  550. {
  551. GetSelectionData(out var from, out var to, out var ids);
  552. var leave = new StandardLeave
  553. {
  554. From = from,
  555. To = to
  556. };
  557. sg ??= new StandardLeaveGrid();
  558. if (sg.EditItems(new StandardLeave[] { leave }))
  559. Refresh();
  560. }
  561. private IEnumerable<LeaveRequest> GetSelectedLeaveRequests()
  562. {
  563. var ids = GetLeaveIDs(false);
  564. if (ids.Any())
  565. {
  566. lg ??= new LeaveRequests();
  567. var table = new Client<LeaveRequest>().Query(
  568. new Filter<LeaveRequest>(x => x.ID).InList(ids),
  569. lg.LoadEditorColumns()
  570. );
  571. var result = table.Rows.Select(x => x.ToObject<LeaveRequest>()).ToArray();
  572. return result;
  573. }
  574. return new LeaveRequest[] { };
  575. }
  576. private IEnumerable<StandardLeave> GetSelectedStandardLeaves()
  577. {
  578. var ids = GetLeaveIDs(true);
  579. if (ids.Any())
  580. {
  581. sg ??= new StandardLeaveGrid();
  582. var table = new Client<StandardLeave>().Query(
  583. new Filter<StandardLeave>(x => x.ID).InList(ids),
  584. sg.LoadEditorColumns()
  585. );
  586. var result = table.Rows.Select(x => x.ToObject<StandardLeave>()).ToArray();
  587. return result;
  588. }
  589. return new StandardLeave[] { };
  590. }
  591. private void EditLeaveClick(object sender, RoutedEventArgs e)
  592. {
  593. var requests = GetSelectedLeaveRequests().ToArray();
  594. if (requests.Any())
  595. {
  596. lg ??= new LeaveRequests();
  597. if (lg.EditItems(requests))
  598. Refresh();
  599. return;
  600. }
  601. var standards = GetSelectedStandardLeaves().ToArray();
  602. if (standards.Any())
  603. {
  604. sg ??= new StandardLeaveGrid();
  605. if (sg.EditItems(standards))
  606. Refresh();
  607. return;
  608. }
  609. MessageBox.Show("Nothing to edit!");
  610. }
  611. private void DeleteLeaveClick(object sender, RoutedEventArgs e)
  612. {
  613. var requests = GetSelectedLeaveRequests().ToArray();
  614. if (requests.Any())
  615. {
  616. if (MessageBox.Show("Delete Leave Request Information?", "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Warning) ==
  617. MessageBoxResult.Yes)
  618. {
  619. using (new WaitCursor())
  620. new Client<LeaveRequest>().Delete(requests, "Deleted from Calendar");
  621. Refresh();
  622. }
  623. return;
  624. }
  625. var standards = GetSelectedStandardLeaves().ToArray();
  626. if (standards.Any())
  627. {
  628. if (MessageBox.Show("Delete Standard Leave Information?", "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Warning) ==
  629. MessageBoxResult.Yes)
  630. {
  631. using (new WaitCursor())
  632. new Client<StandardLeave>().Delete(standards, "Deleted from Calendar");
  633. Refresh();
  634. }
  635. return;
  636. }
  637. MessageBox.Show("Nothing to delete!");
  638. }
  639. // private void DataGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
  640. // {
  641. // if (e.RightButton == MouseButtonState.Pressed)
  642. // {
  643. // var vc = dataGrid.GetVisualContainer();
  644. // var point = e.GetPosition(vc);
  645. // var rci = vc.PointToCellRowColumnIndex(point);
  646. //
  647. // if (rci.RowIndex == 0 || rci.ColumnIndex == 0)
  648. // return;
  649. //
  650. // var menu = new ContextMenu();
  651. // if (!HasData(dataGrid.CurrentCellInfo))
  652. // foreach (var row in _activities.Rows)
  653. // {
  654. // var createleave = new MenuItem
  655. // {
  656. // Header = row.Get<Activity, string>(c => c.Description),
  657. // Tag = row.ToObject<Activity>()
  658. // };
  659. // createleave.Click += CreateLeaveRequestClick;
  660. // menu.Items.Add(createleave);
  661. // }
  662. //
  663. // if (HasData())
  664. // {
  665. // var deleteleave = new MenuItem { Header = "Delete Leave" };
  666. // deleteleave.Click += DeleteLeaveClick;
  667. // menu.Items.Add(deleteleave);
  668. // }
  669. //
  670. // dataGrid.ContextMenu = menu;
  671. // menu.IsOpen = true;
  672. // }
  673. // }
  674. private void DataGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
  675. {
  676. var vc = dataGrid.GetVisualContainer();
  677. var p = Mouse.GetPosition(vc);
  678. var rci = vc.PointToCellRowColumnIndex(p);
  679. if (rci.RowIndex < 1 || rci.ColumnIndex < 1)
  680. {
  681. e.Handled = true;
  682. return;
  683. }
  684. dataGrid.ContextMenu.Items.Clear();
  685. var bCreate = !HasData(dataGrid.CurrentCellInfo);
  686. var bEdit = HasData();
  687. if (bCreate)
  688. {
  689. var createleaveheader = new MenuItem { Header = "Create Leave Request" };
  690. foreach (var row in _activities.Rows)
  691. {
  692. var createleave = new MenuItem
  693. {
  694. Header = row.Get<Activity, string>(c => c.Description),
  695. Tag = row.ToObject<Activity>()
  696. };
  697. createleave.Click += CreateLeaveRequestClick;
  698. createleaveheader.Items.Add(createleave);
  699. }
  700. dataGrid.ContextMenu.Items.Add(createleaveheader);
  701. dataGrid.ContextMenu.Items.Add(new Separator());
  702. var createstandardleave = new MenuItem { Header = "Create Standard Leave" };
  703. createstandardleave.Click += CreateStandardLeaveClick;
  704. dataGrid.ContextMenu.Items.Add(createstandardleave);
  705. }
  706. if (bEdit && bCreate)
  707. dataGrid.ContextMenu.Items.Add(new Separator());
  708. if (bEdit)
  709. {
  710. var editleave = new MenuItem { Header = "Edit Leave" };
  711. editleave.Click += EditLeaveClick;
  712. dataGrid.ContextMenu.Items.Add(editleave);
  713. dataGrid.ContextMenu.Items.Add(new Separator());
  714. var deleteleave = new MenuItem { Header = "Delete Leave" };
  715. deleteleave.Click += DeleteLeaveClick;
  716. dataGrid.ContextMenu.Items.Add(deleteleave);
  717. var cell = GetData(dataGrid.CurrentCellInfo); // not-null because bEdit.
  718. if (cell != null)
  719. {
  720. dataGrid.ContextMenu.Items.Add(new Separator());
  721. var formsItem = new MenuItem { Header = "Digital Forms" };
  722. DynamicGridUtils.PopulateFormMenu<LeaveRequestForm, LeaveRequest, LeaveRequestLink>(
  723. formsItem,
  724. cell.ID,
  725. () => new Client<LeaveRequest>().Load(new Filter<LeaveRequest>(x => x.ID).IsEqualTo(cell.ID)).First());
  726. dataGrid.ContextMenu.Items.Add(formsItem);
  727. }
  728. }
  729. }
  730. private void DateTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  731. {
  732. if (!bReady)
  733. return;
  734. Refresh();
  735. }
  736. private void SyncSelectedTeams(Guid teamid)
  737. {
  738. var bOldReady = bReady;
  739. bReady = false;
  740. if (teamid != CoreUtils.FullGuid)
  741. {
  742. SelectedTeams.SelectedItems.Clear();
  743. foreach (KeyValuePair<Guid, string> sel in SelectedTeams.Items)
  744. if (sel.Key == teamid)
  745. SelectedTeams.SelectedItems.Add(sel);
  746. }
  747. LoadEmployees(true);
  748. bReady = bOldReady;
  749. }
  750. private void GroupsSelectionChanged(object sender, SelectionChangedEventArgs e)
  751. {
  752. if (Teams.SelectedValue == null)
  753. return;
  754. var teamid = (Guid)Teams.SelectedValue;
  755. ChangeSelectedTeams(teamid);
  756. SyncSelectedTeams(teamid);
  757. }
  758. private void ChangeSelectedTeams(Guid teamid)
  759. {
  760. if (teamid == CoreUtils.FullGuid)
  761. {
  762. EmployeeGrid.RowDefinitions[1].Height = new GridLength(_settings.ListSize, GridUnitType.Pixel);
  763. EmployeeGrid.RowDefinitions[2].Height = new GridLength(1, GridUnitType.Auto);
  764. }
  765. else
  766. {
  767. var oldbReady = bReady;
  768. bReady = false;
  769. EmployeeGrid.RowDefinitions[1].Height = new GridLength(0, GridUnitType.Pixel);
  770. EmployeeGrid.RowDefinitions[2].Height = new GridLength(0, GridUnitType.Pixel);
  771. bReady = oldbReady;
  772. }
  773. //bHandled = false;
  774. }
  775. //bool bHandled = false;
  776. //private void SelectedTeams_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
  777. //{
  778. // if (!bReady)
  779. // return;
  780. // if (!bHandled)
  781. // LoadEmployees();
  782. // bHandled = !bHandled;
  783. //}
  784. private void SelectedTeams_ItemChecked(object sender, ItemCheckedEventArgs e)
  785. {
  786. if (!bReady)
  787. return;
  788. LoadEmployees(true);
  789. }
  790. private void LoadEmployees(bool selectall)
  791. {
  792. var emps = new Dictionary<Guid, string>();
  793. foreach (var pair in SelectedTeams.SelectedItems)
  794. if (pair != null)
  795. {
  796. var key = ((KeyValuePair<Guid, string>)pair).Key;
  797. foreach (var row in _employeeteams.Rows.Where(r =>
  798. r.Get<EmployeeTeam, Guid>(c => c.TeamLink.ID).Equals(key) || key.Equals(CoreUtils.FullGuid)))
  799. emps[row.Get<EmployeeTeam, Guid>(c => c.EmployeeLink.ID)] = row.Get<EmployeeTeam, string>(c => c.EmployeeLink.Name);
  800. }
  801. var bOldReady = bReady;
  802. bReady = false;
  803. SelectedEmployees.ItemsSource = emps;
  804. foreach (var item in SelectedEmployees.Items)
  805. {
  806. var pair = (KeyValuePair<Guid, string>)item;
  807. if (_settings.SelectedEmployees.Contains(pair.Key) || selectall)
  808. SelectedEmployees.SelectedItems.Add(item);
  809. }
  810. bReady = bOldReady;
  811. SaveSettings();
  812. Refresh();
  813. }
  814. private void EmployeesSelectionChanged(object sender, SelectionChangedEventArgs e)
  815. {
  816. if (!bReady || e.AddedItems.Count == 0 || e.AddedItems[0] == null)
  817. return;
  818. //ReloadColumns();
  819. SaveSettings();
  820. Refresh();
  821. }
  822. private void Export_Click(object sender, RoutedEventArgs e)
  823. {
  824. var options = new ExcelExportingOptions
  825. {
  826. ExcelVersion = ExcelVersion.Excel2013
  827. };
  828. var excelEngine = dataGrid.ExportToExcel(dataGrid.View, options);
  829. var workBook = excelEngine.Excel.Workbooks[0];
  830. var dlg = new SaveFileDialog
  831. {
  832. Filter = "Excel Files (*.xlsx)|*.xlsx",
  833. FileName = typeof(LeaveRequest).EntityName().Split('.').Last() + ".xlsx"
  834. };
  835. if (dlg.ShowDialog() == true)
  836. try
  837. {
  838. workBook.SaveAs(dlg.FileName);
  839. Process.Start(new ProcessStartInfo(dlg.FileName) { UseShellExecute = true });
  840. }
  841. catch (Exception e2)
  842. {
  843. MessageBox.Show("Error saving spreadsheet!\n\n" + e2.Message);
  844. }
  845. //workBook.SaveAs("Leave Requests.xlsx");
  846. }
  847. private void SelectedTeams_SizeChanged(object sender, SizeChangedEventArgs e)
  848. {
  849. SaveSettings();
  850. }
  851. private void OnlyShowLeaveBox_Checked(object sender, RoutedEventArgs e)
  852. {
  853. SaveSettings();
  854. Refresh();
  855. }
  856. }