using System; using System.Collections.Generic; using System.Collections.ObjectModel; using InABox.Clients; using InABox.Core; using Comal.Classes; using Xamarin.Forms; using System.Linq; using System.Threading.Tasks; using InABox.Configuration; using Syncfusion.SfSchedule.XForms; using XF.Material.Forms; using XF.Material.Forms.UI.Dialogs; using XF.Material.Forms.UI.Dialogs.Configurations; using PRSSecurity = InABox.Core.Security; namespace comal.timesheets { public enum AssignmentView { Day, TimeLine } public enum AssignmentLookupType { ActiveJobs, UnbookedJobs, Tasks } public partial class AssignmentList { public AssignmentModel DataModel { get; private set; } private AssignmentEdit _editor = null; private Guid[] _employeeids = new Guid[] { }; private AssignmentModuleSettings _settings = null; private AssignmentView _view = AssignmentView.Day; private AssignmentLookupType _lookuptype = AssignmentLookupType.UnbookedJobs; private String _teamname = ""; public AssignmentList() { InitializeComponent(); DataModel = new AssignmentModel(App.Data, GetFilter, true); BindingContext = DataModel; _settings = new LocalConfiguration().Load(); DatePicker.Date = _settings.Date.IsEmpty() ? DateTime.Today : _settings.Date; _view = _settings.View; _employeeids = (_settings.Employees != null) ? _settings.Employees : new Guid[] { App.Data.Me.ID }; _lookuptype = _settings.LookupType; LookupType.Text = CoreUtils.Neatify(_lookuptype.ToString()); _teamname = String.IsNullOrWhiteSpace(_settings.TeamName) ? App.Data.Me.Name : _settings.TeamName; ShowHideSources.IsVisible = PRSSecurity.IsAllowed(); } protected override void OnAppearing() { base.OnAppearing(); RefreshLookups(); Reload(); } private void RefreshLookups() { if (_lookuptype == AssignmentLookupType.Tasks) { App.Data.KanbanLookups.Refresh(false, () => { Device.BeginInvokeOnMainThread(() => { Lookups.ItemsSource = new ObservableCollection(App.Data.KanbanLookups); }); }); } else if (_lookuptype == AssignmentLookupType.ActiveJobs) { App.Data.JobLookups.Refresh(false, () => { Device.BeginInvokeOnMainThread(() => { Lookups.ItemsSource = new ObservableCollection(App.Data.JobLookups); }); }); } else if (_lookuptype == AssignmentLookupType.UnbookedJobs) { App.Data.JobLookups.Refresh(false, () => { Device.BeginInvokeOnMainThread(() => { Lookups.ItemsSource = new ObservableCollection(App.Data.JobLookups.Where(x=>x.OpenAssignments == 0)); }); }); } } private void Reload() { DayView.DataSource = null; TimeLineView.DataSource = null; ScheduleType.Text = _teamname; if (_view == AssignmentView.Day) { TimelineFrame.IsVisible = false; DayFrame.IsVisible = true; DayView.DayViewSettings.DayLabelSettings.TimeFormat = "HH:mm"; } else { DayFrame.IsVisible = false; TimelineFrame.IsVisible = true; TimeLineView.ResourceViewSettings.VisibleResourceCount = Math.Max(1, Math.Min(16, _employeeids.Length)); TimeLineView.TimelineViewSettings.AppointmentHeight = (this.Height / TimeLineView.ResourceViewSettings.VisibleResourceCount) + 100; var resources = new ObservableCollection(); foreach (var empid in _employeeids) { var empname = App.Data.Employees.Items.FirstOrDefault(x => x.ID == empid)?.Name ?? empid.ToString(); if (_employeeids.Length > 10) empname = String.Join("", empname.Split(' ').Select(x => x.Substring(0, 1))); else if (_employeeids.Length > 6) { var comps = empname.Split(' ').ToArray(); empname = $"{comps.First()} {String.Join("", comps.Skip(1).Select(x => x.Substring(0, 1)))}"; } resources.Add( new ScheduleResource() { Name = empname, Id = empid, Color = Color.Transparent, Image = "" } ); } TimeLineView.ScheduleResources = resources; TimeLineView.ShowResourceView = true; } RefreshData(); } private Filter GetFilter() => new Filter(x => x.Date).IsEqualTo(DatePicker.Date) .And(x => x.EmployeeLink.ID).InList(_employeeids); private void RefreshData() { DataModel.Refresh(true, () => Device.BeginInvokeOnMainThread(UpdateScreen)); } private void UpdateScreen() { Title = $"{DatePicker.Date:dd MMMM yyyy}"; if (_view == AssignmentView.Day) { DayView.DataSource = new ObservableCollection(DataModel.Items); DayView.MoveToDate = ShowRelevantTime(); } else { TimeLineView.DataSource = new ObservableCollection(DataModel.Items); TimeLineView.MoveToDate = ShowRelevantTime(); } } private DateTime ShowRelevantTime() { return (DataModel.Items.Count > 0 ? (DataModel.Items.First() as AssignmentShell).StartTime : DateTime.Now).AddMinutes(-30); } private void Lookups_OnItemTapped(object sender, ItemTappedEventArgs e) { if (e.Item is ILookupShell lookup) { if (lookup.Selected) lookup.Selected = false; else { IList lookups = _lookuptype == AssignmentLookupType.Tasks ? App.Data.KanbanLookups.Items.ToArray() : App.Data.JobLookups.Items.ToArray(); { foreach (var other in lookups.Where(x => x.Selected).ToArray()) other.Selected = false; } lookup.Selected = true; } } } private void LookupsType_Tapped(object sender, EventArgs e) { _lookuptype = _lookuptype == AssignmentLookupType.Tasks ? AssignmentLookupType.ActiveJobs : _lookuptype == AssignmentLookupType.ActiveJobs ? AssignmentLookupType.UnbookedJobs : AssignmentLookupType.Tasks; _settings.LookupType = _lookuptype; LookupType.Text = CoreUtils.Neatify(_lookuptype.ToString()); new LocalConfiguration().Save(_settings); RefreshLookups(); } private async void Schedule_OnCellTapped(object sender, CellTappedEventArgs e) { if (e.Appointment is AssignmentShell item) { if (item.DeliveryID != Guid.Empty) { var delivery = new DeliveryDetails() { DeliveryID = item.DeliveryID}; Navigation.PushAsync(delivery); } else { var editor = new AssignmentEdit(item); Navigation.PushAsync(editor); } } } private async void Schedule_OnCellLongPressed(object sender, CellTappedEventArgs e) { if (e.Appointment == null) { if (InABox.Core.Security.CanEdit()) { CreateAssignment( e.Datetime, e.Resource as ScheduleResource ); } } else if (InABox.Core.Security.CanDelete() && e.Appointment is AssignmentShell assignment) { await DeleteAssignment(assignment.Id); } } private void CreateAssignment(DateTime date, ScheduleResource resource) { var assignment = new Assignment() { Date = date.Date, Title = "New Assignment", }; assignment.Booked.Start = new TimeSpan(date.TimeOfDay.Hours, 0, 0); assignment.Booked.Finish = date.TimeOfDay.Add(new TimeSpan(1, 0, 0)); assignment.Booked.Duration = new TimeSpan(1, 0, 0); assignment.EmployeeLink.ID = (resource is ScheduleResource sr) ? (Guid)sr.Id : App.Data.Me.ID; var job = (_lookuptype == AssignmentLookupType.ActiveJobs) || (_lookuptype == AssignmentLookupType.UnbookedJobs) ? App.Data.JobLookups.Items.FirstOrDefault(x => x.Selected) : null; if (job != null) { assignment.JobLink.ID = job.ID; assignment.JobLink.JobNumber = job.Code; assignment.JobLink.Name = job.Description; assignment.Description = job.Notes; assignment.Title = job.Description; job.Selected = false; } var task = _lookuptype == AssignmentLookupType.Tasks ? App.Data.KanbanLookups.Items.FirstOrDefault(x => x.Selected) : null; if (task != null) { assignment.Task.ID = task.ID; assignment.Task.Number = int.Parse(task.Code); assignment.Task.Title = task.Description; assignment.Title = task.Notes; assignment.Description = task.Description; task.Selected = false; } var editor = new AssignmentEdit(assignment); Navigation.PushAsync(editor); } private async Task DeleteAssignment(Guid id) { var confirm = await MaterialDialog.Instance.ConfirmAsync( "Are you sure you wish to delete this assignment?", "Confirm Deletion", "Yes, Delete", "Cancel", new MaterialAlertDialogConfiguration() { ButtonFontFamily = Material.FontFamily.Body2 } ); if (confirm == true) { using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Deleting Assignment")) { var assignment = new Assignment() { ID = id }; new Client().Delete(assignment, "Deleted on Mobile Device"); } RefreshData(); } } private void SelectDate_OnClicked(object sender, EventArgs e) { DatePicker.Focus(); } private void DatePicker_OnDateSelected(object sender, DateChangedEventArgs e) { if (_employeeids.Any()) { _settings.Date = DatePicker.Date; new LocalConfiguration().Save(_settings); } DayView.MoveToDate = DatePicker.Date; TimeLineView.MoveToDate = DatePicker.Date; RefreshData(); } private async void SelectEmployees_OnClicked(object sender, EventArgs e) { var actions = new List() { "Only Me" }; //actions.AddRange(App.Data.TeamEmployeeShells.Where(x=>x.ID == App.Data.Employee.ID).Select(x=>x.TeamName).Distinct()); actions.AddRange(App.Data.EmployeeTeams.Select(x => x.TeamName).Distinct()); var result = await MaterialDialog.Instance.SelectActionAsync(title: "Select a Team", actions: actions); if (result == 0) { _view = AssignmentView.Day; _employeeids = new Guid[] { App.Data.Me.ID }; _teamname = App.Data.Me.Name; } else if (result > 0) { _view = AssignmentView.TimeLine; _employeeids = App.Data.EmployeeTeams.Where(x => String.Equals(x.TeamName, actions[result])) .Select(x => x.ID).Distinct().ToArray(); _teamname = actions[result]; } _settings.Employees = _employeeids; _settings.View = _view; _settings.TeamName = _teamname; new LocalConfiguration().Save(_settings); Dispatcher.BeginInvokeOnMainThread(() => { Reload(); }); } private bool _sidebarvisible = false; private void ShowHideSources_OnClicked(object sender, EventArgs e) { _sidebarvisible = !_sidebarvisible; ShowHideSources.Source = _sidebarvisible ? ImageSource.FromFile("rightarrowwhite.png") : ImageSource.FromFile("downarrowwhite.png"); JobColumn.Width = _sidebarvisible ? new GridLength(150, GridUnitType.Absolute) : new GridLength(0, GridUnitType.Absolute); } } }