using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using Comal.Classes; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF; using Microsoft.Win32; using Syncfusion.UI.Xaml.Grid; using Syncfusion.UI.Xaml.Grid.Converter; using Syncfusion.UI.Xaml.Grid.Helpers; using Syncfusion.Windows.Tools.Controls; using Syncfusion.XlsIO; using Activity = Comal.Classes.Activity; using SelectionChangedEventArgs = System.Windows.Controls.SelectionChangedEventArgs; namespace PRSDesktop { public class LeaveValue { public LeaveValue(Guid id, Guid employee, DateTime date, Guid activity, LeaveRequestStatus status) { ID = id; Employee = employee; Date = date; Activity = activity; Status = status; } public Guid ID { get; set; } public Guid Employee { get; set; } public DateTime Date { get; set; } public Guid Activity { get; set; } public LeaveRequestStatus Status { get; set; } } public class LeaveBackgroundConverter : IValueConverter { public Dictionary Colors { get; set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var val = value as LeaveValue; if (val != null) { if (val.ID == Guid.Empty) { if (val.Date.DayOfWeek == DayOfWeek.Saturday || val.Date.DayOfWeek == DayOfWeek.Sunday) return new SolidColorBrush(System.Windows.Media.Colors.LightGray); } else { if (val.Status != LeaveRequestStatus.Approved) return new SolidColorBrush(System.Windows.Media.Colors.DimGray); if (Colors != null) if (Colors.ContainsKey(val.Activity)) return new SolidColorBrush(Colors[val.Activity]); } } return DependencyProperty.UnsetValue; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } public class LeaveForegroundConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var val = value as LeaveValue; if (val != null && val.ID != Guid.Empty && val.Status != LeaveRequestStatus.Approved) return new SolidColorBrush(Colors.Gray); return DependencyProperty.UnsetValue; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } public class LeaveFontStyleConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var val = value as LeaveValue; if (val != null && val.ID != Guid.Empty && val.Status != LeaveRequestStatus.Approved) return FontStyles.Italic; return DependencyProperty.UnsetValue; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } public class LeaveFontWeightConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return FontWeights.Bold; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } public class LeaveContentConverter : IValueConverter { public Dictionary Abbreviations { get; set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var val = value as LeaveValue; return Abbreviations.ContainsKey(val.Activity) ? Abbreviations[val.Activity] : DependencyProperty.UnsetValue; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } /// /// Interaction logic for LeaveCalendar.xaml /// public partial class LeaveCalendar : UserControl { private readonly CoreTable _activities; private readonly Dictionary _activityCodes = new(); private readonly Dictionary _activityColors = new(); private readonly Dictionary _employees = new(); private LeaveSettings _settings; private readonly Dictionary _teams = new(); private bool bReady; private LeaveContentConverter converter = new(); private DataTable data; private LeaveRequestGrid lg; public LeaveCalendar() { InitializeComponent(); //dataGrid.ScrollMode = ScrollMode.Async; LoadSettings(); StartDate.DateTime = DateTime.Today; var setups = ClientFactory.MultiQuery( new QueryDef( null, null, new SortOrder(x => x.TeamLink.Code).ThenBy(x => x.EmployeeLink.Name) ), new QueryDef( new Filter(x => x.IsLeave).IsEqualTo(true), null, null ) ); _employeeTeams = setups.First(); _activities = setups.Last(); _teams = _employeeTeams.ToDictionary(c => c.TeamLink.ID, c => c.TeamLink.Name); if (_teams.ContainsKey(Guid.Empty)) _teams.Remove(Guid.Empty); var teams = _employeeTeams.ToDictionary(c => c.TeamLink.ID, c => c.TeamLink.Name); teams[CoreUtils.FullGuid] = "Multiple Teams"; Teams.ItemsSource = teams; Teams.SelectedValue = _settings.GroupID; ChangeSelectedTeams(_settings.GroupID); SelectedTeams.ItemsSource = _teams; foreach (KeyValuePair pair in SelectedTeams.Items) if (_settings.SelectedGroups.Contains(pair.Key)) SelectedTeams.SelectedItems.Add(pair); LoadEmployees(false); //Guid groupid = _teams.ContainsKey(_settings.GroupID) ? _settings.GroupID : CoreUtils.FullGuid; //{ // Teams.SelectedValue = _settings.GroupID; // Dictionary emps = new Dictionary(); // foreach (var row in _employeeTeams.Rows.Where(r => r.Get(c=>c.TeamLink.ID).Equals(_settings.GroupID) || _settings.GroupID.Equals(CoreUtils.FullGuid))) // emps[row.Get(c=>c.EmployeeLink.ID)] = row.Get(c=>c.EmployeeLink.Name); // SelectedEmployees.ItemsSource = emps; // foreach (var item in SelectedEmployees.Items) // { // KeyValuePair emp = (KeyValuePair)item; // if (_settings.SelectedEmployees.Contains(emp.Key)) // SelectedEmployees.SelectedItems.Add(item); // } //} //activities = new Client().Load(new Filter(x=>x.IsLeave).IsEqualTo(true)); foreach (var row in _activities.Rows) { var id = row.Get(c => c.ID); var color = row.Get(c => c.Color); if (!string.IsNullOrWhiteSpace(color)) _activityColors[id] = (Color)ColorConverter.ConvertFromString(color); var code = Codify(row.Get(c => c.Description)); _activityCodes[id] = Codify(code); } bReady = true; } private CoreTable _employeeTeams { get; } private string Codify(string name) { if (string.IsNullOrWhiteSpace(name)) return "??"; var result = ""; var comps = name.ToUpper().Split(' '); foreach (var comp in comps) if (comp.Any()) result += comp.First(); return string.IsNullOrWhiteSpace(result) ? "??" : result; } private void LoadSettings() { _settings = new UserConfiguration().Load(); if (!_settings.SelectedGroups.Any() && _settings.GroupID != Guid.Empty) _settings.SelectedGroups.Add(_settings.GroupID); if (_settings.ListSize == 0.0F) _settings.ListSize = 200.0F; } private void SaveSettings() { if (!bReady) return; try { _settings.GroupID = Teams.SelectedValue != null ? (Guid)Teams.SelectedValue : Guid.Empty; _settings.SelectedGroups.Clear(); foreach (var sel in SelectedTeams.SelectedItems) { var grp = (KeyValuePair)sel; _settings.SelectedGroups.Add(grp.Key); } _settings.SelectedEmployees.Clear(); foreach (var sel in SelectedEmployees.SelectedItems) { var grp = (KeyValuePair)sel; _settings.SelectedEmployees.Add(grp.Key); } if (EmployeeGrid.RowDefinitions[1].ActualHeight != 0.0F) _settings.ListSize = EmployeeGrid.RowDefinitions[1].ActualHeight; } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } Task.Run(() => { new UserConfiguration().Save(_settings); }); } public void Refresh() { using (new WaitCursor()) { _employees.Clear(); var crosstab = new List(); var empfilter = new Filter(x => x.EmployeeLink.ID).IsEqualTo(CoreUtils.FullGuid); foreach (var sel in SelectedEmployees.Items) { var emp = (KeyValuePair)sel; if (SelectedEmployees.SelectedItems.Contains(emp)) { empfilter = empfilter.Or(x => x.EmployeeLink.ID).IsEqualTo(emp.Key); _employees[emp.Key] = emp.Value; } } //Filter filter = new Filter(x => x.From).IsLessThanOrEqualTo(EndDate.DateTime.Value).And(x => x.To).IsGreaterThanOrEqualTo(StartDate.DateTime.Value); var filter = new Filter(x => x.To).IsGreaterThanOrEqualTo(StartDate.DateTime.Value) .And(x => x.Status).IsNotEqualTo(LeaveRequestStatus.Rejected); filter.Ands.Add(empfilter); var leave = new Client().Query( filter, new Columns(x => x.ID) .Add(x => x.EmployeeLink.ID) .Add(x => x.From) .Add(x => x.To) .Add(x => x.LeaveType.ID) .Add(x => x.LeaveType.Description) .Add(x => x.Status), new SortOrder(x => x.EmployeeLink.Name) ); var first = StartDate.DateTime.Value; var last = DateTime.Today.AddYears(1); foreach (var row in leave.Rows) { var id = row.Get(x => x.ID); var empid = row.Get(x => x.EmployeeLink.ID); var from = row.Get(x => x.From); from = from < first ? first : from; var to = row.Get(x => x.To); to = to > last ? last : to; last = _employees.Keys.Contains(id) && to > last ? to : last; var actid = row.Get(x => x.LeaveType.ID); var type = row.Get(x => x.LeaveType.Description); var status = row.Get(x => x.Status); for (var date = from; date <= to; date = date.AddDays(1)) crosstab.Add(new LeaveValue(id, empid, date, actid, status)); } data = new DataTable(); data.Columns.Add("Date", typeof(DateTime)); foreach (var employee in _employees.Keys) data.Columns.Add(employee.ToString(), typeof(object)); for (var date = first; date <= last; date = date.AddDays(1)) { var values = new List(); values.Add(date); foreach (var employee in _employees.Keys) { var value = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday ? null : crosstab.FirstOrDefault(x => x.Employee.Equals(employee) && x.Date.Equals(date)); values.Add(value == null ? new LeaveValue(Guid.Empty, employee, date, Guid.Empty, LeaveRequestStatus.InProgress) : value); } data.Rows.Add(values.ToArray()); } dataGrid.ItemsSource = data; } } private void DataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e) { e.Column.TextAlignment = TextAlignment.Center; e.Column.HorizontalHeaderContentAlignment = HorizontalAlignment.Center; e.Column.ColumnSizer = GridLengthUnitType.None; var value = e.Column.ValueBinding as Binding; if (value.Path.Path.Equals("Date")) { e.Column.Width = 100; e.Column.HeaderStyle = Resources["DateHeaderStyle"] as Style; } else { var style = new Style(typeof(GridCell)); style.Setters.Add(new Setter(BackgroundProperty, new Binding(value.Path.Path) { Converter = new LeaveBackgroundConverter { Colors = _activityColors } })); style.Setters.Add(new Setter(ForegroundProperty, new Binding(value.Path.Path) { Converter = new LeaveForegroundConverter() })); style.Setters.Add(new Setter(FontStyleProperty, new Binding(value.Path.Path) { Converter = new LeaveFontStyleConverter() })); style.Setters.Add(new Setter(FontWeightProperty, new Binding(value.Path.Path) { Converter = new LeaveFontWeightConverter() })); e.Column.CellStyle = style; e.Column.Width = 30; e.Column.HeaderStyle = Resources["ContentHeaderStyle"] as Style; e.Column.HeaderText = _employees[Guid.Parse(value.Path.Path)]; e.Column.DisplayBinding = new Binding { Path = new PropertyPath(e.Column.MappingName), Converter = new LeaveContentConverter { Abbreviations = _activityCodes } }; //e.Column.ValueBinding = new Binding() { Path = new PropertyPath(e.Column.MappingName), Converter = new LeaveContentConverter() }; //e.Column.UseBindingValue = true; } } //private void DataGrid_FilterItemsPopulating(object sender, GridFilterItemsPopulatingEventArgs e) //{ // e.FilterControl.FilterMode = FilterMode.AdvancedFilter; //} private void GetSelectionData(out DateTime from, out DateTime to, out Guid[] ids) { var emps = new List(); from = DateTime.MaxValue; to = DateTime.MinValue; foreach (var cell in dataGrid.GetSelectedCells()) { var binding = cell.Column.ValueBinding as Binding; if (Guid.TryParse(binding.Path.Path, out var emp)) if (!emps.Contains(emp)) emps.Add(emp); var row = cell.RowData as DataRowView; var date = (DateTime)row.Row.ItemArray.First(); if (date < from) from = date; if (date > to) to = date; } ids = emps.Any() ? emps.ToArray() : _employees.Keys.ToArray(); } private bool HasData() { foreach (var cell in dataGrid.GetSelectedCells()) { if (!cell.IsDataRowCell) continue; var propertyCollection = dataGrid.View.GetPropertyAccessProvider(); var cellvalue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName) as LeaveValue; if (cellvalue != null && cellvalue.ID != Guid.Empty) return true; } return false; } private IList GetData() { return dataGrid.GetSelectedCells() .Where(cell => cell.IsDataRowCell) .Select(cell => { var propertyCollection = dataGrid.View.GetPropertyAccessProvider(); var cellvalue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName) as LeaveValue; if (cellvalue != null && cellvalue.ID != Guid.Empty) return cellvalue; return null; }) .Where(x => x != null) .Select(x => x!) .ToList(); } private LeaveValue? GetData(GridCellInfo cell) { if (!cell.IsDataRowCell) return null; var propertyCollection = dataGrid.View.GetPropertyAccessProvider(); var cellvalue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName) as LeaveValue; return cellvalue != null && cellvalue.ID != Guid.Empty ? cellvalue : null; } private bool HasData(GridCellInfo cell) { if (!cell.IsDataRowCell) return false; var propertyCollection = dataGrid.View.GetPropertyAccessProvider(); var cellvalue = propertyCollection.GetValue(cell.RowData, cell.Column.MappingName) as LeaveValue; return cellvalue != null && cellvalue.ID != Guid.Empty; } private void CreateLeaveClick(object sender, RoutedEventArgs e) { var activity = (sender as MenuItem).Tag as Activity; GetSelectionData(out var from, out var to, out var ids); var leaves = new List(); foreach (var id in ids) { var leave = new LeaveRequest(); leave.From = from; leave.To = to; leave.LeaveType.ID = activity.ID; leave.EmployeeLink.ID = id; leaves.Add(leave); } if (lg == null) lg = new LeaveRequestGrid(); if (lg.EditItems(leaves.ToArray())) //Progress.Show("Saving Leave Requests"); //new Client().Save(leaves, "Created From Leave Calendar"); //Progress.Close(); Refresh(); } private void EditLeaveClick(object sender, RoutedEventArgs e) { GetSelectionData(out var from, out var to, out var ids); var requests = new Client().Load(new Filter(x => x.From).IsLessThanOrEqualTo(to).And(x => x.To) .IsGreaterThanOrEqualTo(from)); requests = requests.Where(x => ids.Contains(x.EmployeeLink.ID)).ToArray(); var lg = new LeaveRequests(); if (lg.EditItems(requests.ToArray())) //Progress.Show("Saving Leave Requests"); //new Client().Save(requests, "Updated From Leave Calendar"); //Progress.Close(); Refresh(); } private void DeleteLeaveClick(object sender, RoutedEventArgs e) { if (MessageBox.Show("Delete Leave Information?", "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) { GetSelectionData(out var from, out var to, out var ids); var requests = new Client().Load(new Filter(x => x.From).IsLessThanOrEqualTo(to).And(x => x.To) .IsGreaterThanOrEqualTo(from)); Progress.Show("Clearing Leave Requests"); foreach (var request in requests.Where(x => ids.Contains(x.EmployeeLink.ID))) new Client().Delete(request, "Deleted from Calendar"); Progress.Close(); Refresh(); } } private void DataGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e) { if (e.RightButton == MouseButtonState.Pressed) { var vc = dataGrid.GetVisualContainer(); var point = e.GetPosition(vc); var rci = vc.PointToCellRowColumnIndex(point); if (rci.RowIndex == 0 || rci.ColumnIndex == 0) return; var menu = new ContextMenu(); if (!HasData(dataGrid.CurrentCellInfo)) foreach (var row in _activities.Rows) { var createleave = new MenuItem { Header = row.Get(c => c.Description) }; createleave.Tag = row.ToObject(); createleave.Click += CreateLeaveClick; menu.Items.Add(createleave); } if (HasData()) { var deleteleave = new MenuItem { Header = "Delete Leave" }; deleteleave.Click += DeleteLeaveClick; menu.Items.Add(deleteleave); } dataGrid.ContextMenu = menu; menu.IsOpen = true; } } private void DataGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e) { var vc = dataGrid.GetVisualContainer(); var p = Mouse.GetPosition(vc); var rci = vc.PointToCellRowColumnIndex(p); if (rci.RowIndex < 1 || rci.ColumnIndex < 1) { e.Handled = true; return; } dataGrid.ContextMenu.Items.Clear(); var bCreate = !HasData(dataGrid.CurrentCellInfo); var bEdit = HasData(); if (bCreate) foreach (var row in _activities.Rows) { var createleave = new MenuItem { Header = row.Get(c => c.Description) }; createleave.Tag = row.ToObject(); createleave.Click += CreateLeaveClick; dataGrid.ContextMenu.Items.Add(createleave); } if (bEdit && bCreate) dataGrid.ContextMenu.Items.Add(new Separator()); if (bEdit) { var editleave = new MenuItem { Header = "Edit Leave" }; editleave.Click += EditLeaveClick; dataGrid.ContextMenu.Items.Add(editleave); dataGrid.ContextMenu.Items.Add(new Separator()); var deleteleave = new MenuItem { Header = "Delete Leave" }; deleteleave.Click += DeleteLeaveClick; dataGrid.ContextMenu.Items.Add(deleteleave); var cell = GetData(dataGrid.CurrentCellInfo); dataGrid.ContextMenu.Items.Add(new Separator()); var formsItem = new MenuItem { Header = "Digital Forms" }; DynamicGridUtils.PopulateFormMenu(formsItem, cell.ID); dataGrid.ContextMenu.Items.Add(formsItem); } } private void DateTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (!bReady) return; Refresh(); } private void SyncSelectedTeams(Guid teamid) { var bOldReady = bReady; bReady = false; if (teamid != CoreUtils.FullGuid) { SelectedTeams.SelectedItems.Clear(); foreach (KeyValuePair sel in SelectedTeams.Items) if (sel.Key == teamid) SelectedTeams.SelectedItems.Add(sel); } LoadEmployees(true); bReady = bOldReady; } private void GroupsSelectionChanged(object sender, SelectionChangedEventArgs e) { if (Teams.SelectedValue == null) return; var teamid = (Guid)Teams.SelectedValue; ChangeSelectedTeams(teamid); SyncSelectedTeams(teamid); } private void ChangeSelectedTeams(Guid teamid) { if (teamid == CoreUtils.FullGuid) { EmployeeGrid.RowDefinitions[1].Height = new GridLength(_settings.ListSize, GridUnitType.Pixel); EmployeeGrid.RowDefinitions[2].Height = new GridLength(1, GridUnitType.Auto); } else { var oldbReady = bReady; bReady = false; EmployeeGrid.RowDefinitions[1].Height = new GridLength(0, GridUnitType.Pixel); EmployeeGrid.RowDefinitions[2].Height = new GridLength(0, GridUnitType.Pixel); bReady = oldbReady; } //bHandled = false; } //bool bHandled = false; //private void SelectedTeams_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) //{ // if (!bReady) // return; // if (!bHandled) // LoadEmployees(); // bHandled = !bHandled; //} private void SelectedTeams_ItemChecked(object sender, ItemCheckedEventArgs e) { if (!bReady) return; LoadEmployees(true); } private void LoadEmployees(bool selectall) { var emps = new Dictionary(); foreach (var pair in SelectedTeams.SelectedItems) if (pair != null) { var key = ((KeyValuePair)pair).Key; foreach (var row in _employeeTeams.Rows.Where(r => r.Get(c => c.TeamLink.ID).Equals(key) || key.Equals(CoreUtils.FullGuid))) emps[row.Get(c => c.EmployeeLink.ID)] = row.Get(c => c.EmployeeLink.Name); } var bOldReady = bReady; bReady = false; SelectedEmployees.ItemsSource = emps; foreach (var item in SelectedEmployees.Items) { var pair = (KeyValuePair)item; if (_settings.SelectedEmployees.Contains(pair.Key) || selectall) SelectedEmployees.SelectedItems.Add(item); } bReady = bOldReady; SaveSettings(); Refresh(); } private void EmployeesSelectionChanged(object sender, SelectionChangedEventArgs e) { if (!bReady || e.AddedItems.Count == 0 || e.AddedItems[0] == null) return; //ReloadColumns(); SaveSettings(); Refresh(); } private void Export_Click(object sender, RoutedEventArgs e) { var options = new ExcelExportingOptions(); options.ExcelVersion = ExcelVersion.Excel2013; var excelEngine = dataGrid.ExportToExcel(dataGrid.View, options); var workBook = excelEngine.Excel.Workbooks[0]; var dlg = new SaveFileDialog(); dlg.Filter = "Excel Files (*.xlsx)|*.xlsx"; dlg.FileName = typeof(LeaveRequest).EntityName().Split('.').Last() + ".xlsx"; if (dlg.ShowDialog() == true) try { workBook.SaveAs(dlg.FileName); Process.Start(new ProcessStartInfo(dlg.FileName) { UseShellExecute = true }); } catch (Exception e2) { MessageBox.Show("Error saving spreadsheet!\n\n" + e2.Message); } //workBook.SaveAs("Leave Requests.xlsx"); } private void SelectedTeams_SizeChanged(object sender, SizeChangedEventArgs e) { SaveSettings(); } } }