using Comal.Classes; using InABox.Clients; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF; using Microsoft.Win32; using Org.BouncyCastle.Crypto; using PRSDesktop.WidgetGroups; using Syncfusion.UI.Xaml.Grid.Helpers; using Syncfusion.UI.Xaml.ScrollAxis; using System; using System.Collections.Generic; using System.Data; using System.Globalization; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; namespace PRSDesktop { class CellBackgroundConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is null || value is not DateTime date) return DependencyProperty.UnsetValue; if (date == DateTime.MinValue || date == DateTime.MaxValue) return DependencyProperty.UnsetValue; var diff = date - DateTime.Now; if (diff <= TimeSpan.Zero) return new SolidColorBrush(Colors.Salmon); else if (diff.TotalDays < 7) return new SolidColorBrush(Colors.Orange); else if (diff.TotalDays < 30) return new SolidColorBrush(Colors.Yellow); return DependencyProperty.UnsetValue; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } public class CellContentConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is null || value is not DateTime date || date == DateTime.MinValue) return DependencyProperty.UnsetValue; if(date == DateTime.MaxValue) return "Perm."; return date.ToString("dd/MM/yy"); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } public class EmployeeQualificationDashboardProperties : IDashboardProperties { public List? Employees { get; set; } = null; public List? Qualifications { get; set; } = null; } public class EmployeeQualificationDashboardElement : DashboardElement { } /// /// Interaction logic for EmployeeQualificationDashboard.xaml /// public partial class EmployeeQualificationDashboard : UserControl, IDashboardWidget, IRequiresCanView, IActionsDashboard { private DataTable DataTable; private CoreTable CoreTable; private HashSet Employees; private HashSet Qualifications; private Dictionary ColumnHeaders; private List QualificationIDs; private List EmployeeIDs; private Filter EmployeeFilter { get; set; } = new Filter().All() .And(new Filter(x => x.StartDate).IsEqualTo(DateTime.MinValue) .Or(x => x.StartDate).IsLessThan(DateTime.Now)) .And(new Filter(x => x.FinishDate).IsEqualTo(DateTime.MinValue) .Or(x => x.FinishDate).IsGreaterThan(DateTime.Now)); public EmployeeQualificationDashboardProperties Properties { get; set; } public EmployeeQualificationDashboard() { InitializeComponent(); } #region CorePanel Stuff public void Refresh() { Properties.Qualifications = Qualifications.ToList(); Properties.Employees = Employees.ToList(); CoreTable = new(); CoreTable.TableName = "Qualifications"; ColumnHeaders = new(); var employeeFilter = EmployeeFilter; var results = Client.QueryMultiple( new KeyedQueryDef(nameof(Employee), employeeFilter, new Columns(x => x.ID, x => x.Name)), new KeyedQueryDef(nameof(EmployeeQualification), new Filter(x => x.Employee.ID).InQuery(employeeFilter, x => x.ID), new Columns( x => x.Employee.ID, x => x.Qualification.ID, x => x.Expiry)), new KeyedQueryDef(nameof(Qualification), new Filter(x => x.ID).InList(Qualifications.ToArray()), new Columns(x => x.ID, x => x.Description))); CoreTable.Columns.Add(new CoreColumn() { ColumnName = "Employee", DataType = typeof(string) }); var columns = new List(); var qualifications = results[nameof(Qualification)]; foreach (var qualification in qualifications.Rows) { var qID = qualification.Get(x => x.ID); if (!columns.Contains(qID)) { CoreTable.Columns.Add(new CoreColumn() { ColumnName = qID.ToString(), DataType = typeof(DateTime) }); columns.Add(qID); ColumnHeaders.Add(qID, qualification.Get(x => x.Description)); } } QualificationIDs = columns; EmployeeIDs = new(); var employeeQualifications = results[nameof(EmployeeQualification)]; foreach (var employee in results[nameof(Employee)].Rows) { var employeeID = employee.Get(x => x.ID); if (!Employees.Contains(employeeID)) { continue; } EmployeeIDs.Add(employeeID); List values = new() { employee["Name"] }; var thisQualifications = employeeQualifications.Rows .Where(x => x.Get(x => x.Employee.ID) == employeeID) .ToList(); foreach (var qID in columns) { var employeeQualification = thisQualifications .Where(x => x.Get(x => x.Qualification.ID) == qID) .FirstOrDefault(); if(employeeQualification != null) { var expiry = employeeQualification.Get(x => x.Expiry); if(expiry == DateTime.MinValue || expiry == DateTime.MaxValue) { values.Add(DateTime.MaxValue); } else { values.Add(expiry); } } else { values.Add(null); } } var row = CoreTable.NewRow(); row.LoadValues(values); CoreTable.Rows.Add(row); } DataTable = CoreTable.ToDataTable(); DataGrid.ItemsSource = DataTable; foreach(var column in CoreTable.Columns) { if(Guid.TryParse(column.ColumnName, out var qID)) { column.ColumnName = ColumnHeaders[qID]; } } } public void Setup() { var employees = Properties.Employees?.ToHashSet(); var qualifications = Properties.Qualifications?.ToHashSet(); if (employees == null || qualifications == null) { var employeeFilter = EmployeeFilter; var results = Client.QueryMultiple( new KeyedQueryDef(nameof(Employee), employeeFilter, new Columns(x => x.ID, x => x.StartDate, x => x.FinishDate)), new KeyedQueryDef(nameof(Qualification), new Filter().All(), new Columns(x => x.ID))); employees ??= results[nameof(Employee)].Rows.Select(x => x.Get(x => x.ID)).ToHashSet(); qualifications ??= results[nameof(Qualification)].Rows.Select(x => x.Get(x => x.ID)).ToHashSet(); } Employees = employees; Qualifications = qualifications; DataGrid.CellDoubleTapped += DataGrid_CellDoubleTapped; } public void Shutdown() { } #endregion #region Actions private void DoExport() { var newTable = new CoreTable() { TableName = CoreTable.TableName }; newTable.LoadColumns(CoreTable.Columns); foreach (var row in CoreTable.Rows) { var newRow = newTable.NewRow(); foreach (var value in row.Values) { object? newValue; if (value is DateTime date) { if (date == DateTime.MaxValue) newValue = "Permanent"; else if (date == DateTime.MinValue) newValue = ""; else newValue = date; } else { newValue = value; } newRow.Values.Add(newValue); } newTable.Rows.Add(newRow); } ExcelExporter.DoExport(newTable, "EmployeeQualifications"); } public void BuildActionsMenu(ContextMenu menu) { if (Security.CanExport()) { menu.AddItem("Export", null, DoExport); } } #endregion #region Grid Events private EmployeeQualification? GetCellEmployeeQualification(int row, int column) { var employeeID = EmployeeIDs[row - 1]; var qualificationID = QualificationIDs[column - 1]; var qualification = new Client() .Query( new Filter(x => x.Employee.ID).IsEqualTo(employeeID) .And(x => x.Qualification.ID).IsEqualTo(qualificationID)); return qualification.Rows.FirstOrDefault()?.ToObject(); } private object? GetCellData(int row, int column) { var cell = DataGrid.GetGridCellInfo(new RowColumnIndex(row, column)); if (!cell.IsDataRowCell) return null; var propertyCollection = DataGrid.View.GetPropertyAccessProvider(); return propertyCollection.GetValue(cell.RowData, cell.Column.MappingName); } private void DoEditQualification(int row, int column) { var qualification = GetCellEmployeeQualification(row, column); if (qualification is null) return; var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(EmployeeQualification)) as DynamicDataGrid; if (grid!.EditItems(new[] { qualification })) { new Client().Save(qualification, "Edited by user from dashboard"); Refresh(); } } private void DataGrid_CellDoubleTapped(object? sender, Syncfusion.UI.Xaml.Grid.GridCellDoubleTappedEventArgs e) { var rowIndex = e.RowColumnIndex.RowIndex; var columnIndex = e.RowColumnIndex.ColumnIndex; DoEditQualification(rowIndex, columnIndex); } private void DataGrid_AutoGeneratingColumn(object sender, Syncfusion.UI.Xaml.Grid.AutoGeneratingColumnArgs e) { if (e.Column.ValueBinding is not Binding value) return; if (Guid.TryParse(e.Column.HeaderText, out var qID)) { e.Column.HeaderStyle = Resources["QualificationHeaderStyle"] as Style; e.Column.HeaderText = ColumnHeaders[qID]; e.Column.Width = 55; e.Column.TextAlignment = TextAlignment.Center; e.Column.ShowHeaderToolTip = true; var style = new Style(); style.Setters.Add(new Setter(BackgroundProperty, new Binding(value.Path.Path) { Converter = new CellBackgroundConverter() })); e.Column.CellStyle = style; e.Column.DisplayBinding = new Binding { Path = new PropertyPath(e.Column.MappingName), Converter = new CellContentConverter() }; } else { e.Column.HeaderStyle = Resources["EmployeeHeaderStyle"] as Style; } } private void PopulateCellMenu(ContextMenu menu, int row, int column) { var data = GetCellData(row, column); if (data is null || data is not DateTime) { menu.AddItem("No Qualification", null, null, false); return; } menu.AddItem("Edit Qualification", null, new Tuple(row, column), EditQualification_Click); } private void EditQualification_Click(Tuple obj) { DoEditQualification(obj.Item1, obj.Item2); } private void DataGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e) { var vc = DataGrid.GetVisualContainer(); var p = Mouse.GetPosition(vc); var rci = vc.PointToCellRowColumnIndex(p); var menu = DataGrid.ContextMenu; menu.Items.Clear(); if(rci.RowIndex == 0) { var selectQualification = new MenuItem() { Header = "Select Qualifications" }; selectQualification.Click += SelectQualification_Click; menu.Items.Add(selectQualification); if(rci.ColumnIndex > 0) { var column = CoreTable.Columns[rci.ColumnIndex]; var hideQualification = new MenuItem() { Header = $"Hide '{column.ColumnName}'" }; hideQualification.Click += (sender, e) => { Qualifications.Remove(QualificationIDs[rci.ColumnIndex - 1]); Refresh(); }; menu.Items.Add(hideQualification); } } if(rci.ColumnIndex == 0) { var selectEmployee = new MenuItem() { Header = "Select Employees" }; selectEmployee.Click += SelectEmployee_Click; menu.Items.Add(selectEmployee); if (rci.RowIndex > 0) { var row = CoreTable.Rows[rci.RowIndex - 1]; var hideEmployee = new MenuItem() { Header = $"Hide '{row["Employee"]}'" }; hideEmployee.Click += (sender, e) => { Employees.Remove(EmployeeIDs[rci.RowIndex - 1]); Refresh(); }; menu.Items.Add(hideEmployee); } } if(rci.RowIndex > 0 && rci.ColumnIndex > 0) { PopulateCellMenu(menu, rci.RowIndex, rci.ColumnIndex); } } private void SelectEmployee_Click(object sender, RoutedEventArgs e) { var window = new EntitySelectionWindow(typeof(Employee), Employees, typeof(EmployeeSelectionGrid)); window.ShowDialog(); Employees = window.Entities; Refresh(); } private void SelectQualification_Click(object sender, RoutedEventArgs e) { var window = new EntitySelectionWindow(typeof(Qualification), Qualifications); window.ShowDialog(); Qualifications = window.Entities; Refresh(); } #endregion } class EmployeeSelectionGrid : EntitySelectionGrid { public override void ConfigureColumns(DynamicGridColumns columns) { columns.Clear(); columns.Add(x => x.Name, 0, "Name", "", Alignment.MiddleLeft); } } }