ソースを参照

Calendar: Changed customising for context menu to allow for Daily Report stuff; fixed binding for Assignments

Kenric Nugteren 1 週間 前
コミット
472653eb98

+ 67 - 18
prs.desktop/Components/Calendar/Appointments/AssignmentAppointment.cs

@@ -9,6 +9,7 @@ using System.Windows.Media.Imaging;
 using Comal.Classes;
 using Geocoding;
 using InABox.Core;
+using InABox.DynamicGrid;
 using InABox.WPF;
 
 namespace PRSDesktop
@@ -39,32 +40,57 @@ namespace PRSDesktop
             AssignmentType = type;
             
             Notes = Model.Description;
-            
-            var subject = new List<string>() { model.Number.ToString() };
-            if (model.JobLink.ID != Guid.Empty)
+
+            Subject = GetSubject();
+
+            Image = GetImage();
+
+            WeakEventManager<Assignment, PropertyChangedEventArgs>.AddHandler(model, nameof(Assignment.PropertyChanged), Assignment_Changed);
+        }
+
+        private static Column<Assignment>[] SubjectColumns = [
+            new(x => x.Number),
+            new(x => x.JobLink.JobNumber),
+            new(x => x.ITP.Code),
+            new(x => x.Task.Number),
+            new(x => x.Meeting.Link.Number),
+            new(x => x.Title),
+            ];
+
+        private string GetSubject()
+        {
+            var subject = new List<string>() { Model.Number.ToString() };
+            if (Model.JobLink.ID != Guid.Empty)
                 subject.Add(
-                    model.ITP.ID != Guid.Empty
-                        ? $"{model.JobLink.JobNumber}-{model.ITP.Code}"
-                        : $"{model.JobLink.JobNumber}"
+                    Model.ITP.ID != Guid.Empty
+                        ? $"{Model.JobLink.JobNumber}-{Model.ITP.Code}"
+                        : $"{Model.JobLink.JobNumber}"
                 );
-            if (model.Task.ID  != Guid.Empty)
-                subject.Add($"Task {model.Task.Number}");
-            if (model.Meeting.Link.ID  != Guid.Empty)
-                subject.Add($"Mtg {model.Meeting.Link.Number}");
+            if (Model.Task.ID  != Guid.Empty)
+                subject.Add($"Task {Model.Task.Number}");
+            if (Model.Meeting.Link.ID  != Guid.Empty)
+                subject.Add($"Mtg {Model.Meeting.Link.Number}");
             
-            subject.Add(model.Title ?? "");
-            Subject = string.Join(" ", subject);
+            subject.Add(Model.Title ?? "");
+            return string.Join(" ", subject);
+        }
+
+        private static Column<Assignment>[] ImageColumns = [
+            new(x => x.Completed),
+            new(x => x.Delivery.ID),
+            new(x => x.Meeting.Link.ID),
+            ];
 
+        private BitmapImage? GetImage()
+        {
             var images = new List<Bitmap>();
-            if (!model.Completed.IsEmpty())
+            if (!Model.Completed.IsEmpty())
                 images.Add(Resources.tick_sml.Resize(32,32));
-            if (model.Delivery.ID != Guid.Empty)
+            if (Model.Delivery.ID != Guid.Empty)
                 images.Add(Resources.box_sml.Resize(32,32));
-            if (model.Meeting.Link.ID != Guid.Empty)
+            if (Model.Meeting.Link.ID != Guid.Empty)
                 images.Add(Resources.employees.Resize(32,32));
-            Image = ImageUtils.MergeBitmaps(images, 10)?.AsBitmapImage();
-
-            WeakEventManager<Assignment, PropertyChangedEventArgs>.AddHandler(model, nameof(Assignment.PropertyChanged), Assignment_Changed);
+            return ImageUtils.MergeBitmaps(images, 10)?.AsBitmapImage();
         }
 
         private static Column<Assignment>[] StartColumns = [
@@ -94,6 +120,29 @@ namespace PRSDesktop
             {
                 EmployeeChanged?.Invoke(this, new());
             }
+
+            if(SubjectColumns.Any(x => x.Property == e.PropertyName))
+            {
+                Subject = GetSubject();
+                OnPropertyChanged(nameof(Subject));
+            }
+            else if(e.PropertyName == nameof(Assignment.Description))
+            {
+                Notes = Model.Description;
+                OnPropertyChanged(nameof(Notes));
+            }
+            else if(e.PropertyName == $"{nameof(Assignment.ActivityLink)}.{nameof(Assignment.ActivityLink.Color)}")
+            {
+                UpdateColour();
+                OnPropertyChanged(nameof(Background));
+                OnPropertyChanged(nameof(Foreground));
+            }
+
+            if(ImageColumns.Any(x => x.Property == e.PropertyName))
+            {
+                Image = GetImage();
+                OnPropertyChanged(nameof(Image));
+            }
         }
 
         public event EventHandler<EventArgs>? EmployeeChanged;

