Browse Source

Replaced Calendar syncfusion with CalendarControl

Kenric Nugteren 1 month ago
parent
commit
d930ce3d64

+ 5 - 6
prs.classes/Utilities/RosterUtils.cs

@@ -51,7 +51,7 @@ namespace Comal.Classes
             return result.ToArray();
         }
 
-        public static EmployeeRosterItem? GetRoster(IList<EmployeeRosterItem>? roster, DateTime? startdate, DateTime currentdate)
+        public static EmployeeRosterItem? GetRoster(IList<EmployeeRosterItem>? roster, DateTime startdate, DateTime currentdate)
         {
             if (startdate > currentdate)
                 return null;
@@ -59,15 +59,14 @@ namespace Comal.Classes
             if ((roster == null) || !roster.Any())
                 roster = DefaultRoster();
 
-            if ((startdate == null) ||  startdate.Value.IsEmpty())
+            if (startdate.IsEmpty())
                 startdate = currentdate.StartOfWeek(DayOfWeek.Monday);
             
-            while (startdate.Value.AddDays(roster.Count) <= currentdate)
-                startdate = startdate.Value.AddDays(roster.Count);                
+            while (startdate.AddDays(roster.Count) <= currentdate)
+                startdate = startdate.AddDays(roster.Count);                
             
-            int rosterday = (int)((currentdate.Date - startdate.Value.Date).TotalDays) % roster.Count;
+            int rosterday = (int)((currentdate.Date - startdate.Date).TotalDays) % roster.Count;
             return roster[rosterday];
-            
         }
         
         

+ 36 - 30
prs.desktop/Components/Calendar/Appointments/AssignmentAppointment.cs

@@ -3,54 +3,60 @@ using System.Collections.Generic;
 using System.Drawing;
 using System.Windows.Media.Imaging;
 using Comal.Classes;
