Selaa lähdekoodia

EmployeeQualificationDashboard using the required qualifications view. Password expiration disable if PasswordExpirationTime <= 0

Kenric Nugteren 2 vuotta sitten
vanhempi
commit
2233874975

+ 12 - 2
prs.desktop/Dashboards/HumanResources/EmployeeQualificationDashboard.xaml

@@ -36,8 +36,17 @@
             <Setter Property="IsTabStop" Value="False"/>
             <Setter Property="Template" Value="{StaticResource VerticalColumnHeader}"/>
         </Style>
-    </UserControl.Resources>
 
+
+        <LinearGradientBrush x:Key="shadedBackground"
+                             EndPoint="0,0" StartPoint="3,3"
+                             MappingMode="Absolute" SpreadMethod="Repeat">
+            <GradientStop Color="Red" Offset="0"/>
+            <GradientStop Color="Red" Offset="0.2"/>
+            <GradientStop Color="Salmon" Offset="0.2"/>
+            <GradientStop Color="Salmon" Offset="1"/>
+        </LinearGradientBrush>
+    </UserControl.Resources>
     <sf:SfDataGrid x:Name="DataGrid"
                    Grid.Row="1" Grid.Column="0"
                    RowHeight="30"
@@ -45,7 +54,8 @@
                    AutoGenerateColumns="True"
                    FrozenColumnCount="1"
                    AutoGeneratingColumn="DataGrid_AutoGeneratingColumn"
-                   ContextMenuOpening="DataGrid_ContextMenuOpening">
+                   ContextMenuOpening="DataGrid_ContextMenuOpening"
+                   CellToolTipOpening="DataGrid_CellToolTipOpening">
         <sf:SfDataGrid.ContextMenu>
             <ContextMenu/>
         </sf:SfDataGrid.ContextMenu>

+ 106 - 19
prs.desktop/Dashboards/HumanResources/EmployeeQualificationDashboard.xaml.cs

@@ -3,6 +3,7 @@ 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;
@@ -24,22 +25,39 @@ namespace PRSDesktop
 
     class CellBackgroundConverter : IValueConverter
     {
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        private EmployeeQualificationDashboard Dashboard;
+
+        public CellBackgroundConverter(EmployeeQualificationDashboard dashboard)
         {
-            if (value is null || value is not DateTime date)
-                return DependencyProperty.UnsetValue;
+            Dashboard = dashboard;
+        }
 
-            if (date == DateTime.MinValue || date == DateTime.MaxValue)
+        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;
-
-            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);
-
+            }
+            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;
         }
 
@@ -92,6 +110,12 @@ namespace PRSDesktop
         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))
@@ -116,19 +140,23 @@ namespace PRSDesktop
             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(Employees.Where(x => x.Value).Select(x => x.Key).ToArray()),
+                    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).InQuery(employeeFilter, x => x.ID),
+                    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 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) });
 
@@ -140,7 +168,7 @@ namespace PRSDesktop
                 var qID = qualification.Get<Qualification, Guid>(x => x.ID);
                 if (!columns.Contains(qID))
                 {
-                    CoreTable.Columns.Add(new CoreColumn() { ColumnName = qID.ToString(), DataType = typeof(DateTime) });
+                    CoreTable.Columns.Add(new CoreColumn() { ColumnName = qID.ToString(), DataType = typeof(object) });
                     columns.Add(qID);
                     ColumnHeaders.Add(qID, qualification.Get<Qualification, string>(x => x.Description));
                 }
@@ -149,12 +177,19 @@ namespace PRSDesktop
 
             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"]
@@ -180,9 +215,13 @@ namespace PRSDesktop
                             values.Add(expiry);
                         }
                     }
+                    else if (required.Contains(qID))
+                    {
+                        values.Add(CellValue.Required);
+                    }
                     else
                     {
-                        values.Add(null);
+                        values.Add(CellValue.None);
                     }
                 }
                 var row = CoreTable.NewRow();
@@ -270,6 +309,10 @@ namespace PRSDesktop
                         else
                             newValue = date;
                     }
+                    else if(value is CellValue cellValue)
+                    {
+                        newValue = "";
+                    }
                     else
                     {
                         newValue = value;
@@ -315,6 +358,15 @@ namespace PRSDesktop
             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)
         {
@@ -350,10 +402,11 @@ namespace PRSDesktop
                 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() }));
+                    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() };
@@ -364,6 +417,39 @@ namespace PRSDesktop
             }
         }
 
+        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);
@@ -455,6 +541,7 @@ namespace PRSDesktop
         }
 
         #endregion
+
     }
 
     class EmployeeSelectionGrid : EntitySelectionGrid<Employee>

+ 1 - 1
prs.desktop/Panels/Suppliers/SupplierPurchaseOrderItemOneToMany.cs

@@ -25,7 +25,7 @@ namespace PRSDesktop
             }
         }
 
-        protected override Dictionary<string, object> EditorValueChanged(IDynamicEditorForm editor, PurchaseOrderItem[] items, string name,
+        protected override Dictionary<string, object?> EditorValueChanged(IDynamicEditorForm editor, PurchaseOrderItem[] items, string name,
             object value)
         {
             var results = base.EditorValueChanged(editor, items, name, value);

+ 1 - 0
prs.server/Engines/Database/DatabaseEngine.cs

@@ -167,6 +167,7 @@ namespace PRSServer
             DbFactory.Start(deviceid);
 
             UserStore.PasswordExpirationTime = TimeSpan.FromDays(Properties.PasswordExpiryTime);
+            RestService.CheckPasswordExpiration = Properties.PasswordExpiryTime > 0;
 
             var users = DbFactory.Provider.Load<User>();
             if (!users.Any())