+ 12 - 4
prs.desktop/Components/Calendar/Appointments/CalendarAppointment.cs

@@ -65,19 +65,27 @@ namespace PRSDesktop
         
         public T Model { get; }
 
-        public Brush Background { get; }
-        public Brush Foreground { get; }
+        public Brush Background { get; private set; }
+        public Brush Foreground { get; private set; }
 
         public abstract TimeSpan StartTime { get; }
         public abstract TimeSpan EndTime { get; }
         public abstract DateTime Date { get; }
 
+        private Func<T, string?> Colour;
+
         public CalendarAppointment(T model, Employee employee, Func<T, string?> color)
         {
             Model = model;
             Employee = employee;
-            
-            var c = color(model);
+
+            Colour = color;
+            UpdateColour();
+        }
+
+        protected void UpdateColour()
+        {
+            var c = Colour(Model);
             Color c2 = string.IsNullOrWhiteSpace(c)
                 ? Colors.White
                 : (Color)ColorConverter.ConvertFromString(c);

+ 40 - 27
prs.desktop/Components/Calendar/Calendar.xaml.cs

@@ -571,7 +571,7 @@ namespace PRSDesktop
 
         public CalendarConfigurationEvent? ConfigurationChanged;
         
-        public event CalendarDataEvent? CustomiseContextMenu;
+        public event CalendarDataMenuEvent? CustomiseContextMenu;
         
         public event CalendarDataEvent? SelectionChanged;
 
@@ -1089,6 +1089,32 @@ namespace PRSDesktop
             Calendar_BlockRightClicked(sender, e);
         }
 
+        public enum ContextMenuItems
+        {
+            Create,
+            Fill
+        }
+
+        public CalendarTimeSlot FillSlot(CalendarBlockEventArgs e, CalendarTimeSlot slot)
+        {
+            if(CalendarControl.GetEmptySpace(e.Point, out var start, out var end))
+            {
+                if(start is null || end is null)
+                {
+                    var block = GetFillBlock(e.Date, e.Column, CalendarControl.GetTime(e.Point));
+                    return new(slot.EmployeeID, e.Date, start ?? block?.Start ?? e.Start, end ?? block?.End ?? e.End);
+                }
+                else
+                {
+                    return new(slot.EmployeeID, e.Date, start.Value, end.Value);
+                }
+            }
+            else
+            {
+                return slot;
+            }
+        }
+
         private void Calendar_BlockRightClicked(object sender, CalendarBlockEventArgs e)
         {
             if(e.Value is AssignmentAppointment appointment)
@@ -1119,6 +1145,11 @@ namespace PRSDesktop
                                 time.Start = start ?? block?.Start ?? time.Start;
                                 time.Finish = end ?? block?.End ?? time.Finish;
                             }
+                            else
+                            {
+                                time.Start = start.Value;
+                                time.Finish = end.Value;
+                            }
                             Client.Save(appointment.Model, "Adjusted to fill time");
                         }
                     });
@@ -1143,7 +1174,7 @@ namespace PRSDesktop
                 e.Menu.AddItem("Zoom Out", null, ZoomOut);
                 e.Menu.AddItem("Reset Zoom", null, ResetZoom);
                 