+using Geocoding;
 using InABox.Core;
 using InABox.WPF;
 
 namespace PRSDesktop
 {
-    public class AssignmentAppointment : CalendarAppointment<AssignmentModel>
+    public class AssignmentAppointment : CalendarAppointment<Assignment>
     {
+        public CalendarAssignmentType AssignmentType { get; }
+
+        public override TimeSpan StartTime => AssignmentType switch
+        {
+            CalendarAssignmentType.Booked => Model.Booked.Start,
+            CalendarAssignmentType.Actual => Model.Actual.Start,
+            _ => Model.EffectiveStartTime()
+        };
+
+        public override TimeSpan EndTime => AssignmentType switch
+        {
+            CalendarAssignmentType.Booked => Model.Booked.Finish,
+            CalendarAssignmentType.Actual => Model.Actual.Finish,
+            _ => Model.EffectiveFinishTime()
+        };
+
+        public override DateTime Date => Model.Date;
         
-        public AssignmentAppointment(AssignmentModel model, Func<AssignmentModel?,Guid> employeeid, Func<AssignmentModel?,String> color, CalendarAssignmentType type) : base(model, employeeid, color)
+        public AssignmentAppointment(Assignment model, Employee employee, CalendarAssignmentType type)
+            : base(model, employee, x => x.ActivityLink.Color)
         {
+            AssignmentType = type;
             
-            StartTime = type switch
-            {
-                CalendarAssignmentType.Booked => Model.Date.Add(Model.BookedStart),
-                CalendarAssignmentType.Actual => Model.Date.Add(Model.ActualStart),
-                _ => Model.Date.Add(Model.EffectiveStart()),
-            };
-            
-            EndTime = type switch
-            {
-                CalendarAssignmentType.Booked => Model.Date.Add(Model.BookedFinish),
-                CalendarAssignmentType.Actual => Model.Date.Add(Model.ActualFinish),
-                _ => Model.Date.Add(Model.EffectiveFinish()),
-            };
-            
-            Notes = Model.Notes;
+            Notes = Model.Description;
             
             var subject = new List<string>() { model.Number.ToString() };
-            if (model.JobID != Guid.Empty)
+            if (model.JobLink.ID != Guid.Empty)
                 subject.Add(
-                    model.ItpID != Guid.Empty
-                        ? $"{model.JobNumber}-{model.ItpCode}"
-                        : $"{model.JobNumber}"
+                    model.ITP.ID != Guid.Empty
+                        ? $"{model.JobLink.JobNumber}-{model.ITP.Code}"
+                        : $"{model.JobLink.JobNumber}"
                 );
-            if (model.TaskID  != Guid.Empty)
-                subject.Add($"Task {model.TaskNumber}");
-            if (model.MeetingID  != Guid.Empty)
-                subject.Add($"Mtg {model.MeetingNumber}");
+            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.Subject ?? "");
-            Subject = String.Join(" ", subject);
+            subject.Add(model.Title ?? "");
+            Subject = string.Join(" ", subject);
 
-            List<Bitmap> images = new List<Bitmap>();
+            var images = new List<Bitmap>();
             if (!model.Completed.IsEmpty())
                 images.Add(Resources.tick_sml.Resize(32,32));
-            if (model.DeliveryID != Guid.Empty)
+            if (model.Delivery.ID != Guid.Empty)
                 images.Add(Resources.box_sml.Resize(32,32));
-            if (model.MeetingID != Guid.Empty)
+            if (model.Meeting.Link.ID != Guid.Empty)
                 images.Add(Resources.employees.Resize(32,32));
             Image = ImageUtils.MergeBitmaps(images, 10)?.AsBitmapImage();
         }

+ 35 - 23
prs.desktop/Components/Calendar/Appointments/CalendarAppointment.cs

@@ -2,6 +2,7 @@ using System;
 using System.Collections.ObjectModel;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
+using Comal.Classes;
 using InABox.WPF;
 using PropertyChanged;
 using Syncfusion.UI.Xaml.Scheduler;
@@ -12,53 +13,64 @@ namespace PRSDesktop
     public interface ICalendarAppointment
     {
         // object Id { get; }
-        // String? Subject { get; }
-        // String? Notes { get; }
+
+        Brush Background { get; }
+        Brush Foreground { get; }
+
+        string? Subject { get; }
+        string? Notes { get; }
         // ObservableCollection<object> ResourceIdCollection { get; }
         // DateTime StartTime { get; }
         // DateTime EndTime { get; }
-        // Brush Foreground { get; }
-        // Brush AppointmentBackground { get; }
         
         BitmapImage? Image { get; }
         object Model { get; }
+
+        Employee Employee { get; }
+
+        TimeSpan StartTime { get; }
+        TimeSpan EndTime { get; }
+        DateTime Date { get; }
     }
     
-    public interface ICalendarAppointment<T> : ICalendarAppointment
+    public interface ICalendarAppointment<T> : ICalendarAppointment where T : notnull
     {
-        T Model { get; }
+        new T Model { get; }
+
+        object ICalendarAppointment.Model => Model;
     }
     
     [DoNotNotify]
-    public abstract class CalendarAppointment<T> : ScheduleAppointment, ICalendarAppointment<T> where T : IModel
+    public abstract class CalendarAppointment<T> : ICalendarAppointment<T> where T : notnull
     {
-        //public object Id { get; set; }
-        // public ObservableCollection<object> ResourceIdCollection { get; set; }
-        //public Brush Foreground { get; set; }
-        // public Brush AppointmentBackground { get; set; }
-        //
-        // public abstract DateTime StartTime { get; set; }
-        // public abstract DateTime EndTime { get; set; }
-        // public abstract string? Subject { get; set; }
-        // public abstract string? Notes { get; set; }
+        public Employee Employee { get; set; }
 
         public BitmapImage? Image { get; set; }
+
+        public string? Subject { get; set; }
+
+        public string? Notes { get; set; }
         
         public T Model { get; }
-        object ICalendarAppointment.Model => Model;
-        
-        public CalendarAppointment(T model, Func<T?,Guid> employeeid, Func<T?,String> color)
+
+        public Brush Background { get; }
+        public Brush Foreground { get; }
+
+        public abstract TimeSpan StartTime { get; }
+        public abstract TimeSpan EndTime { get; }
+        public abstract DateTime Date { get; }
+
+        public CalendarAppointment(T model, Employee employee, Func<T, string?> color)
         {
             Model = model;
-            Id = model.ID;
-            ResourceIdCollection = new ObservableCollection<object>() { employeeid(model).ToString() };
+            Employee = employee;
             
-            String c = color(model);
+            var c = color(model);
             Color c2 = string.IsNullOrWhiteSpace(c)
                 ? Colors.White
                 : (Color)ColorConverter.ConvertFromString(c);
             
-            AppointmentBackground = new SolidColorBrush(c2);
+            Background = new SolidColorBrush(c2);
             Foreground = new SolidColorBrush(ImageUtils.GetForegroundColor(c2));
         }
         

+ 11 - 11
prs.desktop/Components/Calendar/Appointments/LeaveRequestAppointment.cs

@@ -6,20 +6,20 @@ using PRS.Shared;
 
 namespace PRSDesktop
 {
-    public class LeaveRequestAppointment : CalendarAppointment<LeaveRequestModel>
+    public class LeaveRequestAppointment : CalendarAppointment<LeaveRequest>
     {
-        
-        // public override DateTime StartTime { get; set; }
-        // public override DateTime EndTime { get; set; }
-        // public override string? Subject { get; set; }
-        // public override string? Notes { get; set; }
-        // public override BitmapImage? Image  { get; set; }
+        public RosterBlock Block { get; }
+
+        public override TimeSpan StartTime => Block.Start;
+        public override TimeSpan EndTime => Block.Finish;
 
-        public LeaveRequestAppointment(LeaveRequestModel model, Func<LeaveRequestModel?, Guid> employeeid, Func<LeaveRequestModel?, string> color, RosterBlock block) : base(model, employeeid, color)
+        public override DateTime Date => Block.Date;
+        
+        public LeaveRequestAppointment(LeaveRequest model, Employee employee, RosterBlock block) : base(model, employee, x => x.LeaveType.Color)
         {
-            StartTime = block.Date.Add(block.Start);
-            EndTime = block.Date.Add(block.Finish);
-            Subject = Model.Subject;
+            Block = block;
+
+            Subject = Model.LeaveType.Description;
             Notes = Model.Notes;
             Image = Resources.lock_sml.AsBitmapImage(32, 32);
         }

+ 11 - 10
prs.desktop/Components/Calendar/Appointments/StandardLeaveAppointment.cs

@@ -6,20 +6,21 @@ using PRS.Shared;
 
 namespace PRSDesktop
 {
-    public class StandardLeaveAppointment : CalendarAppointment<StandardLeaveModel>
+    public class StandardLeaveAppointment : CalendarAppointment<StandardLeave>
     {
+        public RosterBlock Block { get; }
 
-        // public override DateTime StartTime { get; set; }
-        // public override DateTime EndTime { get; set; }
-        // public override string? Subject { get; set; }
-        // public override string? Notes { get; set; }
-        // public override BitmapImage? Image { get; set; }
+        public override TimeSpan StartTime => Block.Start;
+        public override TimeSpan EndTime => Block.Finish;
+
+        public override DateTime Date => Block.Date;
         
-        public StandardLeaveAppointment(StandardLeaveModel model, Func<StandardLeaveModel?, Guid> employeeid, Func<StandardLeaveModel?, string> color, RosterBlock block) : base(model, employeeid, color)
+        public StandardLeaveAppointment(StandardLeave leave, Employee employee, RosterBlock block)
+            : base(leave, employee, x => x.LeaveType.Color)
         {
-            StartTime = block.Date.Add(block.Start);
-            EndTime = block.Date.Add(block.Finish);
-            Subject = Model.Subject;
+            Block = block;
+
+            Subject = Model.LeaveType.Description;
             Notes = "";
             Image = Resources.lock_sml.AsBitmapImage(32, 32);
         }

+ 10 - 7
prs.desktop/Components/Calendar/Appointments/TimeSheetAppointment.cs

@@ -2,12 +2,13 @@ using System;
 using System.Collections.Generic;
 using System.Drawing;
 using System.Windows.Media.Imaging;
+using Comal.Classes;
 using InABox.Core;
 using InABox.WPF;
 
 namespace PRSDesktop
 {
-    public class TimeSheetAppointment : CalendarAppointment<TimeSheetModel>
+    public class TimeSheetAppointment : CalendarAppointment<TimeSheet>
     {
 
         // public override DateTime StartTime { get; set; }
@@ -15,15 +16,17 @@ namespace PRSDesktop
         // public override string? Notes { get; set; }
         public BitmapImage? Image { get; set; }
         // public override string? Subject { get; set; }
+
+        public override TimeSpan StartTime => Model.Approved.IsEmpty() ? Model.Start : Model.ApprovedStart;
+        public override TimeSpan EndTime => Model.Approved.IsEmpty() ? Model.Finish : Model.ApprovedFinish;
+
+        public override DateTime Date => Model.Date;
         
-        public TimeSheetAppointment(TimeSheetModel model, Func<TimeSheetModel?,Guid> employeeid, Func<TimeSheetModel?,String> color) : base(model, employeeid, color)
+        public TimeSheetAppointment(TimeSheet model, Employee employee, Func<TimeSheetModel, String> color) : base(model, employee, x => x.ActivityLink.Color)
         {
-
-            StartTime = Model.Date.Add(Model.Approved.IsEmpty() ? Model.Start : Model.ApprovedStart);
-            EndTime = Model.Date.Add(Model.Approved.IsEmpty() ? Model.Finish : Model.ApprovedFinish);
             Notes = Model.Notes;
-            Subject = Model.Subject;
-            List<Bitmap> images = new List<Bitmap>();
+            Subject = Model.ActivityLink.Description;
+            var images = new List<Bitmap>();
             
             if (!model.Approved.IsEmpty())
                 images.Add(Resources.tick_sml.Resize(32,32));

+ 53 - 5
prs.desktop/Components/Calendar/Calendar.xaml

@@ -4,9 +4,11 @@
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:local="clr-namespace:PRSDesktop"
+             xmlns:classes="clr-namespace:Comal.Classes"
              xmlns:wpf="clr-namespace:InABox.Wpf;assembly=InABox.Wpf"
              xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
              xmlns:dynamicGrid="clr-namespace:InABox.DynamicGrid;assembly=InABox.Wpf"
+             xmlns:system="clr-namespace:System;assembly=System.Runtime.InteropServices"
              mc:Ignorable="d"
              d:DesignHeight="600" d:DesignWidth="800" SizeChanged="Calendar_OnSizeChanged"
              Name="Main">
@@ -58,15 +60,62 @@
                                   Stroke="Black"
                                   StrokeThickness="1"/>
                     </Button>
-                    <DatePicker DockPanel.Dock="Left"/>
+                    <DatePicker DockPanel.Dock="Left"
+                                SelectedDate="{Binding ElementName=Main,Path=SelectedDate}"/>
                     <Button DockPanel.Dock="Right"
                             Content="Today"
                             MinHeight="25"
                             Margin="4,0,0,0"/>
                 </DockPanel>
-                <wpf:CalendarControl Name="Calendar"
-                                     Grid.Row="1">
-                    
+                <wpf:CalendarControl Name="CalendarControl"
+                                     RowHeight="0"
+                                     MinimumColumnWidth="75"
+                                     Grid.Row="1"
+                                     BlockClicked="Calendar_BlockClicked"
+                                     BlockHeld="Calendar_BlockHeld"
+                                     BlockRightClicked="Calendar_BlockRightClicked"
+                                     ColumnMapping="{Binding Employee}"
+                                     DateMapping="{Binding Date}"
+                                     StartTimeMapping="{Binding StartTime}"
+                                     EndTimeMapping="{Binding EndTime}">
+                    <wpf:CalendarControl.DateTemplate>
+                        <DataTemplate DataType="system:DateTime">
+                            <StackPanel Background="WhiteSmoke"
+                                        Margin="0"
+                                        VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
+                                        Orientation="Vertical">
+                                <Label HorizontalContentAlignment="Center" VerticalContentAlignment="Bottom"
+                                       FontSize="12" FontFamily="Arial" FontWeight="Bold"
+                                       Foreground="Black"
+                                       Margin="0,0,0,-5"
+                                       Content="{Binding Converter={x:Static local:Calendar.DayOfWeekConverter}}"/>
+                                <Label HorizontalContentAlignment="Center" VerticalContentAlignment="Top"
+                                       FontSize="10"
+                                       Content="{Binding StringFormat='dd MMM yy'}"/>
+                            </StackPanel>
+                        </DataTemplate>
+                    </wpf:CalendarControl.DateTemplate>
+                    <wpf:CalendarControl.HeaderTemplate>
+                        <DataTemplate DataType="classes:Employee">
+                            <Border Background="White"
+                                    Height="50">
+                                <TextBlock VerticalAlignment="Center"
+                                           HorizontalAlignment="Stretch"
+                                           TextAlignment="Center"
+                                           Tag="{Binding}"
+                                           SizeChanged="TextBlock_SizeChanged"/>
+                            </Border>
+                        </DataTemplate>
+                    </wpf:CalendarControl.HeaderTemplate>
+                    <wpf:CalendarControl.ItemTemplate>
+                        <DataTemplate DataType="local:ICalendarAppointment">
+                            <Border BorderBrush="Black" BorderThickness="1"
+                                    Margin="2" Padding="2" CornerRadius="2"
+                                    Background="{Binding Background}">
+                                <local:CalendarBlock DataContext="{Binding}" />
+                            </Border>
+                        </DataTemplate>
+                    </wpf:CalendarControl.ItemTemplate>
                 </wpf:CalendarControl>
             </Grid>
             <!--local:SfScheduler2
@@ -180,7 +229,6 @@
                         x:Name="CalendarViewSelector" 
                         DockPanel.Dock="Left" 
                         SelectedValue="{Binding CalendarView, ElementName=Main}"
-                        SelectionChanged="CalendarViewSelector_SelectionChanged"
                         VerticalContentAlignment="Center" 
                         SelectedIndex="-1"
                         Margin="5,0,0,0"/>

File diff suppressed because it is too large
+ 317 - 333
prs.desktop/Components/Calendar/Calendar.xaml.cs


+ 10 - 12
prs.desktop/Components/Calendar/CalendarTimeSlot.cs

@@ -1,16 +1,14 @@
 using System;
 
-namespace PRSDesktop
+namespace PRSDesktop;
+
+public class CalendarTimeSlot(Guid employeeid, DateTime date, TimeSpan start, TimeSpan end)
 {
-    public class CalendarTimeSlot
-    {
-        public CalendarTimeSlot(Guid employeeid, DateTime time)
-        {
-            EmployeeID = employeeid;
-            Time = time;
-        }
-        
-        public Guid EmployeeID { get; }
-        public DateTime Time { get; }
-    }
+    public Guid EmployeeID { get; } = employeeid;
+
+    public DateTime Date { get; } = date;
+
+    public TimeSpan Start { get; } = start;
+
+    public TimeSpan End { get; } = end;
 }

+ 5 - 10
prs.desktop/Components/Calendar/Events/CalendarDataEvent.cs

@@ -5,7 +5,7 @@ namespace PRSDesktop
     
     public interface ICalendarDataEventArgs
     {
-        object Item { get; }
+        object? Item { get; }
     }
     
     public interface ICalendarDataEventArgs<T>
@@ -13,18 +13,13 @@ namespace PRSDesktop
         T? Item { get; }
     }
     
-    public class CalendarDataEventArgs<T> : EventArgs, ICalendarDataEventArgs<T>, ICalendarDataEventArgs
+    public class CalendarDataEventArgs<T>(T item) : EventArgs, ICalendarDataEventArgs<T>, ICalendarDataEventArgs
     {
-        public T? Item { get; }
+        public T Item { get; } = item;
 
-        object ICalendarDataEventArgs.Item => Item;
-
-        public CalendarDataEventArgs(T? item)
-        {
-            Item = item;
-        }
+        object? ICalendarDataEventArgs.Item => Item;
     }
-    
+
     public delegate void CalendarDataEvent(object sender, ICalendarDataEventArgs args);
     
 }

+ 6 - 5
prs.desktop/Components/EmployeeSelector/EmployeeSelector.xaml.cs

@@ -105,14 +105,15 @@ namespace PRSDesktop
             var rows = _employees.Rows.Where(r => empids.Contains(r.Get<Employee, Guid>(c => c.ID)));
             foreach (var row in rows)
             {
-                if(!_rosters.TryGetValue(row.Get<Employee, Guid>(x => x.ID), out var rosters))
-                {
-                    rosters = Array.Empty<EmployeeRosterItem>();
-                }
-                result.Add(transform.Invoke(row, rosters));
+                result.Add(transform.Invoke(row, GetRoster(row.Get<Employee, Guid>(x => x.ID))));
             }
             return result.ToArray();
         }
+
+        public EmployeeRosterItem[] GetRoster(Guid employeeID)
+        {
+            return _rosters.GetValueOrDefault(employeeID) ?? [];
+        }
         
         public EmployeeSelector()
         {

+ 31 - 47
prs.desktop/Panels/DailyReports/DailyReport.xaml.cs

@@ -387,13 +387,12 @@ namespace PRSDesktop
         
         public event TimeSheetConfirmedEvent OnTimeSheetConfirmed;
         
-        private void PopulateFavourites(ItemsControl menu, RoutedEventHandler action, DateTime time, bool filltime)
+        private void PopulateFavourites(ItemsControl menu, CalendarTimeSlot slot, bool filltime)
         {
             
             menu.Items.RemoveAt(0);
             var create = new MenuItem { Header = "Create New Assignment" };
-            create.Tag = new Tuple<DateTime, AssignmentFavourite?>(time, null);
-            create.Click += action;
+            create.Click += (o, e) => CreateNewAssignment(slot, null);
             menu.Items.Insert(0,create);
             
             if (_settings.Favourites?.Any() == true)
@@ -403,8 +402,7 @@ namespace PRSDesktop
                 foreach (var favourite in _settings.Favourites)
                 {
                     var fav = new MenuItem { Header = favourite.Title };
-                    fav.Tag = new Tuple<DateTime, AssignmentFavourite?>(time, favourite);
-                    fav.Click += action;
+                    fav.Click += (o, e) => CreateNewAssignment(slot, favourite);
                     menu.Items.Insert(i,fav);
                     i++;
                 }
@@ -419,9 +417,9 @@ namespace PRSDesktop
             
             if (args is CalendarDataEventArgs<CalendarTimeSlot> slot)
             {
-                PopulateFavourites(menu, CreateAssignment_Click, slot.Item.Time, false);
+                PopulateFavourites(menu, slot.Item, false);
             }
-            else if (args is CalendarDataEventArgs<AssignmentModel> model)
+            else if (args is CalendarDataEventArgs<Assignment> model)
             {
                 menu.Items.Insert(1,new Separator());
                 var SetAsFavouriteMenu = new MenuItem { Header = GetFavourite(model.Item) == null ? "Set As Favourite" : "Update Favourite"};
@@ -439,12 +437,12 @@ namespace PRSDesktop
         }
         
 
-        private AssignmentFavourite? GetFavourite(AssignmentModel? model)
+        private AssignmentFavourite? GetFavourite(Assignment? model)
         {
-            return model == null ? null : _settings.Favourites.FirstOrDefault(x => string.Equals(x.Title, model.Subject));
+            return model == null ? null : _settings.Favourites.FirstOrDefault(x => string.Equals(x.Title, model.Title));
         }
 
-        private void SetAsFavourite(AssignmentModel? model)
+        private void SetAsFavourite(Assignment? model)
         {
             if (model == null)
             {
@@ -457,17 +455,17 @@ namespace PRSDesktop
             if (favourite == null)
             {
                 bCreated = true;
-                favourite = new AssignmentFavourite { Title = model.Subject };
+                favourite = new AssignmentFavourite { Title = model.Title };
                 _settings.Favourites.Add(favourite);
             }
 
-            favourite.JobID = model.JobID;
-            favourite.JobNumber = model.JobNumber;
-            favourite.ITPID = model.ItpID;
-            favourite.ITPCode = model.ItpCode;
-            favourite.ActivityID = model.ActivityID;
-            favourite.ActivityColor = model.Color;
-            favourite.ActivityName = model.ActivityCode;
+            favourite.JobID = model.JobLink.ID;
+            favourite.JobNumber = model.JobLink.JobNumber;
+            favourite.ITPID = model.ITP.ID;
+            favourite.ITPCode = model.ITP.Code;
+            favourite.ActivityID = model.ActivityLink.ID;
+            favourite.ActivityColor = model.ActivityLink.Color;
+            favourite.ActivityName = model.ActivityLink.Code;
             new UserConfiguration<DailyActivityScreenSettings>().Save(_settings);
 
             MessageBox.Show(bCreated ? "Favourite Created!" : "Favourite Updated!");
@@ -493,21 +491,16 @@ namespace PRSDesktop
             //UpdateDayButtons();
         }
 
-        private void CreateAssignment_Click(object sender, RoutedEventArgs e)
-        {
-            var fav = (sender as MenuItem)?.Tag as Tuple<DateTime, AssignmentFavourite?>;
-            var start = fav != null ? fav.Item1.TimeOfDay : Calendar.SelectedDate.TimeOfDay;
-            CreateNewAssignment(start, fav?.Item2);
-        }
-
-        private void CreateNewAssignment(TimeSpan start, AssignmentFavourite? favourite)
+        private void CreateNewAssignment(CalendarTimeSlot slot, AssignmentFavourite? favourite)
         {
             CalendarDataEvent populate = (sender, args) => PopulateFavourite(args.Item as Assignment, favourite);
             Calendar.ItemCreated += populate;
-            var ass = Calendar.CreateAssignment(new CalendarTimeSlot(Employee.ID, Calendar.SelectedDate.Add(start)));
+            var ass = Calendar.CreateAssignment(slot);
             Calendar.ItemCreated -= populate;
-            SelectAssignment(ass);
-
+            if(ass is not null)
+            {
+                SelectAssignment(ass);
+            }
         }
 
         private void PopulateFavourite(Assignment? assignment, AssignmentFavourite? favourite)
@@ -708,7 +701,7 @@ namespace PRSDesktop
                     }
                 );
 
-                Calendar.UpdateAssignment(SelectedAssignment);
+                // TODO: Calendar.UpdateAssignment(SelectedAssignment);
             }
         }
 
@@ -936,28 +929,19 @@ namespace PRSDesktop
         private void ConfirmTimesheet_Click(object sender, RoutedEventArgs e)
         {
             var bBlankActivities = false;
-            var bOverlapping = true;
+            var bOverlapping = false;
 
-            var rows = Calendar.GetAssignments(Employee.ID, DatePicker.SelectedDate.Value);
+            var rows = Calendar.GetAssignments(Employee.ID, Calendar.SelectedDate);
             foreach (var row in rows)
             {
-                var id = row.Get<Assignment, Guid>(c => c.ID);
-                var date = row.Get<Assignment, DateTime>(c => c.Date);
-                var start = row.Get<Assignment, TimeSpan>(c => c.Actual.Start);
-                var finish = row.Get<Assignment, TimeSpan>(c => c.Actual.Finish);
-                if (rows.Any(r =>
-                        r.Get<Assignment, Guid>(c => c.ID) != id
-                        && r.Get<Assignment, DateTime>(c => c.Date) == date
-                        && r.Get<Assignment, TimeSpan>(c => c.Actual.Finish) > start
-                        && r.Get<Assignment, TimeSpan>(c => c.Actual.Start) < finish
-                    ))
-                    bOverlapping = false;
-
-                if (Security.IsAllowed<RequireActivityCodesOnDailyReports>())
-                    bBlankActivities = rows.Any(r => !Entity.IsEntityLinkValid<Assignment, AssignmentActivityLink>(x => x.ActivityLink, r));
+                bOverlapping = bOverlapping
+                    || rows.Any(x => x.ID != row.ID && x.Date == row.Date && x.Actual.Finish > row.Actual.Start && x.Actual.Start < row.Actual.Finish);
             }
 
-            if (!bOverlapping)
+            if (Security.IsAllowed<RequireActivityCodesOnDailyReports>())
+                bBlankActivities = rows.Any(x => x.ActivityLink.ID == Guid.Empty);
+
+            if (bOverlapping)
             {
                 MessageBox.Show("This report contains overlapping blocks!\n\nPlease correct before confirming this timesheet.");
                 return;

+ 1 - 1
prs.desktop/Panels/Delivery/DeliveryPanel.xaml.cs

@@ -300,7 +300,7 @@ namespace PRSDesktop
                         item.Header = description;
                         item.Click += (o,e) =>
                         {
-                            if (Deliveries.CreateBooking(row, slot.Item.EmployeeID, slot.Item.Time))
+                            if (Deliveries.CreateBooking(row, slot.Item.EmployeeID, slot.Item.Date + slot.Item.Start))
                                 Refresh();
                         };
                         CreateBooking.Items.Add(item);

+ 1 - 1
prs.desktop/Panels/LeaveRequests/LeaveCalendar.xaml.cs

@@ -77,7 +77,7 @@ public class LeaveBackgroundConverter : IValueConverter
             if ( (!tuple.Item2.IsEmpty() && (tuple.Item2 > val.Date)) || (!tuple.Item3.IsEmpty() && (tuple.Item3 < val.Date)))
                 return new SolidColorBrush(System.Windows.Media.Colors.LightGray) { Opacity = 0.8 };
                 
-            var roster = RosterUtils.GetRoster(tuple?.Item4, tuple?.Item5, val.Date);
+            var roster = RosterUtils.GetRoster(tuple.Item4, tuple.Item5, val.Date);
             return (roster?.Enabled == true)
                 ? roster?.Duration < 5.0F
                     ? new System.Windows.Media.LinearGradientBrush(

+ 1 - 1
prs.shared/Posters/Timberline/TimesheetTimberlinePoster.cs

@@ -698,7 +698,7 @@ public class Module
                 // Find the roster data.
                 var employee = employees.GetValueOrDefault(key.Employee);
                 var employeeRosters = rosters.GetValueOrDefault(employee != null ? employee.ID : Guid.Empty);
-                var overtimeID = RosterUtils.GetRoster(employeeRosters, employee?.RosterStart, key.Date)?.Overtime.ID ?? Guid.Empty;
+                var overtimeID = RosterUtils.GetRoster(employeeRosters, employee?.RosterStart ?? DateTime.MinValue, key.Date)?.Overtime.ID ?? Guid.Empty;
 
                 // Split up the paid work blocks by the overtime and assign PayrollIDs.
                 var blockItems = EvaluateOvertime(blocks, overtimeID);

Some files were not shown because too many files changed in this diff