123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558 |
- using Comal.Classes;
- using InABox.Clients;
- using InABox.Core;
- using InABox.DynamicGrid;
- using InABox.WPF;
- using jdk.nashorn.@internal.ir;
- 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;
- using InABox.Configuration;
- namespace PRSDesktop
- {
- class CellBackgroundConverter : IValueConverter
- {
- private EmployeeQualificationDashboard Dashboard;
- public CellBackgroundConverter(EmployeeQualificationDashboard dashboard)
- {
- Dashboard = dashboard;
- }
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if(value is DateTime date)
- {
- 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;
- }
- if(value is EmployeeQualificationDashboard.CellValue cellValue)
- {
- switch (cellValue)
- {
- case EmployeeQualificationDashboard.CellValue.Required:
- return Dashboard.Resources["shadedBackground"];
- case EmployeeQualificationDashboard.CellValue.None:
- return DependencyProperty.UnsetValue;
- }
- }
- 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 : UserConfigurationSettings, IDashboardProperties
- {
- public Dictionary<Guid, bool>? Employees { get; set; } = null;
- public Dictionary<Guid, bool>? Qualifications { get; set; } = null;
- }
- public class EmployeeQualificationDashboardElement : DashboardElement<EmployeeQualificationDashboard, HumanResources, EmployeeQualificationDashboardProperties> { }
- /// <summary>
- /// Interaction logic for EmployeeQualificationDashboard.xaml
- /// </summary>
- public partial class EmployeeQualificationDashboard : UserControl, IDashboardWidget<HumanResources, EmployeeQualificationDashboardProperties>, IRequiresCanView<EmployeeQualification>, IActionsDashboard
- {
- private DataTable DataTable;
- private CoreTable CoreTable;
- private List<Guid> AllEmployees;
- private Dictionary<Guid, bool> Employees;
- private Dictionary<Guid, bool> Qualifications;
- private Dictionary<Guid, string> ColumnHeaders;
- private List<Guid> QualificationIDs;
- private List<Guid> EmployeeIDs;
- public enum CellValue
- {
- None,
- Required
- }
- private Filter<Employee> EmployeeFilter { get; set; } = new Filter<Employee>().All()
- .And(new Filter<Employee>(x => x.StartDate).IsEqualTo(DateTime.MinValue)
- .Or(x => x.StartDate).IsLessThan(DateTime.Now))
- .And(new Filter<Employee>(x => x.FinishDate).IsEqualTo(DateTime.MinValue)
- .Or(x => x.FinishDate).IsGreaterThan(DateTime.Now));
-
- public EmployeeQualificationDashboardProperties Properties { get; set; }
- public event LoadSettings<EmployeeQualificationDashboardProperties>? LoadSettings;
- public event SaveSettings<EmployeeQualificationDashboardProperties>? SaveSettings;
- public EmployeeQualificationDashboard()
- {
- InitializeComponent();
- }
- #region CorePanel Stuff
- public void Refresh()
- {
- Properties.Qualifications = Qualifications;
- Properties.Employees = Employees;
- CoreTable = new("Qualifications");
- ColumnHeaders = new();
- var employeeFilter = EmployeeFilter;
- var employeeIDs = Employees.Where(x => x.Value).Select(x => x.Key).ToArray();
- var results = Client.QueryMultiple(
- new KeyedQueryDef<Employee>(nameof(Employee),
- new Filter<Employee>(x => x.ID).InList(employeeIDs),
- new Columns<Employee>(x => x.ID, x => x.Name)),
- new KeyedQueryDef<EmployeeQualification>(nameof(EmployeeQualification),
- new Filter<EmployeeQualification>(x => x.Employee.ID).InList(employeeIDs),
- new Columns<EmployeeQualification>(
- x => x.Employee.ID,
- x => x.Qualification.ID,
- x => x.Expiry)),
- new KeyedQueryDef<Qualification>(nameof(Qualification),
- new Filter<Qualification>(x => x.ID).InList(Qualifications.Where(x => x.Value).Select(x => x.Key).ToArray()),
- new Columns<Qualification>(x => x.ID, x => x.Description)),
- new KeyedQueryDef<EmployeeRequiredQualification>(
- new Filter<EmployeeRequiredQualification>(x => x.Employee.ID).InList(employeeIDs),
- new Columns<EmployeeRequiredQualification>(x => x.Employee.ID, x => x.Qualification.ID)));
- CoreTable.Columns.Add(new CoreColumn() { ColumnName = "Employee", DataType = typeof(string) });
- var columns = new List<Guid>();
- var qualifications = results[nameof(Qualification)];
- foreach (var qualification in qualifications.Rows)
- {
- var qID = qualification.Get<Qualification, Guid>(x => x.ID);
- if (!columns.Contains(qID))
- {
- CoreTable.Columns.Add(new CoreColumn() { ColumnName = qID.ToString(), DataType = typeof(object) });
- columns.Add(qID);
- ColumnHeaders.Add(qID, qualification.Get<Qualification, string>(x => x.Description));
- }
- }
- QualificationIDs = columns;
- EmployeeIDs = new();
- var requiredQualifications = results.Get<EmployeeRequiredQualification>()
- .ToObjects<EmployeeRequiredQualification>()
- .GroupBy(x => x.Employee.ID, x => x.Qualification.ID)
- .ToDictionary(x => x.Key, x => x.ToHashSet());
- var employeeQualifications = results[nameof(EmployeeQualification)];
- foreach (var employee in results[nameof(Employee)].Rows)
- {
- var employeeID = employee.Get<Employee, Guid>(x => x.ID);
- EmployeeIDs.Add(employeeID);
- var required = requiredQualifications.GetValueOrDefault(employeeID) ?? new HashSet<Guid>();
- List<object?> values = new()
- {
- employee["Name"]
- };
- var thisQualifications = employeeQualifications.Rows
- .Where(x => x.Get<EmployeeQualification, Guid>(x => x.Employee.ID) == employeeID)
- .ToList();
- foreach (var qID in columns)
- {
- var employeeQualification = thisQualifications
- .Where(x => x.Get<EmployeeQualification, Guid>(x => x.Qualification.ID) == qID)
- .FirstOrDefault();
- if(employeeQualification != null)
- {
- var expiry = employeeQualification.Get<EmployeeQualification, DateTime>(x => x.Expiry);
- if(expiry == DateTime.MinValue || expiry == DateTime.MaxValue)
- {
- values.Add(DateTime.MaxValue);
- }
- else
- {
- values.Add(expiry);
- }
- }
- else if (required.Contains(qID))
- {
- values.Add(CellValue.Required);
- }
- else
- {
- values.Add(CellValue.None);
- }
- }
- 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 static bool IsEmployeeActive(Employee employee)
- => (employee.StartDate == DateTime.MinValue || employee.StartDate < DateTime.Now)
- && (employee.FinishDate == DateTime.MinValue || employee.FinishDate > DateTime.Now);
- public void Setup()
- {
- var employeeFilter = EmployeeFilter;
- var results = Client.QueryMultiple(
- new KeyedQueryDef<Employee>(nameof(Employee),
- new Filter<Employee>().All(),
- new Columns<Employee>(x => x.ID, x => x.StartDate, x => x.FinishDate)),
- new KeyedQueryDef<Qualification>(nameof(Qualification),
- new Filter<Qualification>().All(),
- new Columns<Qualification>(x => x.ID)));
- var employees = results[nameof(Employee)].ToObjects<Employee>().ToDictionary(
- x => x.ID,
- x => IsEmployeeActive(x));
- if (Properties.Employees is not null)
- {
- employees = employees
- .ToDictionary(
- x => x.Key,
- x => !Properties.Employees.ContainsKey(x.Key) || Properties.Employees[x.Key]);
- }
- var qualifications = results[nameof(Qualification)].Rows.Select(x => x.Get<Qualification, Guid>(x => x.ID)).ToDictionary(x => x, x => true);
- if(Properties.Qualifications is not null)
- {
- qualifications = qualifications
- .ToDictionary(
- x => x.Key,
- x => !Properties.Qualifications.ContainsKey(x.Key) || Properties.Qualifications[x.Key]);
- }
- Employees = employees;
- Qualifications = qualifications;
- DataGrid.CellDoubleTapped += DataGrid_CellDoubleTapped;
- }
- public void Shutdown()
- {
- }
- #endregion
- #region Actions
- private void DoExport()
- {
- var newTable = new CoreTable(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 if(value is CellValue cellValue)
- {
- newValue = "";
- }
- else
- {
- newValue = value;
- }
- newRow.Values.Add(newValue);
- }
- newTable.Rows.Add(newRow);
- }
- ExcelExporter.DoExport(newTable, "EmployeeQualifications");
- }
- public void BuildActionsMenu(ContextMenu menu)
- {
- if (Security.CanExport<EmployeeQualification>())
- {
- 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<EmployeeQualification>()
- .Query(
- new Filter<EmployeeQualification>(x => x.Employee.ID).IsEqualTo(employeeID)
- .And(x => x.Qualification.ID).IsEqualTo(qualificationID));
- return qualification.Rows.FirstOrDefault()?.ToObject<EmployeeQualification>();
- }
- 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 string GetColumnHeader(int column)
- {
- var header = DataGrid.GetHeaderCell(DataGrid.Columns[column]);
- if (header is null)
- return "";
- return header.Content?.ToString() ?? "";
- }
- private string GetRowHeader(int row) => GetCellData(row, 0)?.ToString() ?? "";
- 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<EmployeeQualification>;
- if (grid!.EditItems(new[] { qualification }))
- {
- new Client<EmployeeQualification>().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;
- e.Column.ShowToolTip = true;
- var style = new Style();
- style.Setters.Add(new Setter(BackgroundProperty,
- new Binding(value.Path.Path) { Converter = new CellBackgroundConverter(this) }));
- 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 bool OpenCellTooltip(ToolTip tooltip, int row, int column)
- {
- var data = GetCellData(row, column);
- if(data is CellValue cellValue)
- {
- if (cellValue == CellValue.Required)
- {
- tooltip.Content = new TextBlock { Text = $"{GetRowHeader(row)} requires '{GetColumnHeader(column)}', but they do not have it." };
- return true;
- }
- }
- return false;
- }
- private void DataGrid_CellToolTipOpening(object sender, Syncfusion.UI.Xaml.Grid.GridCellToolTipOpeningEventArgs e)
- {
- var vc = DataGrid.GetVisualContainer();
- var p = Mouse.GetPosition(vc);
- var rci = vc.PointToCellRowColumnIndex(p);
- if (rci.RowIndex > 0 && rci.ColumnIndex > 0)
- {
- if(!OpenCellTooltip(e.ToolTip, rci.RowIndex, rci.ColumnIndex))
- {
- e.ToolTip.IsOpen = false;
- e.ToolTip.Visibility = Visibility.Collapsed;
- }
- else
- {
- e.ToolTip.Visibility = Visibility.Visible;
- }
- }
- }
- 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<int, int>(row, column), EditQualification_Click);
- }
- private void EditQualification_Click(Tuple<int, int> 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[QualificationIDs[rci.ColumnIndex - 1]] = false;
- 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[EmployeeIDs[rci.RowIndex - 1]] = false;
- 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.Where(x => x.Value).Select(x => x.Key).ToHashSet(), typeof(EmployeeSelectionGrid));
- window.ShowDialog();
- Employees = Employees.ToDictionary(
- x => x.Key,
- x => window.Entities.Contains(x.Key));
- Refresh();
- }
- private void SelectQualification_Click(object sender, RoutedEventArgs e)
- {
- var window = new EntitySelectionWindow(typeof(Qualification), Qualifications.Where(x => x.Value).Select(x => x.Key).ToHashSet());
- window.ShowDialog();
- Qualifications = Qualifications.ToDictionary(
- x => x.Key,
- x => window.Entities.Contains(x.Key));
- Refresh();
- }
- #endregion
- }
- class EmployeeSelectionGrid : EntitySelectionGrid<Employee>
- {
- public override void ConfigureColumns(DynamicGridColumns columns)
- {
- columns.Clear();
- columns.Add<Employee, string>(x => x.Name, 0, "Name", "", Alignment.MiddleLeft);
- }
- }
- }
|