-                CustomiseContextMenu?.Invoke(e.Menu, new CalendarDataEventArgs(appointment.Model));
+                CustomiseContextMenu?.Invoke(e.Menu, new CalendarDataMenuEventArgs(appointment.Model, e));
             }
             else if(e.Value is null)
             {
@@ -1151,33 +1182,15 @@ namespace PRSDesktop
 
                 var slot = new CalendarTimeSlot(employee.ID, e.Date, e.Start, e.End);
 
-                var createmenu = e.Menu.AddItem("Create...", null, null);
+                var createmenu = e.Menu.AddItem("Create...", null, null)
+                    .WithName($"Menu_{nameof(ContextMenuItems.Create)}");
                 createmenu.AddItem("New Assignment", null, slot, slot => CreateAssignment(slot));
                 createmenu.AddItem("New Meeting", null, slot, CreateMeeting);
 
-                CalendarTimeSlot FillSlot()
-                {
-                    if(CalendarControl.GetEmptySpace(e.Point, out var start, out var end))
-                    {
-                        if(start is null || end is null)
-                        {
-                            var block = GetFillBlock(e.Date, e.Column, CalendarControl.GetTime(e.Point));
-                            return new(employee.ID, e.Date, start ?? block?.Start ?? e.Start, end ?? block?.End ?? e.End);
-                        }
-                        else
-                        {
-                            return new(employee.ID, e.Date, start.Value, end.Value);
-                        }
-                    }
-                    else
-                    {
-                        return slot;
-                    }
-                }
-
-                var fillMenu = e.Menu.AddItem("Fill...", null, null);
-                fillMenu.AddItem("New Assignment", null, () => CreateAssignment(FillSlot()));
-                fillMenu.AddItem("New Meeting", null, () => CreateMeeting(FillSlot()));
+                var fillMenu = e.Menu.AddItem("Fill...", null, null)
+                    .WithName($"Menu_{nameof(ContextMenuItems.Fill)}");
+                fillMenu.AddItem("New Assignment", null, () => CreateAssignment(FillSlot(e, slot)));
+                fillMenu.AddItem("New Meeting", null, () => CreateMeeting(FillSlot(e, slot)));
 
                 if (_copiedmodel != null)
                 {
@@ -1190,7 +1203,7 @@ namespace PRSDesktop
                 e.Menu.AddItem("Zoom Out", null, ZoomOut);
                 e.Menu.AddItem("Reset Zoom", null, ResetZoom);
 
-                CustomiseContextMenu?.Invoke(e.Menu, new CalendarDataEventArgs(slot));
+                CustomiseContextMenu?.Invoke(e.Menu, new CalendarDataMenuEventArgs(slot, e));
             }
         }
         

+ 9 - 0
prs.desktop/Components/Calendar/Events/CalendarDataEvent.cs

@@ -1,3 +1,4 @@
+using InABox.Wpf;
 using System;
 
 namespace PRSDesktop
@@ -12,6 +13,14 @@ namespace PRSDesktop
     {
         public object? Item { get; } = item;
     }
+    
+    public class CalendarDataMenuEventArgs(object? item, CalendarBlockEventArgs args) : EventArgs, ICalendarDataEventArgs
+    {
+        public object? Item { get; } = item;
+
+        public CalendarBlockEventArgs Args { get; } = args;
+    }
 
     public delegate void CalendarDataEvent(object sender, ICalendarDataEventArgs args);
+    public delegate void CalendarDataMenuEvent(object sender, CalendarDataMenuEventArgs args);
 }

+ 38 - 20
prs.desktop/Panels/DailyReports/DailyReport.xaml.cs

@@ -387,37 +387,57 @@ namespace PRSDesktop
         
         public event TimeSheetConfirmedEvent OnTimeSheetConfirmed;
         
