using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Threading; using com.sun.jmx.mbeanserver; using Comal.Classes; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF; using Syncfusion.UI.Xaml.Scheduler; using Action = System.Action; using SelectionChangedEventArgs = System.Windows.Controls.SelectionChangedEventArgs; namespace PRSDesktop { public partial class AssignmentView2 : UserControl { #region Private Fields private class AssignmentViewModel : ScheduleAppointment, IAssignmentViewModel { public Guid AssignmentID { get; set; } public Guid EmployeeID { get; set; } public Brush AppointmentForeground { get; set; } public int Number { get; set; } public string JobNumber { get; set; } public BitmapImage Completed { get; set; } public BitmapImage HasDelivery { get; set; } public BitmapImage Locked { get; set; } public BitmapImage TimeSheet { get; set; } } private readonly BitmapImage back = PRSDesktop.Resources.back.AsBitmapImage(32, 32); private readonly BitmapImage box = PRSDesktop.Resources.box_sml.AsBitmapImage(32, 32); private readonly BitmapImage first = PRSDesktop.Resources.first.AsBitmapImage(32, 32); private readonly BitmapImage last = PRSDesktop.Resources.last.AsBitmapImage(32, 32); private readonly BitmapImage locked = PRSDesktop.Resources.lock_sml.AsBitmapImage(32, 32); private readonly BitmapImage next = PRSDesktop.Resources.next.AsBitmapImage(32, 32); private readonly BitmapImage tick = PRSDesktop.Resources.tick_sml.AsBitmapImage(32, 32); private readonly BitmapImage timesheet = PRSDesktop.Resources.clock_sml.AsBitmapImage(32, 32); private bool bReady = false; private Dictionary _teams = new Dictionary() { { CoreUtils.FullGuid, "All Teams" } }; private CoreTable _employees = new CoreTable(typeof(EmployeeTeam)); private CoreTable _assignments = new CoreTable(typeof(Assignment)); private Guid _selectedassignment = Guid.Empty; private DateTime _selecteddate = DateTime.MinValue; private Guid _selectedteam = Guid.Empty; private Guid[] _selectedemployees = new Guid[] { }; private double _zoom = 100.0D; private bool _sidebaropen = false; private AssignmentGrid _assignmentgrid = null; #endregion #region Events public event CustomiseAssignments CustomiseAssignments; public event CustomiseAssignmentsContextMenu CustomiseContextMenu; public event AssignmentSelectionChangedEvent AssignmentSelectionChanged; public event AssignmentChangedEvent AssignmentChanged; public event AssignmentViewSettingsChanged SettingsChanged; #endregion public AssignmentView2() { InitializeComponent(); Loaded += OnLoaded; PrevMonth.Content = new Image { Source = first }; PrevDay.Content = new Image { Source = back }; NextDay.Content = new Image { Source = next }; NextMonth.Content = new Image { Source = last }; } private void OnLoaded(object sender, RoutedEventArgs args) { Loaded -= OnLoaded; UpdateUI(UpdateDateVisible); UpdateUI(UpdateCanShowHideSideBar); UpdateUI(UpdateTimeInterval); UpdateUI(UpdateStartHour); UpdateUI(UpdateEndHour); UpdateUI(UpdateWorkingHourColors); } #region Settings private void DoSettingsChanged() { var settings = new AssignmentViewSettings() { SelectedDate = this.SelectedDate, SelectedTeam = this.SelectedTeam, SelectedEmployees = this.SelectedEmployees, Zoom = this.Zoom, SideBarOpen = this.SideBarOpen }; SettingsChanged?.Invoke(this, settings); } #endregion #region Public Properties public DateTime SelectedDate { get => _selecteddate; set { if (value != _selecteddate) { _selecteddate = value; UpdateUI(UpdateSelectedDate); DoSettingsChanged(); } } } public Guid SelectedTeam { get => _selectedteam; set { if (value != _selectedteam) { _selectedteam = value; UpdateUI(UpdateSelectedTeam); DoSettingsChanged(); } } } public Guid[] SelectedEmployees { get => _selectedemployees; set { if (new HashSet(value).SetEquals(_selectedemployees) == false) { _selectedemployees = value; UpdateUI(UpdateSelectedEmployees); DoSettingsChanged(); } } } public double Zoom { get => _zoom; set { if (Math.Abs(value - _zoom) > 0.001D) { _zoom = value; UpdateUI(UpdateZoom); DoSettingsChanged(); } } } public bool SideBarOpen { get => _sidebaropen; set { if (value != _sidebaropen) { _sidebaropen = value; UpdateUI(UpdateSideBarOpen); DoSettingsChanged(); } } } public int StartHour { get => (int)GetValue(StartHourProperty); set { if (value != StartHour) { SetValue(StartHourProperty, value); UpdateUI(UpdateStartHour); } } } public int EndHour { get => (int)GetValue(EndHourProperty); set { if (value != EndHour) { SetValue(EndHourProperty, value); UpdateUI(UpdateEndHour); } } } public Color WorkingHourColor { get => (Color)GetValue(WorkingHourColorProperty); set { if (!Color.Equals(value, WorkingHourColor)) { SetValue(WorkingHourColorProperty, value); UpdateUI(UpdateWorkingHourColors); } } } public Color NonWorkingHourColor { get => (Color)GetValue(NonWorkingHourColorProperty); set { if (Color.Equals(value, NonWorkingHourColor)) { SetValue(NonWorkingHourColorProperty, value); UpdateUI(UpdateWorkingHourColors); } } } public AssignmentViewTimeInterval TimeInterval { get => (AssignmentViewTimeInterval)GetValue(TimeIntervalProperty); set { if (value != TimeInterval) { SetValue(TimeIntervalProperty, value); UpdateUI(UpdateTimeInterval); } } } public bool CanShowHideSideBar { get => (bool)GetValue(CanShowHideSideBarProperty); set { if (value != CanShowHideSideBar) { SetValue(CanShowHideSideBarProperty, value); UpdateUI(UpdateCanShowHideSideBar); } } } public bool DateVisible { get => (bool)GetValue(DateVisibleProperty); set { if (value != DateVisible) { SetValue(DateVisibleProperty, value); UpdateUI(UpdateDateVisible); } } } #endregion #region Dependency Properties public static readonly DependencyProperty StartHourProperty = DependencyProperty.Register( "StartHour", typeof(int), typeof(AssignmentView2), new PropertyMetadata(6) ); public static readonly DependencyProperty EndHourProperty = DependencyProperty.Register( "EndHour", typeof(int), typeof(AssignmentView2), new PropertyMetadata(18) ); public static readonly DependencyProperty WorkingHourColorProperty = DependencyProperty.Register( "WorkingHourColor", typeof(Color), typeof(AssignmentView2), new PropertyMetadata(Colors.Transparent) ); public static readonly DependencyProperty NonWorkingHourColorProperty = DependencyProperty.Register( "NonWorkingHourColor", typeof(Color), typeof(AssignmentView2), new PropertyMetadata(Colors.Gainsboro) ); public static readonly DependencyProperty TimeIntervalProperty = DependencyProperty.Register( "TimeInterval", typeof(AssignmentViewTimeInterval), typeof(AssignmentView2), new PropertyMetadata(AssignmentViewTimeInterval.FifteenMinutes) ); public static readonly DependencyProperty CanShowHideSideBarProperty = DependencyProperty.Register( "CanShowHideSideBar", typeof(bool), typeof(AssignmentView2), new PropertyMetadata(true) ); public static readonly DependencyProperty DateVisibleProperty = DependencyProperty.Register( "DateVisible", typeof(bool), typeof(AssignmentView2), new PropertyMetadata(true) ); #endregion #region UI Sync Stuff // These functions should "push" property values to the UI // They should _not_ update the properties themselves // to avoid circular updates private bool _updatingUI = false; private void UpdateUI(Action action) { _updatingUI = true; try { action?.Invoke(); } finally { _updatingUI = false; } } private void UpdateStartHour() { StartTime.Value = new TimeSpan(StartHour, 0, 0); StartAMPM.Content = StartHour < 12 ? " AM " : StartHour > 12 ? " PM " : " NN "; UpdateWorkingHourColors(); Bookings.SelectedDate = _selecteddate.Date; var margin = IntervalToTimeSpan(TimeInterval); var start = new TimeSpan(StartHour, 0, 0); if (start >= margin) start -= margin; Bookings.DisplayDate = _selecteddate.Add(start); } private void UpdateEndHour() { EndTime.Value = new TimeSpan(EndHour, 0, 0); EndAMPM.Content = EndHour < 12 ? " AM " : EndHour > 12 ? " PM " : " NN "; UpdateWorkingHourColors(); } private void UpdateWorkingHourColors() { if (Bookings.ResourceCollection == null) return; var resources = Bookings.ResourceCollection.OfType(); if (!resources.Any()) return; var regions = new ObservableCollection(); foreach (var resource in resources) { if (StartHour > 0) { var before = new SpecialTimeRegion { StartTime = SelectedDate.Date, EndTime = SelectedDate.Date.AddHours(StartHour), ResourceIdCollection = new ObservableCollection { resource.Id }, Background = new SolidColorBrush(NonWorkingHourColor), Foreground = new SolidColorBrush(Colors.Black), CanMergeAdjacentRegions = true }; regions.Add(before); } if (EndHour < 24) { var after = new SpecialTimeRegion { StartTime = SelectedDate.Date.AddHours(EndHour), EndTime = SelectedDate.Date.AddDays(1).AddMilliseconds(-1), ResourceIdCollection = new ObservableCollection { resource.Id }, Background = new SolidColorBrush(NonWorkingHourColor), Foreground = new SolidColorBrush(Colors.Black), CanMergeAdjacentRegions = true }; regions.Add(after); } if (StartHour < EndHour) { var working = new SpecialTimeRegion { StartTime = SelectedDate.Date.AddHours(StartHour), EndTime = SelectedDate.Date.AddHours(EndHour), ResourceIdCollection = new ObservableCollection { resource.Id }, Background = new SolidColorBrush(WorkingHourColor), Foreground = new SolidColorBrush(Colors.Black), CanMergeAdjacentRegions = true }; regions.Add(working); } } Bookings.DaysViewSettings.SpecialTimeRegions = regions; } private void UpdateSelectedTeam() { Teams.SelectedValue = SelectedTeam; LoadEmployees(); } private void UpdateTimeInterval() { try { Bookings.DaysViewSettings.TimeInterval = IntervalToTimeSpan(TimeInterval); } catch (Exception e) { // If the view is invisible, setting the time interval throws an exeception (internal scroll viewer is still set to null) // So we only want to log an error if the view is actually visible if (Bookings.IsVisible) Logger.Send(LogType.Error, "", String.Format("Unable to update TimeInterval!\n{0}\n\n{1}", e.Message, e.StackTrace)); } } private void UpdateCanShowHideSideBar() { ShowSideBar.Visibility = CanShowHideSideBar && !SideBarOpen ? Visibility.Visible : Visibility.Collapsed; HideSideBar.Visibility = CanShowHideSideBar && SideBarOpen ? Visibility.Visible : Visibility.Collapsed; } private void UpdateDateVisible() { DateRow.Height = DateVisible ? new GridLength(35, GridUnitType.Pixel) : new GridLength(0, GridUnitType.Pixel); } private void UpdateSideBarOpen() { SideBar.Width = SideBarOpen ? new GridLength(200, GridUnitType.Pixel) : new GridLength(0, GridUnitType.Pixel); DateBorder.BorderThickness = SideBarOpen ? new Thickness(0.75, 0.75, 0, 0.75) : new Thickness(0.75, 0.75, 0.75, 0.75); UpdateCanShowHideSideBar(); } private void UpdateZoom() { ResizeIntervals(Bookings.ActualHeight); } private void UpdateSelectedDate() { CurrentDate.Text = string.Format("{0:ddd, dd MMMM yyyy}", SelectedDate); Bookings.SelectedDate = _selecteddate.Date; var margin = IntervalToTimeSpan(TimeInterval); var start = new TimeSpan(StartHour, 0, 0); if (start >= margin) start -= margin; Bookings.DisplayDate = _selecteddate.Add(start); } public void SetDisplayWindow(int start, int end) { if (!double.IsNaN(ActualHeight)) { ResizeIntervals(ActualHeight); SelectedDate = SelectedDate; // to trigger a reset? } } private void LoadEmployees() { var emps = new Dictionary(); foreach (var row in _employees.Rows.Where(r => r.Get(c => c.TeamLink.ID).Equals(SelectedTeam) || SelectedTeam.Equals(CoreUtils.FullGuid))) emps[row.Get(c => c.EmployeeLink.ID)] = row.Get(c => c.EmployeeLink.Name); Employees.ItemsSource = emps; } private void UpdateSelectedEmployees() { List resources = new List(); Employees.SelectedItems.Clear(); foreach (var item in Employees.Items) { var emp = (KeyValuePair)item; if (SelectedEmployees.Contains(emp.Key)) { Employees.SelectedItems.Add(item); resources.Add( new SchedulerResource { Name = emp.Value, Id = emp.Key.ToString() } ); } } Bookings.ResourceCollection = new ObservableCollection(resources); Bookings.DaysViewSettings.ResourceHeaderSize = resources.Count <= 1 ? 0 : 50; } #endregion public Assignment FindAssignment(Guid id) { return _assignments.Rows.FirstOrDefault(r => r.Get(c => c.ID).Equals(id))?.ToObject(); } private IAssignmentViewModel FindModel(Guid id) { var appointments = Bookings.ItemsSource as ScheduleAppointmentCollection; return appointments.FirstOrDefault(x => (x as IAssignmentViewModel).AssignmentID.Equals(id)) as IAssignmentViewModel; } public void AddAssignment(Assignment assignment) { var row = _assignments.NewRow(); _assignments.LoadRow(row, assignment); _assignments.Rows.Add(row); LoadModels(assignment.ID); } public void GetWindow(TimeSpan time, ref TimeSpan start, ref TimeSpan finish) { foreach (var row in _assignments.Rows) { var curstart = row.Get(x => x.Start); var curfinish = row.Get(x => x.Finish); if ((curfinish <= time) && (curfinish >= start)) start = curfinish; if ((curstart >= time) && (curstart <= finish)) finish = curstart; } } public CoreTable Data() => _assignments; public void Setup() { _employees = new Client().Query( null, new Columns( x => x.TeamLink.ID, x => x.TeamLink.Code, x => x.TeamLink.Name, x => x.EmployeeLink.ID, x => x.EmployeeLink.Name ), new SortOrder(x => x.TeamLink.Code).ThenBy(x => x.EmployeeLink.Name) ); _employees.IntoDictionary( _teams, x => x.TeamLink.ID, r => r.Get(c=>c.TeamLink.Name) ); Teams.ItemsSource = _teams; bReady = true; } private void ResizeIntervals(double height) { if (double.IsNaN(height) || height == 0.0F) return; var zoomedheight = height * (Zoom / 100.0F); Bookings.DaysViewSettings.TimeIntervalSize = zoomedheight / 24; } private void Bookings_SizeChanged(object sender, SizeChangedEventArgs e) { ResizeIntervals(e.NewSize.Height); } public void Refresh() { var filter = new Filter(x => x.Date).IsGreaterThanOrEqualTo(SelectedDate.Date) .And(x => x.Date).IsLessThanOrEqualTo(SelectedDate.Date.AddDays(1)) .And(x =>x.EmployeeLink.ID).InList(SelectedEmployees); _assignments = new Client().Query( filter, new Columns( x => x.ID, x => x.Title, x => x.ActivityLink.ID, x => x.ActivityLink.Color, x => x.ActivityLink.Description, x => x.ActivityLink.Deleted, x => x.JobLink.ID, x => x.JobLink.Name, x => x.JobLink.JobNumber, x => x.JobLink.Deleted, x => x.ITP.ID, x => x.ITP.Code, x => x.ITP.Description, x => x.ITP.Deleted, x => x.Number, x => x.Description, x => x.Date, x => x.Start, x => x.Duration, x => x.Finish, x => x.LeaveRequestLink.ID, x => x.Completed, x => x.Delivery.ID, x => x.Delivery.Notes, x => x.Delivery.Deleted, x => x.TimeSheetLink.ID, x => x.TimeSheetLink.Deleted, x => x.EmployeeLink.ID, x => x.Task.ID, x => x.Task.Number ) ); CustomiseAssignments?.Invoke(this, _assignments); LoadModels(Guid.Empty); } private void LoadModels(Guid id) { IAssignmentViewModel selected = null; var appointments = new ScheduleAppointmentCollection(); foreach (var row in _assignments.Rows) { var assignment = row.ToObject(); var sColor = assignment.ActivityLink.Color; var bgColor = string.IsNullOrWhiteSpace(sColor) ? Colors.White : (Color)ColorConverter.ConvertFromString(sColor); var jobdesc = new List(); var itask = assignment.Task.Number; if (itask > 0) jobdesc.Add(string.Format("Task #{0}", itask)); if (assignment.JobLink.IsValid()) { var job = assignment.JobLink.JobNumber; if (assignment.ITP.IsValid()) job = string.Format("{0} {1}", job, assignment.ITP.Code); job = string.Format("({0})", job); jobdesc.Add(job); } var date = assignment.Date; var sNote = assignment.Description + (assignment.Delivery.IsValid() ? "\n" + assignment.Delivery.Notes : ""); var model = new AssignmentViewModel { Subject = string.Format("{0}", assignment.Title?.Trim()), JobNumber = string.Format(" {0} ", string.Join(" ", jobdesc)), Number = assignment.Number, Notes = sNote.Trim(), StartTime = date.Add(assignment.Start), EndTime = date.Add(assignment.Finish), AssignmentID = assignment.ID, EmployeeID = assignment.EmployeeLink.ID, //AllDay = false, AppointmentForeground = new SolidColorBrush(Colors.Black), AppointmentBackground = new SolidColorBrush(bgColor), Locked = assignment.LeaveRequestLink.IsValid() ? locked : null, Completed = !assignment.LeaveRequestLink.IsValid() && !assignment.Completed.IsEmpty() ? tick : null, HasDelivery = !assignment.LeaveRequestLink.IsValid() && assignment.Delivery.IsValid() ? box : null, TimeSheet = assignment.TimeSheetLink.IsValid() ? timesheet : null, ResourceIdCollection = new ObservableCollection() { assignment.EmployeeLink.ID.ToString() } }; appointments.Add(model); if (model.AssignmentID == id) selected = model; } Bookings.ItemsSource = appointments; ResizeIntervals(Bookings.ActualHeight); UpdateWorkingHourColors(); } public void UpdateAssignment(Assignment assignment) { var row = _assignments.Rows.FirstOrDefault(r => r.Get(x => x.ID).Equals(assignment.ID)); _assignments.LoadRow(row, assignment); var model = FindModel(assignment.ID); var sColor = assignment.ActivityLink.Color; var bgColor = string.IsNullOrWhiteSpace(sColor) ? Colors.White : (Color)ColorConverter.ConvertFromString(sColor); var date = assignment.Date; var leaveid = assignment.LeaveRequestLink.ID; var job = ""; if (assignment.JobLink.IsValid()) { job = assignment.JobLink.JobNumber; if (assignment.ITP.IsValid()) job = string.Format("{0} {1}", job, assignment.ITP.Code); job = string.Format(" ({0}) ", job); } model.Subject = assignment.Title; model.Number = assignment.Number; model.JobNumber = job; model.Notes = assignment.Description; model.StartTime = date.Add(assignment.Start); model.EndTime = date.Add(assignment.Finish); model.AppointmentBackground = new SolidColorBrush(bgColor); model.Locked = assignment.LeaveRequestLink.IsValid() ? locked : null; model.Completed = !assignment.LeaveRequestLink.IsValid() && !assignment.Completed.IsEmpty() ? tick : null; model.HasDelivery = !assignment.LeaveRequestLink.IsValid() && assignment.Delivery.IsValid() ? box : null; model.TimeSheet = assignment.TimeSheetLink.IsValid() ? timesheet : null; //Bookings.UpdateLayout(); } #region Responding to UI Events private void PrevMonth_Click(object sender, RoutedEventArgs e) { SelectedDate = SelectedDate.AddDays(-7); AssignmentSelectionChanged?.Invoke(this, null); Refresh(); } private void PrevDay_Click(object sender, RoutedEventArgs e) { SelectedDate = SelectedDate.AddDays(-1); AssignmentSelectionChanged?.Invoke(this, null); Refresh(); } private void CurrentDate_MouseDoubleClick(object sender, MouseButtonEventArgs e) { SelectedDate = DateTime.Today; AssignmentSelectionChanged?.Invoke(this, null); Refresh(); } private void NextDay_Click(object sender, RoutedEventArgs e) { SelectedDate = SelectedDate.AddDays(1); AssignmentSelectionChanged?.Invoke(this, null); Refresh(); } private void NextMonth_Click(object sender, RoutedEventArgs e) { SelectedDate = SelectedDate.AddDays(7); AssignmentSelectionChanged?.Invoke(this, null); Refresh(); } private void Teams_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (_updatingUI) return; SelectedTeam = (Guid)Teams.SelectedValue; SelectedEmployees = _employees.Rows .Where(r => (SelectedTeam == CoreUtils.FullGuid) || (r.Get(c => c.TeamLink.ID) == SelectedTeam)) .Select(r => r.Get(c => c.EmployeeLink.ID)) .Distinct() .ToArray(); Refresh(); } private void Employees_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (_updatingUI) return; SelectedEmployees = Employees.SelectedItems.Select(x => ((KeyValuePair)x).Key).ToArray(); Refresh(); } private void StartTime_OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (_updatingUI) return; StartHour = (int)StartTime.Value.Value.TotalHours; } private void EndTime_OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (_updatingUI) return; EndHour = (int)EndTime.Value.Value.TotalHours; } private void OpenSideBar_Click(object sender, RoutedEventArgs e) { SideBarOpen = true; } private void CloseSideBar_Click(object sender, RoutedEventArgs e) { SideBarOpen = false; } #endregion private void Schedule_AppointmentEditorOpening(object sender, AppointmentEditorOpeningEventArgs e) { if (e.Appointment != null) { var model = (AssignmentViewModel)e.Appointment; Assignment ass = null; using (new WaitCursor()) { ass = new Client().Load(new Filter(x => x.ID).IsEqualTo(model.AssignmentID)) .FirstOrDefault(); } if (ass != null) EditAssignment(ass); else MessageBox.Show("Cannot Load Assignment!"); } else { var res = e.Resource; if (res != null) { var ass = new Assignment(); ass.EmployeeLink.ID = Guid.Parse(res.Id.ToString()); ass.Date = e.DateTime; ass.Duration = new TimeSpan(1, 0, 0); var ag = new DynamicDataGrid(); if (ag.EditItems(new[] { ass })) Refresh(); } else { MessageBox.Show("No Employee Selected!"); } } e.Cancel = true; } // private void Schedule_AppointmentStartDragging(object sender, AppointmentStartDraggingEventArgs e) // { // var model = e.Appointment as AssignmentViewModel; // if (model == null || model.Locked != null || model.TimeSheet != null) // e.Cancel = true; // } // // private void Schedule_AppointmentEndDragging(object sender, AppointmentEndDraggingEventArgs e) // { // var model = (AssignmentViewModel)e.Appointment; // // var row = model != null ? Assignments.Rows.FirstOrDefault(r => r.Get(x => x.ID).Equals(model.AssignmentID)) : null; // if (row != null) // { // Assignment ass = null; // using (new WaitCursor()) // { // ass = new Client().Load(new Filter(x => x.ID).IsEqualTo(model.AssignmentID)).FirstOrDefault(); // } // // if (ass != null) // { // var resource = e.Resources.FirstOrDefault() as Resource; // var employeeid = Guid.Parse(resource.ResourceName); // ass.EmployeeLink.ID = employeeid; // // var newtime = e.To.TimeOfDay; // if (e.To.Minute >= 45) // newtime = new TimeSpan(e.To.Hour, 45, 0); // else if (e.To.Minute >= 30) // newtime = new TimeSpan(e.To.Hour, 30, 0); // else if (e.To.Minute >= 15) // newtime = new TimeSpan(e.To.Hour, 15, 0); // else // newtime = new TimeSpan(e.To.Hour, 0, 0); // ass.Date = e.To.Date; // ass.Start = newtime; // // using (new WaitCursor()) // { // new Client().Save(ass, "Dragged by User", (obj, args) => { }); // } // // AssignmentChanged?.Invoke(this, ass); // // Refresh(); // // e.Cancel = true; // } // else // { // MessageBox.Show("Unable to load Assigmment!"); // } // } // else // { // MessageBox.Show("Unable to locate Assignment!"); // } // } // // private void Schedule_AppointmentEndResizing(object sender, AppointmentEndResizingEventArgs e) // { // var model = (AssignmentViewModel)e.Appointment; // var row = model != null ? Assignments.Rows.FirstOrDefault(r => r.Get(x => x.ID).Equals(model.AssignmentID)) : null; // if (row != null) // { // Assignment ass = null; // using (new WaitCursor()) // { // ass = new Client().Load(new Filter(x => x.ID).IsEqualTo(model.AssignmentID)).FirstOrDefault(); // } // // if (ass != null) // { // var newtime = e.To; // if (e.To.Minute >= 45) // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 45, 0); // else if (e.To.Minute >= 30) // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 30, 0); // else if (e.To.Minute >= 15) // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 15, 0); // else // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 0, 0); // ass.Date = newtime; // using (new WaitCursor()) // { // new Client().Save(ass, "Dragged by User", (obj, args) => { }); // } // // AssignmentChanged?.Invoke(this, ass); // // Refresh(); // e.Cancel = true; // } // else // { // MessageBox.Show("Unable to load Assigmment!"); // } // } // else // { // MessageBox.Show("Unable to locate Assignment!"); // } // } // // private AssignmentViewTimeInterval TimeSpanToInterval(TimeSpan time) // { // if (time <= new TimeSpan(0, 5, 0)) // return AssignmentViewTimeInterval.FiveMinutes; // if (time <= new TimeSpan(0, 6, 0)) // return AssignmentViewTimeInterval.SixMinutes; // if (time <= new TimeSpan(0, 10, 0)) // return AssignmentViewTimeInterval.TenMinutes; // if (time <= new TimeSpan(0, 15, 0)) // return AssignmentViewTimeInterval.FifteenMinutes; // if (time <= new TimeSpan(0, 20, 0)) // return AssignmentViewTimeInterval.TwentyMinutes; // if (time <= new TimeSpan(0, 30, 0)) // return AssignmentViewTimeInterval.ThirtyMinutes; // return AssignmentViewTimeInterval.SixyMinutes; // } private TimeSpan IntervalToTimeSpan(AssignmentViewTimeInterval interval) { switch (interval) { case AssignmentViewTimeInterval.FiveMinutes: return new TimeSpan(0, 5, 0); case AssignmentViewTimeInterval.SixMinutes: return new TimeSpan(0, 6, 0); case AssignmentViewTimeInterval.TenMinutes: return new TimeSpan(0, 10, 0); case AssignmentViewTimeInterval.FifteenMinutes: return new TimeSpan(0, 15, 0); case AssignmentViewTimeInterval.TwentyMinutes: return new TimeSpan(0, 20, 0); case AssignmentViewTimeInterval.ThirtyMinutes: return new TimeSpan(0, 30, 0); default: return new TimeSpan(1, 0, 0); } } // private int GetDivider(AssignmentViewTimeInterval interval) // { // switch (interval) // { // case AssignmentViewTimeInterval.FiveMinutes: // return 12; // case AssignmentViewTimeInterval.SixMinutes: // return 10; // case AssignmentViewTimeInterval.TenMinutes: // return 6; // case AssignmentViewTimeInterval.FifteenMinutes: // return 4; // case AssignmentViewTimeInterval.TwentyMinutes: // return 3; // case AssignmentViewTimeInterval.ThirtyMinutes: // return 2; // default: // return 1; // } // } // // private TimeSpan GetTime(int row) // { // int divider = GetDivider(TimeInterval); // var hours = row / divider; // var mins = row % divider * (60 / divider); // return new TimeSpan(hours, mins, 0); // } // private TimeSpan GetTime(Point point) // { // var view = Bookings.FindVisualChildren().LastOrDefault(x => x.Name.Equals("PART_ScrollViewer")); // var intervalheight = (Bookings.ActualHeight - 30.0F) / (24 * 4); // var row = (int)Math.Truncate((view.VerticalOffset + point.Y - 30.0F) / Bookings.DaysViewSettings.TimeIntervalSize); // var result = GetTime(row); // return result; // } // private void Bookings_Drop(object sender, DragEventArgs e) // { // if (e.Data.GetDataPresent("Comal.Classes.Delivery")) // { // var delivery = (e.Data.GetData("Comal.Classes.Delivery") as CoreRow[]).FirstOrDefault(); // if (delivery == null) // return; // // var assignment = new Assignment(); // // var resource = Bookings.ResourceCollection.OfType().ToArray(); // var colwidth = Bookings.ActualWidth / resource.Length; // var column = (int)Math.Truncate(e.GetPosition(Bookings).X / colwidth); // var employee = resource[column]; // // assignment.EmployeeLink.ID = Guid.Parse(employee.Id.ToString()); // // assignment.Date = SelectedDate.Date; // // //double intervalheight = (Bookings.ActualHeight - 30.0F) / (double)((Bookings.WorkEndHour - Bookings.WorkStartHour) * 4); // //int row = (int)Math.Truncate((e.GetPosition(Bookings).Y - 30.0F) / intervalheight); // //int hour = Bookings.WorkStartHour + (row / 4); // //int min = (row % 4) * 15; // //assignment.Start = new TimeSpan(hour, min, 0); // assignment.Start = GetTime(e.GetPosition(Bookings)); // // assignment.Duration = new TimeSpan(2, 0, 0); // // assignment.JobLink.ID = delivery.Get(x => x.Job.ID); // // assignment.Description = string.Format("Delivery Docket #{0}", delivery.Get(x => x.Number)); // // using (new WaitCursor()) // { // new Client().Save(assignment, "Created for Delivery"); // var del = new Client().Load(new Filter(x => x.ID).IsEqualTo(delivery.Get(x => x.ID))) // .FirstOrDefault(); // del.Assignment.ID = assignment.ID; // new Client().Save(del, "Booked via Scheduler"); // } // // AssignmentChanged?.Invoke(this, assignment); // // Refresh(); // // AssignmentSelectionChanged?.Invoke(this, assignment); // } // else if (e.Data.GetDataPresent("Comal.Classes.Kanban")) // { // var kanban = e.Data.GetData("Comal.Classes.Kanban") as Kanban; // if (kanban == null) // return; // // var assignment = new Assignment(); // // var resources = Bookings.ResourceCollection.OfType().ToArray(); // var colwidth = Bookings.ActualWidth / resources.Length; // var column = (int)Math.Truncate(e.GetPosition(Bookings).X / colwidth); // var employee = resources[column]; // // assignment.EmployeeLink.ID = Guid.Parse(employee.Id.ToString()); // // assignment.Date = SelectedDate.Date; // // var view = Bookings.FindVisualChildren().FirstOrDefault(x => x.Name.Equals("Scrollviewer1")); // var intervalheight = (Bookings.ActualHeight - 30.0F) / (24 * 4); // var row = (int)Math.Truncate((view.VerticalOffset + e.GetPosition(Bookings).Y - 30.0F) / Bookings.DaysViewSettings.TimeIntervalSize); // assignment.Start = GetTime(row); // // assignment.Duration = new TimeSpan(0, 30, 0); // // assignment.JobLink.ID = kanban.JobLink.ID; // assignment.Task.ID = kanban.ID; // // assignment.Title = kanban.Title; // // AssignmentChanged?.Invoke(this, assignment); // // Refresh(); // // AssignmentSelectionChanged?.Invoke(this, assignment); // } // } private void Bookings_OnAppointmentTapped(object? sender, AppointmentTappedArgs e) { var model = e.Appointment as IAssignmentViewModel; if (model != null) { var ass = FindAssignment(model.AssignmentID); if ( ((ass == null) && (_selectedassignment != null)) || ((ass != null) && (ass.ID != _selectedassignment)) ) { _selectedassignment = ass != null ? ass.ID : Guid.Empty; AssignmentSelectionChanged?.Invoke(this, ass); } } else { if (_selectedassignment != Guid.Empty) { _selectedassignment = Guid.Empty; AssignmentSelectionChanged?.Invoke(this, null); } } } #region Context Menu Handling private void Bookings_OnSchedulerContextMenuOpening(object? sender, SchedulerContextMenuOpeningEventArgs e) { IAssignmentData args = null; e.ContextMenu.Items.Clear(); if (e.MenuType == SchedulerContextMenuType.Appointment) { var model = e.MenuInfo.Appointment as IAssignmentViewModel; args = new AssignmentData(model, Guid.Empty, DateTime.MinValue); CreateEditMenu(e.ContextMenu, args); e.ContextMenu.Items.Add(new Separator()); CreateDeleteMenu(e.ContextMenu, args); e.ContextMenu.Items.Add(new Separator()); } else if (e.MenuType == SchedulerContextMenuType.TimeSlotCell) { if (Guid.TryParse(e.MenuInfo.Resource.Id?.ToString(), out Guid employeeid)) { args = new AssignmentData(null, employeeid, e.MenuInfo.DateTime.Value); CreateAddMenu(e.ContextMenu, args); e.ContextMenu.Items.Add(new Separator()); } } CreateZoomMenus(e.ContextMenu, args); CustomiseContextMenu?.Invoke(e.ContextMenu, args); } private void CreateMenu(ContextMenu menu, string name, string header, IAssignmentData args, RoutedEventHandler action, Visibility visibility) { var item = new MenuItem(); item.Name = name; item.Header = header; item.Click += action; item.Visibility = visibility; item.Tag = args; menu.Items.Add(item); } public bool CreateAddMenu(ContextMenu menu, IAssignmentData args) { if (args.Model == null) { CreateMenu(menu, "CreateAssignment", "Create Assignment", args, CreateAssignment_Click, Visibility.Visible); return true; } return false; } public bool CreateEditMenu(ContextMenu menu, IAssignmentData args) { if (args.Model != null) { CreateMenu(menu, "EditAssignment", "Edit Assignment", args, EditAssignment_Click, Visibility.Visible); return true; } return false; } public bool CreateDeleteMenu(ContextMenu menu, IAssignmentData args) { if (args.Model != null) { CreateMenu(menu, "DeleteAssignment", "Delete Assignment", args, DeleteAssignment_Click, Visibility.Visible); return true; } return false; } public bool CreateZoomMenus(ContextMenu menu, IAssignmentData args) { CreateMenu(menu, "ZoomIn", "Zoom In", args, ZoomIn_Click, Visibility.Visible); CreateMenu(menu, "ZoomOut", "Zoom Out", args, ZoomOut_Click, Visibility.Visible); CreateMenu(menu, "ZoomReset", "Reset Zoom", args, ZoomReset_Click, Visibility.Visible); return true; } private void EditAssignment(Assignment ass) { if (_assignmentgrid == null) _assignmentgrid = new AssignmentGrid(); if (_assignmentgrid.EditItems(new[] { ass })) { AssignmentChanged?.Invoke(this, ass); Refresh(); } } private void CreateAssignment_Click(object sender, RoutedEventArgs e) { var data = (sender as MenuItem).Tag as IAssignmentData; if (data != null) { var ass = new Assignment(); ass.Date = data.Time.Date; ass.Start = data.Time.TimeOfDay; ass.Duration = new TimeSpan(1, 0, 0); ass.EmployeeLink.ID = data.EmployeeID; EditAssignment(ass); } else { MessageBox.Show("Please select an employee first!"); } } private void EditAssignment_Click(object sender, RoutedEventArgs e) { var data = (sender as MenuItem).Tag as IAssignmentData; Assignment ass = null; using (new WaitCursor()) { ass = new Client().Load(new Filter(x => x.ID).IsEqualTo(data.Model.AssignmentID)) .FirstOrDefault(); } if (ass != null) EditAssignment(ass); else MessageBox.Show("Cannot Load Assignment!"); } private void DeleteAssignment_Click(object sender, RoutedEventArgs e) { var data = (sender as MenuItem).Tag as IAssignmentData; if ((data == null) || (data.Model == null)) { MessageBox.Show("No Assignment to Delete"); return; } if (MessageBox.Show("Are you sure you wish to delete this assignment?", "Confirm Delete", MessageBoxButton.YesNo) == MessageBoxResult.Yes) { Assignment ass = new Assignment() { ID = data.Model.AssignmentID}; using (new WaitCursor()) new Client().Delete(ass, "Assignment Deleted from Scheduler"); AssignmentChanged?.Invoke(this, ass); Refresh(); } } private void ZoomIn_Click(object sender, RoutedEventArgs e) { Zoom *= 1.25F; } private void ZoomOut_Click(object sender, RoutedEventArgs e) { Zoom /= 1.25F; } private void ZoomReset_Click(object sender, RoutedEventArgs e) { Zoom = 100.0F; } #endregion private void Bookings_PreviewKeyDown(object sender, KeyEventArgs e) { e.Handled = e.Key == Key.Delete; } } }