LeaveCalendar.xaml.cs 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  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 PRS.Shared;
  22. using PRSDesktop.Grids;
  23. using Syncfusion.UI.Xaml.Grid;
  24. using Syncfusion.UI.Xaml.Grid.Converter;
  25. using Syncfusion.UI.Xaml.Grid.Helpers;
  26. using Syncfusion.Windows.Tools.Controls;
  27. using Syncfusion.XlsIO;
  28. using Activity = Comal.Classes.Activity;
  29. using Columns = InABox.Core.Columns;
  30. using SelectionChangedEventArgs = System.Windows.Controls.SelectionChangedEventArgs;
  31. namespace PRSDesktop
  32. {
  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. SelectedTeams.ItemsSource = _teams;
  194. foreach (KeyValuePair<Guid, string> pair in SelectedTeams.Items)
  195. if (_settings.SelectedGroups.Contains(pair.Key))
  196. SelectedTeams.SelectedItems.Add(pair);
  197. LoadEmployees(false);
  198. foreach (var row in _activities.Rows)
  199. {
  200. var id = row.Get<Activity, Guid>(c => c.ID);
  201. var color = row.Get<Activity, string>(c => c.Color);
  202. if (!string.IsNullOrWhiteSpace(color))
  203. _activityColors[id] = (Color)ColorConverter.ConvertFromString(color);
  204. var code = Codify(row.Get<Activity, string>(c => c.Description));
  205. _activityCodes[id] = Codify(code);
  206. }
  207. var rosterstarts = _employeeteams.ToDictionary<EmployeeTeam, Guid, DateTime>(x => x.EmployeeLink.ID, x => x.EmployeeLink.RosterStart);
  208. var startdates = _employeeteams.ToDictionary<EmployeeTeam, Guid, DateTime>(x => x.EmployeeLink.ID, x => x.EmployeeLink.StartDate);
  209. var finishdates = _employeeteams.ToDictionary<EmployeeTeam, Guid, DateTime>(x => x.EmployeeLink.ID, x => x.EmployeeLink.FinishDate);
  210. var rosters = _employeeteams.ToDictionary<EmployeeTeam, Guid, String>(x => x.EmployeeLink.ID, x => x.EmployeeLink.Roster);
  211. foreach (var empid in startdates.Keys)
  212. {
  213. var startdate = startdates[empid];
  214. var finishdate = finishdates[empid];
  215. var roster = !String.IsNullOrWhiteSpace(rosters[empid])
  216. ? Serialization.Deserialize<List<EmployeeRosterItem>>(rosters[empid]).ToArray()
  217. : null;
  218. var rosterstart = rosterstarts[empid];
  219. _rosters.Add(new Tuple<Guid, DateTime, DateTime, EmployeeRosterItem[], DateTime>(empid, startdate, finishdate, roster, rosterstart));
  220. }
  221. bReady = true;
  222. }
  223. private static string Codify(string name)
  224. {
  225. if (string.IsNullOrWhiteSpace(name))
  226. return "??";
  227. var result = "";
  228. var comps = name.ToUpper().Split(' ');
  229. foreach (var comp in comps)
  230. if (comp.Any())
  231. result += comp.First();
  232. return string.IsNullOrWhiteSpace(result) ? "??" : result;
  233. }
  234. [MemberNotNull(nameof(_settings))]
  235. private void LoadSettings()
  236. {
  237. _settings = new UserConfiguration<LeaveSettings>().Load();
  238. if (!_settings.SelectedGroups.Any() && _settings.GroupID != Guid.Empty)
  239. _settings.SelectedGroups.Add(_settings.GroupID);
  240. if (_settings.ListSize == 0.0F)
  241. _settings.ListSize = 200.0F;
  242. }
  243. private void SaveSettings()
  244. {
  245. if (!bReady)
  246. return;
  247. try
  248. {
  249. _settings.GroupID = Teams.SelectedValue != null ? (Guid)Teams.SelectedValue : Guid.Empty;
  250. _settings.SelectedGroups.Clear();
  251. foreach (var sel in SelectedTeams.SelectedItems)
  252. {
  253. var grp = (KeyValuePair<Guid, string>)sel;
  254. _settings.SelectedGroups.Add(grp.Key);
  255. }
  256. _settings.SelectedEmployees.Clear();
  257. foreach (var sel in SelectedEmployees.SelectedItems)
  258. {
  259. var grp = (KeyValuePair<Guid, string>)sel;
  260. _settings.SelectedEmployees.Add(grp.Key);
  261. }
  262. if (EmployeeGrid.RowDefinitions[1].ActualHeight != 0.0F)
  263. _settings.ListSize = EmployeeGrid.RowDefinitions[1].ActualHeight;
  264. }
  265. catch (Exception e)
  266. {
  267. Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
  268. }
  269. Task.Run(() => { new UserConfiguration<LeaveSettings>().Save(_settings); });
  270. }
  271. public void Refresh()
  272. {
  273. if (!bReady)
  274. return;
  275. using (new WaitCursor())
  276. {
  277. _employees.Clear();
  278. var crosstab = new List<LeaveValue>();
  279. MultiQuery query = new MultiQuery();
  280. var empfilter = new Filter<LeaveRequest>(x => x.EmployeeLink.ID).IsEqualTo(CoreUtils.FullGuid);
  281. foreach (var sel in SelectedEmployees.Items)
  282. {
  283. var emp = (KeyValuePair<Guid, string>)sel;
  284. if (SelectedEmployees.SelectedItems.Contains(emp))
  285. {
  286. empfilter = empfilter.Or(x => x.EmployeeLink.ID).IsEqualTo(emp.Key);
  287. _employees[emp.Key] = emp.Value;
  288. }
  289. }
  290. var start = StartDate.DateTime ?? DateTime.Today;
  291. var end = EndDate.DateTime ?? DateTime.Today.AddYears(1);
  292. var leavefilter = new Filter<LeaveRequest>(x => x.To).IsGreaterThanOrEqualTo(start)
  293. .And(x => x.From).IsLessThanOrEqualTo(end)
  294. .And(x => x.Status).IsNotEqualTo(LeaveRequestStatus.Rejected);
  295. leavefilter.Ands.Add(empfilter);
  296. query.Add<LeaveRequest>(
  297. leavefilter,
  298. Columns.None<LeaveRequest>().Add(x => x.ID)
  299. .Add(x => x.EmployeeLink.ID)
  300. .Add(x => x.From)
  301. .Add(x=>x.FromTime)
  302. .Add(x => x.To)
  303. .Add(x=>x.ToTime)
  304. .Add(x => x.LeaveType.ID)
  305. .Add(x => x.LeaveType.Description)
  306. .Add(x => x.Status)
  307. );
  308. query.Add<StandardLeave>(
  309. new Filter<StandardLeave>(x => x.To).IsGreaterThanOrEqualTo(start).And(x => x.From).IsLessThanOrEqualTo(end),
  310. Columns.None<StandardLeave>().Add(x => x.ID)
  311. .Add(x => x.From)
  312. .Add(x=>x.FromTime)
  313. .Add(x => x.To)
  314. .Add(x=>x.ToTime)
  315. .Add(x => x.LeaveType.ID)
  316. );
  317. query.Query();
  318. var leaverequests = query.Get<LeaveRequest>();
  319. var standardleaves = query.Get<StandardLeave>();
  320. foreach (var standardrow in standardleaves.Rows)
  321. {
  322. var id = standardrow.Get<StandardLeave, Guid>(x => x.ID);
  323. var actid = standardrow.Get<StandardLeave, Guid>(x => x.LeaveType.ID);
  324. var from = standardrow.Get<StandardLeave, DateTime>(x => x.From);
  325. from = from < start ? start : from;
  326. var to = standardrow.Get<StandardLeave, DateTime>(x => x.To);
  327. to = to > end ? end : to;
  328. for (var date = from; date <= to; date = date.AddDays(1))
  329. foreach (var empid in _employees.Keys)
  330. crosstab.Add(new LeaveValue(id, empid, date, actid, LeaveRequestStatus.Approved, true));
  331. }
  332. foreach (var leaverow in leaverequests.Rows)
  333. {
  334. var id = leaverow.Get<LeaveRequest, Guid>(x => x.ID);
  335. var empid = leaverow.Get<LeaveRequest, Guid>(x => x.EmployeeLink.ID);
  336. var actid = leaverow.Get<LeaveRequest, Guid>(x => x.LeaveType.ID);
  337. var status = leaverow.Get<LeaveRequest, LeaveRequestStatus>(x => x.Status);
  338. var from = leaverow.Get<LeaveRequest, DateTime>(x => x.From);
  339. from = from < start ? start : from;
  340. var to = leaverow.Get<LeaveRequest, DateTime>(x => x.To);
  341. to = to > end ? end : to;
  342. var totime = leaverow.Get<LeaveRequest, TimeSpan>(x => x.ToTime);
  343. for (var date = from; date < to.Add(totime); date = date.AddDays(1))
  344. crosstab.Add(new LeaveValue(id, empid, date, actid, status, false));
  345. }
  346. var data = new DataTable();
  347. data.Columns.Add("Date", typeof(DateTime));
  348. foreach (var employee in _employees.Keys)
  349. data.Columns.Add(employee.ToString(), typeof(object));
  350. for (var date = start; date <= end; date = date.AddDays(1))
  351. {
  352. var values = new List<object> { date };
  353. foreach (var employee in _employees.Keys)
  354. {
  355. LeaveValue value = null;
  356. var roster = _rosters.FirstOrDefault(x => x.Item1 == employee);
  357. if (roster != null)
  358. {
  359. var curroster = RosterUtils.GetRoster(roster.Item4, roster.Item5, date);
  360. if (curroster?.Enabled == true)
  361. {
  362. value = crosstab.FirstOrDefault(x => x.Employee.Equals(employee) && x.Date.Equals(date) && x.Standard);
  363. if (value == null)
  364. value = crosstab.FirstOrDefault(x => x.Employee.Equals(employee) && x.Date.Equals(date) && !x.Standard);
  365. }
  366. }
  367. values.Add(value ?? new LeaveValue(Guid.Empty, employee, date, Guid.Empty, LeaveRequestStatus.InProgress, false));
  368. }
  369. data.Rows.Add(values.ToArray());
  370. }
  371. dataGrid.ItemsSource = data;
  372. }
  373. }
  374. private void DataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e)
  375. {
  376. e.Column.TextAlignment = TextAlignment.Center;
  377. e.Column.HorizontalHeaderContentAlignment = HorizontalAlignment.Center;
  378. e.Column.ColumnSizer = GridLengthUnitType.None;
  379. var value = (e.Column.ValueBinding as Binding)!;
  380. if (value.Path.Path.Equals("Date"))
  381. {
  382. e.Column.Width = 100;
  383. e.Column.HeaderStyle = Resources["DateHeaderStyle"] as Style;
  384. e.Column.AllowFocus = false;
  385. }
  386. else
  387. {
  388. var style = new Style(typeof(GridCell));
  389. style.Setters.Add(new Setter(BackgroundProperty,
  390. new Binding(value.Path.Path)
  391. {
  392. Converter = new LeaveBackgroundConverter
  393. {
  394. Colors = _activityColors,
  395. Rosters = _rosters
  396. }
  397. }));
  398. style.Setters.Add(new Setter(ForegroundProperty, new Binding(value.Path.Path) { Converter = new LeaveForegroundConverter() }));
  399. style.Setters.Add(new Setter(FontStyleProperty, new Binding(value.Path.Path) { Converter = new LeaveFontStyleConverter() }));
  400. style.Setters.Add(new Setter(FontWeightProperty, new Binding(value.Path.Path) { Converter = new LeaveFontWeightConverter() }));
  401. e.Column.CellStyle = style;
  402. e.Column.Width = 30;
  403. e.Column.HeaderStyle = Resources["ContentHeaderStyle"] as Style;
  404. e.Column.HeaderText = _employees[Guid.Parse(value.Path.Path)];
  405. e.Column.DisplayBinding = new Binding
  406. { Path = new PropertyPath(e.Column.MappingName), Converter = new LeaveContentConverter { Abbreviations = _activityCodes } };
  407. //e.Column.ValueBinding = new Binding() { Path = new PropertyPath(e.Column.MappingName), Converter = new LeaveContentConverter() };
  408. //e.Column.UseBindingValue = true;
  409. e.Column.AllowFocus = true;
  410. }
  411. }
  412. //private void DataGrid_FilterItemsPopulating(object sender, GridFilterItemsPopulatingEventArgs e)
  413. //{
  414. // e.FilterControl.FilterMode = FilterMode.AdvancedFilter;
  415. //}
  416. private void GetSelectionData(out DateTime from, out DateTime to, out Guid[] ids)
  417. {
  418. var emps = new List<Guid>();
  419. from = DateTime.MaxValue;
  420. to = DateTime.MinValue;
  421. foreach (var cell in dataGrid.GetSelectedCells())
  422. {
  423. var binding = (cell.Column.ValueBinding as Binding)!;
  424. if (Guid.TryParse(binding.Path.Path, out var emp))
  425. if (!emps.Contains(emp))
  426. emps.Add(emp);
  427. var row = (cell.RowData as DataRowView)!;
  428. var date = (DateTime)row.Row.ItemArray.First()!;
  429. if (date < from)
  430. from = date;
  431. if (date > to)
  432. to = date;
  433. }
  434. ids = emps.Any() ? emps.ToArray() : _employees.Keys.ToArray();
  435. }
  436. private bool HasData()
  437. {
  438. foreach (var cell in dataGrid.GetSelectedCells())
  439. {
  440. if (!cell.IsDataRowCell)
  441. continue;
  442. var propertyCollection = dataGrid.View.GetPropertyAccessProvider();
  443. var cellValue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName);
  444. if (cellValue is LeaveValue leaveValue && leaveValue.ID != Guid.Empty)
  445. return true;
  446. }
  447. return false;
  448. }
  449. private Guid[] GetLeaveIDs(bool standard)
  450. {
  451. List<Guid> result = new List<Guid>();
  452. foreach (var cell in dataGrid.GetSelectedCells())
  453. {
  454. if (cell.IsDataRowCell)
  455. {
  456. var propertyCollection = dataGrid.View.GetPropertyAccessProvider();
  457. var cellvalue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName) as LeaveValue;
  458. if (cellvalue != null && (cellvalue.ID != Guid.Empty) && (cellvalue.Standard == standard) && !result.Contains(cellvalue.ID))
  459. result.Add(cellvalue.ID);
  460. }
  461. }
  462. return result.ToArray();
  463. }
  464. private LeaveValue? GetData(GridCellInfo cell)
  465. {
  466. if (!cell.IsDataRowCell)
  467. return null;
  468. var propertyCollection = dataGrid.View.GetPropertyAccessProvider();
  469. var cellValue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName);
  470. return cellValue is LeaveValue leaveValue && leaveValue.ID != Guid.Empty ? leaveValue : null;
  471. }
  472. private bool HasData(GridCellInfo cell)
  473. {
  474. if (cell?.IsDataRowCell != true)
  475. return false;
  476. var propertyCollection = dataGrid.View.GetPropertyAccessProvider();
  477. var cellValue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName);
  478. return cellValue is LeaveValue leaveValue && leaveValue.ID != Guid.Empty;
  479. }
  480. private void CreateLeaveRequestClick(object sender, RoutedEventArgs e)
  481. {
  482. var activity = ((sender as MenuItem)!.Tag as Activity)!;
  483. GetSelectionData(out var from, out var to, out var ids);
  484. var leaves = new List<LeaveRequest>();
  485. foreach (var id in ids)
  486. {
  487. var leave = new LeaveRequest
  488. {
  489. From = from,
  490. To = to
  491. };
  492. leave.LeaveType.ID = activity.ID;
  493. leave.EmployeeLink.ID = id;
  494. leaves.Add(leave);
  495. }
  496. lg ??= new LeaveRequestGrid();
  497. if (lg.EditItems(leaves.ToArray()))
  498. {
  499. Progress.ShowModal("Checking Forms...", progress =>
  500. {
  501. List<LeaveRequestForm> updates = new List<LeaveRequestForm>();
  502. var table = new Client<ActivityForm>().Query(
  503. new Filter<ActivityForm>(x => x.Activity.ID).IsEqualTo(leaves.First().LeaveType.ID)
  504. .And(x => x.Form.AppliesTo)
  505. .IsEqualTo(typeof(LeaveRequest).EntityName().Split('.').Last())
  506. );
  507. foreach (var leave in leaves)
  508. {
  509. foreach (var row in table.Rows)
  510. {
  511. var activityform = row.ToObject<ActivityForm>();
  512. var leaveform = new LeaveRequestForm();
  513. leaveform.Parent.ID = leave.ID;
  514. leaveform.Form.ID = activityform.Form.ID;
  515. leaveform.Form.Synchronise(activityform.Form);
  516. var model =
  517. new DigitalFormDataModel<LeaveRequest, LeaveRequestLink, LeaveRequestForm>(leave, leaveform, []);
  518. leaveform.Description = model.EvaluateExpression(activityform.Form.DescriptionExpression) ?? activityform.Form.Description;
  519. updates.Add(leaveform);
  520. }
  521. }
  522. if (updates.Any())
  523. {
  524. progress.Report("Saving forms...");
  525. new Client<LeaveRequestForm>().Save(updates, "Created from Leave Calendar");
  526. }
  527. });
  528. Refresh();
  529. }
  530. }
  531. private void CreateStandardLeaveClick(object sender, RoutedEventArgs e)
  532. {
  533. GetSelectionData(out var from, out var to, out var ids);
  534. var leave = new StandardLeave
  535. {
  536. From = from,
  537. To = to
  538. };
  539. sg ??= new StandardLeaveGrid();
  540. if (sg.EditItems(new StandardLeave[] { leave }))
  541. Refresh();
  542. }
  543. private IEnumerable<LeaveRequest> GetSelectedLeaveRequests()
  544. {
  545. var ids = GetLeaveIDs(false);
  546. if (ids.Any())
  547. {
  548. lg ??= new LeaveRequests();
  549. var table = new Client<LeaveRequest>().Query(
  550. new Filter<LeaveRequest>(x => x.ID).InList(ids),
  551. lg.LoadEditorColumns()
  552. );
  553. var result = table.Rows.Select(x => x.ToObject<LeaveRequest>()).ToArray();
  554. return result;
  555. }
  556. return new LeaveRequest[] { };
  557. }
  558. private IEnumerable<StandardLeave> GetSelectedStandardLeaves()
  559. {
  560. var ids = GetLeaveIDs(true);
  561. if (ids.Any())
  562. {
  563. sg ??= new StandardLeaveGrid();
  564. var table = new Client<StandardLeave>().Query(
  565. new Filter<StandardLeave>(x => x.ID).InList(ids),
  566. sg.LoadEditorColumns()
  567. );
  568. var result = table.Rows.Select(x => x.ToObject<StandardLeave>()).ToArray();
  569. return result;
  570. }
  571. return new StandardLeave[] { };
  572. }
  573. private void EditLeaveClick(object sender, RoutedEventArgs e)
  574. {
  575. var requests = GetSelectedLeaveRequests().ToArray();
  576. if (requests.Any())
  577. {
  578. lg ??= new LeaveRequests();
  579. if (lg.EditItems(requests))
  580. Refresh();
  581. return;
  582. }
  583. var standards = GetSelectedStandardLeaves().ToArray();
  584. if (standards.Any())
  585. {
  586. sg ??= new StandardLeaveGrid();
  587. if (sg.EditItems(standards))
  588. Refresh();
  589. return;
  590. }
  591. MessageBox.Show("Nothing to edit!");
  592. }
  593. private void DeleteLeaveClick(object sender, RoutedEventArgs e)
  594. {
  595. var requests = GetSelectedLeaveRequests().ToArray();
  596. if (requests.Any())
  597. {
  598. if (MessageBox.Show("Delete Leave Request Information?", "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Warning) ==
  599. MessageBoxResult.Yes)
  600. {
  601. using (new WaitCursor())
  602. new Client<LeaveRequest>().Delete(requests, "Deleted from Calendar");
  603. Refresh();
  604. }
  605. return;
  606. }
  607. var standards = GetSelectedStandardLeaves().ToArray();
  608. if (standards.Any())
  609. {
  610. if (MessageBox.Show("Delete Standard Leave Information?", "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Warning) ==
  611. MessageBoxResult.Yes)
  612. {
  613. using (new WaitCursor())
  614. new Client<StandardLeave>().Delete(standards, "Deleted from Calendar");
  615. Refresh();
  616. }
  617. return;
  618. }
  619. MessageBox.Show("Nothing to delete!");
  620. }
  621. // private void DataGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
  622. // {
  623. // if (e.RightButton == MouseButtonState.Pressed)
  624. // {
  625. // var vc = dataGrid.GetVisualContainer();
  626. // var point = e.GetPosition(vc);
  627. // var rci = vc.PointToCellRowColumnIndex(point);
  628. //
  629. // if (rci.RowIndex == 0 || rci.ColumnIndex == 0)
  630. // return;
  631. //
  632. // var menu = new ContextMenu();
  633. // if (!HasData(dataGrid.CurrentCellInfo))
  634. // foreach (var row in _activities.Rows)
  635. // {
  636. // var createleave = new MenuItem
  637. // {
  638. // Header = row.Get<Activity, string>(c => c.Description),
  639. // Tag = row.ToObject<Activity>()
  640. // };
  641. // createleave.Click += CreateLeaveRequestClick;
  642. // menu.Items.Add(createleave);
  643. // }
  644. //
  645. // if (HasData())
  646. // {
  647. // var deleteleave = new MenuItem { Header = "Delete Leave" };
  648. // deleteleave.Click += DeleteLeaveClick;
  649. // menu.Items.Add(deleteleave);
  650. // }
  651. //
  652. // dataGrid.ContextMenu = menu;
  653. // menu.IsOpen = true;
  654. // }
  655. // }
  656. private void DataGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
  657. {
  658. var vc = dataGrid.GetVisualContainer();
  659. var p = Mouse.GetPosition(vc);
  660. var rci = vc.PointToCellRowColumnIndex(p);
  661. if (rci.RowIndex < 1 || rci.ColumnIndex < 1)
  662. {
  663. e.Handled = true;
  664. return;
  665. }
  666. dataGrid.ContextMenu.Items.Clear();
  667. var bCreate = !HasData(dataGrid.CurrentCellInfo);
  668. var bEdit = HasData();
  669. if (bCreate)
  670. {
  671. var createleaveheader = new MenuItem { Header = "Create Leave Request" };
  672. foreach (var row in _activities.Rows)
  673. {
  674. var createleave = new MenuItem
  675. {
  676. Header = row.Get<Activity, string>(c => c.Description),
  677. Tag = row.ToObject<Activity>()
  678. };
  679. createleave.Click += CreateLeaveRequestClick;
  680. createleaveheader.Items.Add(createleave);
  681. }
  682. dataGrid.ContextMenu.Items.Add(createleaveheader);
  683. dataGrid.ContextMenu.Items.Add(new Separator());
  684. var createstandardleave = new MenuItem { Header = "Create Standard Leave" };
  685. createstandardleave.Click += CreateStandardLeaveClick;
  686. dataGrid.ContextMenu.Items.Add(createstandardleave);
  687. }
  688. if (bEdit && bCreate)
  689. dataGrid.ContextMenu.Items.Add(new Separator());
  690. if (bEdit)
  691. {
  692. var editleave = new MenuItem { Header = "Edit Leave" };
  693. editleave.Click += EditLeaveClick;
  694. dataGrid.ContextMenu.Items.Add(editleave);
  695. dataGrid.ContextMenu.Items.Add(new Separator());
  696. var deleteleave = new MenuItem { Header = "Delete Leave" };
  697. deleteleave.Click += DeleteLeaveClick;
  698. dataGrid.ContextMenu.Items.Add(deleteleave);
  699. var cell = GetData(dataGrid.CurrentCellInfo); // not-null because bEdit.
  700. if (cell != null)
  701. {
  702. dataGrid.ContextMenu.Items.Add(new Separator());
  703. var formsItem = new MenuItem { Header = "Digital Forms" };
  704. DynamicGridUtils.PopulateFormMenu<LeaveRequestForm, LeaveRequest, LeaveRequestLink>(
  705. formsItem,
  706. cell.ID,
  707. () => new Client<LeaveRequest>().Load(new Filter<LeaveRequest>(x => x.ID).IsEqualTo(cell.ID)).First());
  708. dataGrid.ContextMenu.Items.Add(formsItem);
  709. }
  710. }
  711. }
  712. private void DateTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  713. {
  714. if (!bReady)
  715. return;
  716. Refresh();
  717. }
  718. private void SyncSelectedTeams(Guid teamid)
  719. {
  720. var bOldReady = bReady;
  721. bReady = false;
  722. if (teamid != CoreUtils.FullGuid)
  723. {
  724. SelectedTeams.SelectedItems.Clear();
  725. foreach (KeyValuePair<Guid, string> sel in SelectedTeams.Items)
  726. if (sel.Key == teamid)
  727. SelectedTeams.SelectedItems.Add(sel);
  728. }
  729. LoadEmployees(true);
  730. bReady = bOldReady;
  731. }
  732. private void GroupsSelectionChanged(object sender, SelectionChangedEventArgs e)
  733. {
  734. if (Teams.SelectedValue == null)
  735. return;
  736. var teamid = (Guid)Teams.SelectedValue;
  737. ChangeSelectedTeams(teamid);
  738. SyncSelectedTeams(teamid);
  739. }
  740. private void ChangeSelectedTeams(Guid teamid)
  741. {
  742. if (teamid == CoreUtils.FullGuid)
  743. {
  744. EmployeeGrid.RowDefinitions[1].Height = new GridLength(_settings.ListSize, GridUnitType.Pixel);
  745. EmployeeGrid.RowDefinitions[2].Height = new GridLength(1, GridUnitType.Auto);
  746. }
  747. else
  748. {
  749. var oldbReady = bReady;
  750. bReady = false;
  751. EmployeeGrid.RowDefinitions[1].Height = new GridLength(0, GridUnitType.Pixel);
  752. EmployeeGrid.RowDefinitions[2].Height = new GridLength(0, GridUnitType.Pixel);
  753. bReady = oldbReady;
  754. }
  755. //bHandled = false;
  756. }
  757. //bool bHandled = false;
  758. //private void SelectedTeams_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
  759. //{
  760. // if (!bReady)
  761. // return;
  762. // if (!bHandled)
  763. // LoadEmployees();
  764. // bHandled = !bHandled;
  765. //}
  766. private void SelectedTeams_ItemChecked(object sender, ItemCheckedEventArgs e)
  767. {
  768. if (!bReady)
  769. return;
  770. LoadEmployees(true);
  771. }
  772. private void LoadEmployees(bool selectall)
  773. {
  774. var emps = new Dictionary<Guid, string>();
  775. foreach (var pair in SelectedTeams.SelectedItems)
  776. if (pair != null)
  777. {
  778. var key = ((KeyValuePair<Guid, string>)pair).Key;
  779. foreach (var row in _employeeteams.Rows.Where(r =>
  780. r.Get<EmployeeTeam, Guid>(c => c.TeamLink.ID).Equals(key) || key.Equals(CoreUtils.FullGuid)))
  781. emps[row.Get<EmployeeTeam, Guid>(c => c.EmployeeLink.ID)] = row.Get<EmployeeTeam, string>(c => c.EmployeeLink.Name);
  782. }
  783. var bOldReady = bReady;
  784. bReady = false;
  785. SelectedEmployees.ItemsSource = emps;
  786. foreach (var item in SelectedEmployees.Items)
  787. {
  788. var pair = (KeyValuePair<Guid, string>)item;
  789. if (_settings.SelectedEmployees.Contains(pair.Key) || selectall)
  790. SelectedEmployees.SelectedItems.Add(item);
  791. }
  792. bReady = bOldReady;
  793. SaveSettings();
  794. Refresh();
  795. }
  796. private void EmployeesSelectionChanged(object sender, SelectionChangedEventArgs e)
  797. {
  798. if (!bReady || e.AddedItems.Count == 0 || e.AddedItems[0] == null)
  799. return;
  800. //ReloadColumns();
  801. SaveSettings();
  802. Refresh();
  803. }
  804. private void Export_Click(object sender, RoutedEventArgs e)
  805. {
  806. var options = new ExcelExportingOptions
  807. {
  808. ExcelVersion = ExcelVersion.Excel2013
  809. };
  810. var excelEngine = dataGrid.ExportToExcel(dataGrid.View, options);
  811. var workBook = excelEngine.Excel.Workbooks[0];
  812. var dlg = new SaveFileDialog
  813. {
  814. Filter = "Excel Files (*.xlsx)|*.xlsx",
  815. FileName = typeof(LeaveRequest).EntityName().Split('.').Last() + ".xlsx"
  816. };
  817. if (dlg.ShowDialog() == true)
  818. try
  819. {
  820. workBook.SaveAs(dlg.FileName);
  821. Process.Start(new ProcessStartInfo(dlg.FileName) { UseShellExecute = true });
  822. }
  823. catch (Exception e2)
  824. {
  825. MessageBox.Show("Error saving spreadsheet!\n\n" + e2.Message);
  826. }
  827. //workBook.SaveAs("Leave Requests.xlsx");
  828. }
  829. private void SelectedTeams_SizeChanged(object sender, SizeChangedEventArgs e)
  830. {
  831. SaveSettings();
  832. }
  833. }
  834. }