-        private void PopulateFavourites(ItemsControl menu, CalendarTimeSlot slot, bool filltime)
+        private void PopulateFavourites(ItemsControl parent, MenuItem item, CalendarBlockEventArgs e, CalendarTimeSlot slot, bool fillTime)
         {
+            var index = parent.Items.IndexOf(item);
             
-            menu.Items.RemoveAt(0);
-            var create = new MenuItem { Header = "Create New Assignment" };
-            create.Click += (o, e) => CreateNewAssignment(slot, null);
-            menu.Items.Insert(0,create);
+            parent.Items.RemoveAt(index);
+
+            CalendarTimeSlot GetSlot() => fillTime ? Calendar.FillSlot(e, slot) : slot;
+
+            var hasFavourites = _settings.Favourites?.Any() == true;
+
+            var create = parent.AddMenuItem(
+                hasFavourites
+                ? fillTime ? "Fill" : "Create"
+                : fillTime ? "Fill Time" : "Create New Assignment",
+                null, () => CreateNewAssignment(GetSlot(), null), index: index);
             
-            if (_settings.Favourites?.Any() == true)
+            if (hasFavourites)
             {
-                menu.Items.Insert(1,new Separator());
-                int i = 2;
-                foreach (var favourite in _settings.Favourites)
+                create.AddItem("New Assignment", null, () => CreateNewAssignment(GetSlot(), null));
+                create.AddSeparator();
+                foreach (var favourite in _settings.Favourites!)
                 {
-                    var fav = new MenuItem { Header = favourite.Title };
-                    fav.Click += (o, e) => CreateNewAssignment(slot, favourite);
-                    menu.Items.Insert(i,fav);
-                    i++;
+                    create.AddMenuItem(favourite.Title, null, () => CreateNewAssignment(GetSlot(), favourite));
                 }
             }
         }
+        private void PopulateFavourites(ItemsControl menu, CalendarTimeSlot slot, CalendarBlockEventArgs e)
+        {
+            var createItem = menu.FindMenuItem($"Menu_{nameof(Calendar.ContextMenuItems.Create)}");
+            if (createItem is not null && createItem.Parent is ItemsControl createParent)
+            {
+                PopulateFavourites(createParent, createItem, e, slot, false);
+            }
+
+            var fillItem = menu.FindMenuItem($"Menu_{nameof(Calendar.ContextMenuItems.Fill)}");
+            if(fillItem is not null && fillItem.Parent is ItemsControl fillParent)
+            {
+                fillParent.AddMenuSeparatorIfNeeded(index: fillParent.Items.IndexOf(fillItem));
+                PopulateFavourites(fillParent, fillItem, e, slot, true);
+            }
+        }
         
         
-        private void Assignments_OnCustomiseContextMenu(object sender, ICalendarDataEventArgs args)
+        private void Assignments_OnCustomiseContextMenu(object sender, CalendarDataMenuEventArgs args)
         {
             if (sender is not ContextMenu menu)
                 return;
             
             if (args.Item is CalendarTimeSlot slot)
             {
-                PopulateFavourites(menu, slot, false);
+                PopulateFavourites(menu, slot, args.Args);
             }
             else if (args.Item is Assignment assignment)
             {
@@ -493,10 +513,10 @@ namespace PRSDesktop
 
         private void CreateNewAssignment(CalendarTimeSlot slot, AssignmentFavourite? favourite)
         {
-            CalendarDataEvent populate = (sender, args) => PopulateFavourite(args.Item as Assignment, favourite);
-            Calendar.ItemCreated += populate;
+            void Populate(object sender, ICalendarDataEventArgs args) => PopulateFavourite(args.Item as Assignment, favourite);
+            Calendar.ItemCreated += Populate;
             var ass = Calendar.CreateAssignment(slot);
-            Calendar.ItemCreated -= populate;
+            Calendar.ItemCreated -= Populate;
             if(ass is not null)
             {
                 SelectAssignment(ass);
@@ -700,8 +720,6 @@ namespace PRSDesktop
                             Logger.Send(LogType.Error, "", String.Format("Error Updating Assignment: {0}\n{1}", e.Message, e.StackTrace));
                     }
                 );
-
-                // TODO: Calendar.UpdateAssignment(SelectedAssignment);
             }
         }