|  | @@ -17,1244 +17,1243 @@ using System.Drawing;
 | 
	
		
			
				|  |  |  using System.ComponentModel;
 | 
	
		
			
				|  |  |  using InABox.Wpf;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -namespace PRSDesktop
 | 
	
		
			
				|  |  | +namespace PRSDesktop;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public class TaskPanelProperties : BaseObject, IGlobalConfigurationSettings
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    [Comment("Require that all tasks are given a task type.")]
 | 
	
		
			
				|  |  | +    public bool RequireTaskTypes { get; set; } = false;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public class TaskPanelFilterButton : FilterButton<Kanban>
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    public class TaskPanelProperties : BaseObject, IGlobalConfigurationSettings
 | 
	
		
			
				|  |  | +    public TaskPanelFilterButton() : base(
 | 
	
		
			
				|  |  | +        new GlobalConfiguration<CoreFilterDefinitions>(nameof(Kanban)),
 | 
	
		
			
				|  |  | +        new UserConfiguration<CoreFilterDefinitions>(nameof(Kanban)))
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        [CheckBoxEditor(ToolTip = "Require that all tasks are given a task type.")]
 | 
	
		
			
				|  |  | -        public bool RequireTaskTypes { get; set; } = false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    public class TaskPanelFilterButton : FilterButton<Kanban>
 | 
	
		
			
				|  |  | +    public static Filter<Kanban> ConvertFilterToKanbanFilter(Filter<Kanban>? kanbanFilter)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        public TaskPanelFilterButton() : base(
 | 
	
		
			
				|  |  | -            new GlobalConfiguration<CoreFilterDefinitions>(nameof(Kanban)),
 | 
	
		
			
				|  |  | -            new UserConfiguration<CoreFilterDefinitions>(nameof(Kanban)))
 | 
	
		
			
				|  |  | +        if (kanbanFilter is null)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | +            return new Filter<Kanban>().All();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public static Filter<Kanban> ConvertFilterToKanbanFilter(Filter<Kanban>? kanbanFilter)
 | 
	
		
			
				|  |  | +        else if (CoreUtils.TryFindMemberExpression(kanbanFilter.Expression, out var mexp))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            if (kanbanFilter is null)
 | 
	
		
			
				|  |  | +            var prop = CoreUtils.GetFullPropertyName(mexp, ".");
 | 
	
		
			
				|  |  | +            var filter = new Filter<Kanban>(prop)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                return new Filter<Kanban>().All();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if (CoreUtils.TryFindMemberExpression(kanbanFilter.Expression, out var mexp))
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                var prop = CoreUtils.GetFullPropertyName(mexp, ".");
 | 
	
		
			
				|  |  | -                var filter = new Filter<Kanban>(prop)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    Operator = kanbanFilter.Operator,
 | 
	
		
			
				|  |  | -                    Value = kanbanFilter.Value
 | 
	
		
			
				|  |  | -                };
 | 
	
		
			
				|  |  | +                Operator = kanbanFilter.Operator,
 | 
	
		
			
				|  |  | +                Value = kanbanFilter.Value
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                filter.Ands.AddRange(kanbanFilter.Ands.Select(ConvertFilterToKanbanFilter));
 | 
	
		
			
				|  |  | -                filter.Ors.AddRange(kanbanFilter.Ors.Select(ConvertFilterToKanbanFilter));
 | 
	
		
			
				|  |  | +            filter.Ands.AddRange(kanbanFilter.Ands.Select(ConvertFilterToKanbanFilter));
 | 
	
		
			
				|  |  | +            filter.Ors.AddRange(kanbanFilter.Ors.Select(ConvertFilterToKanbanFilter));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                return filter;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                return new Filter<Kanban>().None();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            return filter;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return new Filter<Kanban>().None();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public static Filter<KanbanSubscriber> ConvertFilterToSubscriberFilter(Filter<IKanban>? kanbanFilter)
 | 
	
		
			
				|  |  | +    public static Filter<KanbanSubscriber> ConvertFilterToSubscriberFilter(Filter<IKanban>? kanbanFilter)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (kanbanFilter is null)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            if (kanbanFilter is null)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                return new Filter<KanbanSubscriber>().All();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if (CoreUtils.TryFindMemberExpression(kanbanFilter.Expression, out var mexp))
 | 
	
		
			
				|  |  | +            return new Filter<KanbanSubscriber>().All();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else if (CoreUtils.TryFindMemberExpression(kanbanFilter.Expression, out var mexp))
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var prop = CoreUtils.GetFullPropertyName(mexp, ".");
 | 
	
		
			
				|  |  | +            var filter = new Filter<KanbanSubscriber>(nameof(KanbanSubscriber.Kanban) + "." + prop)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                var prop = CoreUtils.GetFullPropertyName(mexp, ".");
 | 
	
		
			
				|  |  | -                var filter = new Filter<KanbanSubscriber>(nameof(KanbanSubscriber.Kanban) + "." + prop)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    Operator = kanbanFilter.Operator,
 | 
	
		
			
				|  |  | -                    Value = kanbanFilter.Value
 | 
	
		
			
				|  |  | -                };
 | 
	
		
			
				|  |  | +                Operator = kanbanFilter.Operator,
 | 
	
		
			
				|  |  | +                Value = kanbanFilter.Value
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                filter.Ands.AddRange(kanbanFilter.Ands.Select(ConvertFilterToSubscriberFilter));
 | 
	
		
			
				|  |  | -                filter.Ors.AddRange(kanbanFilter.Ors.Select(ConvertFilterToSubscriberFilter));
 | 
	
		
			
				|  |  | +            filter.Ands.AddRange(kanbanFilter.Ands.Select(ConvertFilterToSubscriberFilter));
 | 
	
		
			
				|  |  | +            filter.Ors.AddRange(kanbanFilter.Ors.Select(ConvertFilterToSubscriberFilter));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                return filter;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                return new Filter<KanbanSubscriber>().None();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            return filter;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return new Filter<KanbanSubscriber>().None();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    ///     Interaction logic for TaskPanel.xaml
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    public partial class TaskPanel : UserControl, IPanel<Kanban>, ITaskHost, IMasterDetailControl<Job>, IPropertiesPanel<TaskPanelProperties, CanConfigureTasksPanel>
 | 
	
		
			
				|  |  | +/// <summary>
 | 
	
		
			
				|  |  | +///     Interaction logic for TaskPanel.xaml
 | 
	
		
			
				|  |  | +/// </summary>
 | 
	
		
			
				|  |  | +public partial class TaskPanel : UserControl, IPanel<Kanban>, ITaskHost, IMasterDetailControl<Job>, IPropertiesPanel<TaskPanelProperties, CanConfigureTasksPanel>
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    private bool _bTabChanging;
 | 
	
		
			
				|  |  | +    private KanbanType[] kanbanTypes = null!; // Initialized in Setup()
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    public IList<KanbanType> KanbanTypes => kanbanTypes;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    public Job? Master { get; set; }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    public TaskPanel()
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        private bool _bTabChanging;
 | 
	
		
			
				|  |  | -        private KanbanType[] kanbanTypes = null!; // Initialized in Setup()
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  | -        public IList<KanbanType> KanbanTypes => kanbanTypes;
 | 
	
		
			
				|  |  | +        InitializeComponent();
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  | -        public Job? Master { get; set; }
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  | -        public TaskPanel()
 | 
	
		
			
				|  |  | +        foreach (TabItem tab in TaskPanels.Items)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            InitializeComponent();
 | 
	
		
			
				|  |  | -            
 | 
	
		
			
				|  |  | -            foreach (TabItem tab in TaskPanels.Items)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                var panel = (tab.Content as ITaskControl)!;
 | 
	
		
			
				|  |  | -                _viewmap[panel.KanbanViewType] = tab;
 | 
	
		
			
				|  |  | -                panel.Host = this;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            var panel = (tab.Content as ITaskControl)!;
 | 
	
		
			
				|  |  | +            _viewmap[panel.KanbanViewType] = tab;
 | 
	
		
			
				|  |  | +            panel.Host = this;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        #region Menu
 | 
	
		
			
				|  |  | +    #region Menu
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private void CompleteTask(ITaskControl control, RoutedEventArgs e, DateTime completed)
 | 
	
		
			
				|  |  | +    private void CompleteTask(ITaskControl control, RoutedEventArgs e, DateTime completed)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (!MessageWindow.ShowYesNo("Are you sure you want to complete the selected tasks?", "Confirm Completion"))
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        var tasks = (((FrameworkElement)e.Source).Tag as IEnumerable<TaskModel>)!;
 | 
	
		
			
				|  |  | +        Progress.ShowModal("Completing Tasks", progress =>
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            if (!MessageWindow.ShowYesNo("Are you sure you want to complete the selected tasks?", "Confirm Completion"))
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            var tasks = (((FrameworkElement)e.Source).Tag as IEnumerable<TaskModel>)!;
 | 
	
		
			
				|  |  | -            Progress.ShowModal("Completing Tasks", progress =>
 | 
	
		
			
				|  |  | +            var kanbans = LoadKanbans(tasks, Columns.Required<Kanban>().Add(x => x.ID, x => x.Completed, x => x.Status));
 | 
	
		
			
				|  |  | +            foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                var kanbans = LoadKanbans(tasks, Columns.Required<Kanban>().Add(x => x.ID, x => x.Completed, x => x.Status));
 | 
	
		
			
				|  |  | -                foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    kanban.Completed = completed;
 | 
	
		
			
				|  |  | -                    kanban.Status = KanbanStatus.Complete;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                kanban.Completed = completed;
 | 
	
		
			
				|  |  | +                kanban.Status = KanbanStatus.Complete;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                Client.Save(kanbans, $"Kanban Marked as Complete");
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            control.Refresh();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        private void AddChangeStatusButton(ITaskControl control, TaskModel[] models, MenuItem menu, string header, KanbanStatus status)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            menu.AddItem(header, null, Tuple.Create(control, models, status), ChangeStatus_Click);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +            Client.Save(kanbans, $"Kanban Marked as Complete");
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        control.Refresh();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    private void AddChangeStatusButton(ITaskControl control, TaskModel[] models, MenuItem menu, string header, KanbanStatus status)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        menu.AddItem(header, null, Tuple.Create(control, models, status), ChangeStatus_Click);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private void ChangeStatus_Click(Tuple<ITaskControl, TaskModel[], KanbanStatus> obj)
 | 
	
		
			
				|  |  | +    private void ChangeStatus_Click(Tuple<ITaskControl, TaskModel[], KanbanStatus> obj)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var (control, tasks, status) = obj;
 | 
	
		
			
				|  |  | +        if (!MessageWindow.ShowYesNo($"Are you sure you want to mark the selected tasks as {status}?", "Confirm Change Status"))
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        Progress.ShowModal("Changing Status", progress =>
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var (control, tasks, status) = obj;
 | 
	
		
			
				|  |  | -            if (!MessageWindow.ShowYesNo($"Are you sure you want to mark the selected tasks as {status}?", "Confirm Change Status"))
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            Progress.ShowModal("Changing Status", progress =>
 | 
	
		
			
				|  |  | +            var kanbans = LoadKanbans(tasks, Columns.Required<Kanban>().Add(x => x.ID, x => x.Completed, x => x.Status));
 | 
	
		
			
				|  |  | +            foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                var kanbans = LoadKanbans(tasks, Columns.Required<Kanban>().Add(x => x.ID, x => x.Completed, x => x.Status));
 | 
	
		
			
				|  |  | -                foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  | +                if (status == KanbanStatus.Complete)
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    if (status == KanbanStatus.Complete)
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        kanban.Completed = DateTime.Now;
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    kanban.Status = status;
 | 
	
		
			
				|  |  | +                    kanban.Completed = DateTime.Now;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | +                kanban.Status = status;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                new Client<Kanban>().Save(kanbans, $"Kanban Marked as {status}");
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            control.Refresh();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +            new Client<Kanban>().Save(kanbans, $"Kanban Marked as {status}");
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        control.Refresh();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public bool CanChangeTasks(IEnumerable<TaskModel> models)
 | 
	
		
			
				|  |  | +    public bool CanChangeTasks(IEnumerable<TaskModel> models)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        foreach (var task in models)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            foreach (var task in models)
 | 
	
		
			
				|  |  | +            if (!App.EmployeeID.Equals(task.ManagerID) && !App.EmployeeID.Equals(task.EmployeeID))
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                if (!App.EmployeeID.Equals(task.ManagerID) && !App.EmployeeID.Equals(task.EmployeeID))
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    // If you can change others tasks, IsFullControl is true - but we don't check at the beginning of the function
 | 
	
		
			
				|  |  | -                    // to save checking security tokens every time.
 | 
	
		
			
				|  |  | -                    return Security.IsAllowed<CanChangeOthersTasks>();
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                // If you can change others tasks, IsFullControl is true - but we don't check at the beginning of the function
 | 
	
		
			
				|  |  | +                // to save checking security tokens every time.
 | 
	
		
			
				|  |  | +                return Security.IsAllowed<CanChangeOthersTasks>();
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            return true;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        return true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void PopulateMenu(ITaskControl control, TaskModel task, ContextMenu menu)
 | 
	
		
			
				|  |  | +    public void PopulateMenu(ITaskControl control, TaskModel task, ContextMenu menu)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        menu.Items.Clear();
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        var models = control.SelectedModels(task).ToArray();
 | 
	
		
			
				|  |  | +        var references = GetReferences(models);
 | 
	
		
			
				|  |  | +        var bLinks = references.Any(x => x.ReferenceType() != null);
 | 
	
		
			
				|  |  | +        var referencetypes = references.Select(x => x.ReferenceType()).Distinct().ToArray();
 | 
	
		
			
				|  |  | +        var bSingle = models.Length == 1;
 | 
	
		
			
				|  |  | +        var canChange = CanChangeTasks(models);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var edit = new MenuItem
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            menu.Items.Clear();
 | 
	
		
			
				|  |  | -            
 | 
	
		
			
				|  |  | -            var models = control.SelectedModels(task).ToArray();
 | 
	
		
			
				|  |  | -            var references = GetReferences(models);
 | 
	
		
			
				|  |  | -            var bLinks = references.Any(x => x.ReferenceType() != null);
 | 
	
		
			
				|  |  | -            var referencetypes = references.Select(x => x.ReferenceType()).Distinct().ToArray();
 | 
	
		
			
				|  |  | -            var bSingle = models.Length == 1;
 | 
	
		
			
				|  |  | -            var canChange = CanChangeTasks(models);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            var edit = new MenuItem
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Tag = models,
 | 
	
		
			
				|  |  | -                Header = referencetypes.SingleOrDefault() == typeof(Requisition)
 | 
	
		
			
				|  |  | -                    ? "Edit Requisition Details"
 | 
	
		
			
				|  |  | -                    : referencetypes.SingleOrDefault() == typeof(Setout)
 | 
	
		
			
				|  |  | -                        ? "Edit Setout Details"
 | 
	
		
			
				|  |  | -                        : referencetypes.SingleOrDefault() == typeof(Delivery)
 | 
	
		
			
				|  |  | -                            ? "Edit Delivery Details"
 | 
	
		
			
				|  |  | -                            : referencetypes.SingleOrDefault() == typeof(PurchaseOrder)
 | 
	
		
			
				|  |  | -                                ? "Edit Order Details"
 | 
	
		
			
				|  |  | -                                : "Edit Task" + (bSingle ? "" : "s")
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | -            edit.Click += (o, e) =>
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                var tasks = (((MenuItem)e.Source).Tag as IEnumerable<TaskModel>)!;
 | 
	
		
			
				|  |  | -                if (EditReferences(tasks))
 | 
	
		
			
				|  |  | -                    control.Refresh();
 | 
	
		
			
				|  |  | -                e.Handled = true;
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | -            edit.IsEnabled = referencetypes.Length == 1;
 | 
	
		
			
				|  |  | -            menu.Items.Add(edit);
 | 
	
		
			
				|  |  | +            Tag = models,
 | 
	
		
			
				|  |  | +            Header = referencetypes.SingleOrDefault() == typeof(Requisition)
 | 
	
		
			
				|  |  | +                ? "Edit Requisition Details"
 | 
	
		
			
				|  |  | +                : referencetypes.SingleOrDefault() == typeof(Setout)
 | 
	
		
			
				|  |  | +                    ? "Edit Setout Details"
 | 
	
		
			
				|  |  | +                    : referencetypes.SingleOrDefault() == typeof(Delivery)
 | 
	
		
			
				|  |  | +                        ? "Edit Delivery Details"
 | 
	
		
			
				|  |  | +                        : referencetypes.SingleOrDefault() == typeof(PurchaseOrder)
 | 
	
		
			
				|  |  | +                            ? "Edit Order Details"
 | 
	
		
			
				|  |  | +                            : "Edit Task" + (bSingle ? "" : "s")
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        edit.Click += (o, e) =>
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var tasks = (((MenuItem)e.Source).Tag as IEnumerable<TaskModel>)!;
 | 
	
		
			
				|  |  | +            if (EditReferences(tasks))
 | 
	
		
			
				|  |  | +                control.Refresh();
 | 
	
		
			
				|  |  | +            e.Handled = true;
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        edit.IsEnabled = referencetypes.Length == 1;
 | 
	
		
			
				|  |  | +        menu.Items.Add(edit);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (!bLinks && models.Length == 1)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var digitalForms = new MenuItem { Header = "Digital Forms" };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (!bLinks && models.Length == 1)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                var digitalForms = new MenuItem { Header = "Digital Forms" };
 | 
	
		
			
				|  |  | +            var model = models.First();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                var model = models.First();
 | 
	
		
			
				|  |  | +            DynamicGridUtils.PopulateFormMenu<KanbanForm, Kanban, KanbanLink>(
 | 
	
		
			
				|  |  | +                digitalForms,
 | 
	
		
			
				|  |  | +                model.ID,
 | 
	
		
			
				|  |  | +                () => new Client<Kanban>().Load(new Filter<Kanban>(x => x.ID).IsEqualTo(model.ID)).First(),
 | 
	
		
			
				|  |  | +                model.EmployeeID == App.EmployeeID);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                DynamicGridUtils.PopulateFormMenu<KanbanForm, Kanban, KanbanLink>(
 | 
	
		
			
				|  |  | -                    digitalForms,
 | 
	
		
			
				|  |  | -                    model.ID,
 | 
	
		
			
				|  |  | -                    () => new Client<Kanban>().Load(new Filter<Kanban>(x => x.ID).IsEqualTo(model.ID)).First(),
 | 
	
		
			
				|  |  | -                    model.EmployeeID == App.EmployeeID);
 | 
	
		
			
				|  |  | +            menu.Items.Add(digitalForms);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                menu.Items.Add(digitalForms);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        if (!models.Any(x => !x.CompletedDate.IsEmpty()) && !bLinks)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            menu.Items.Add(new Separator());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var job = new MenuItem
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Tag = models,
 | 
	
		
			
				|  |  | +                Header = "Link to Job"
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            job.SubmenuOpened += (o, e) => CreateJobSubMenu(control, job, models);
 | 
	
		
			
				|  |  | +            menu.Items.Add(job);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (!models.Any(x => !x.CompletedDate.IsEmpty()) && !bLinks)
 | 
	
		
			
				|  |  | +            if (bSingle)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                menu.Items.Add(new Separator());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                var job = new MenuItem
 | 
	
		
			
				|  |  | +                menu.AddItem("Create Setout from Task", null, models.First(), task =>
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    Tag = models,
 | 
	
		
			
				|  |  | -                    Header = "Link to Job"
 | 
	
		
			
				|  |  | -                };
 | 
	
		
			
				|  |  | -                job.SubmenuOpened += (o, e) => CreateJobSubMenu(control, job, models);
 | 
	
		
			
				|  |  | -                menu.Items.Add(job);
 | 
	
		
			
				|  |  | +                    if (!MessageWindow.ShowYesNo("This will convert this task into a Setout.\n\nDo you wish to continue?", "Confirmation"))
 | 
	
		
			
				|  |  | +                        return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                if (bSingle)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | +                    ManufacturingTemplate? template = new Client<ManufacturingTemplate>()
 | 
	
		
			
				|  |  | +                        .Load(new Filter<ManufacturingTemplate>(x => x.Code).IsEqualTo("PRS")).FirstOrDefault();
 | 
	
		
			
				|  |  | +                    if (template == null)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        MessageWindow.ShowMessage("[Pressing] Template does not exist!", "No template");
 | 
	
		
			
				|  |  | +                        return;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    menu.AddItem("Create Setout from Task", null, models.First(), task =>
 | 
	
		
			
				|  |  | +                    string? setoutNumber = null;
 | 
	
		
			
				|  |  | +                    Kanban? kanban = null;
 | 
	
		
			
				|  |  | +                    ManufacturingTemplateStage[] tstages = Array.Empty<ManufacturingTemplateStage>();
 | 
	
		
			
				|  |  | +                    Progress.ShowModal("Creating Setout", (progress) =>
 | 
	
		
			
				|  |  |                      {
 | 
	
		
			
				|  |  | -                        if (!MessageWindow.ShowYesNo("This will convert this task into a Setout.\n\nDo you wish to continue?", "Confirmation"))
 | 
	
		
			
				|  |  | -                            return;
 | 
	
		
			
				|  |  | +                        var kanbanFilter = new Filter<Kanban>(x => x.ID).IsEqualTo(task.ID);
 | 
	
		
			
				|  |  | +                        var tables = Client.QueryMultiple(new Dictionary<string, IQueryDef>
 | 
	
		
			
				|  |  | +                        {
 | 
	
		
			
				|  |  | +                            { "ManufacturingTemplateStage", new QueryDef<ManufacturingTemplateStage>(
 | 
	
		
			
				|  |  | +                                new Filter<ManufacturingTemplateStage>(x => x.Template.ID).IsEqualTo(template.ID),
 | 
	
		
			
				|  |  | +                                null,
 | 
	
		
			
				|  |  | +                                new SortOrder<ManufacturingTemplateStage>(x => x.Sequence)) },
 | 
	
		
			
				|  |  | +                            { "Kanban", new QueryDef<Kanban>(
 | 
	
		
			
				|  |  | +                                kanbanFilter,
 | 
	
		
			
				|  |  | +                                null,
 | 
	
		
			
				|  |  | +                                null) },
 | 
	
		
			
				|  |  | +                            { "Setout", new QueryDef<Setout>(
 | 
	
		
			
				|  |  | +                                new Filter<Setout>(x => x.JobLink.ID)
 | 
	
		
			
				|  |  | +                                    .InQuery(new SubQuery<Kanban>(kanbanFilter, new Column<Kanban>(x => x.JobLink.ID))),
 | 
	
		
			
				|  |  | +                                Columns.None<Setout>().Add(x => x.JobLink.JobNumber, x => x.Number),
 | 
	
		
			
				|  |  | +                                null) }
 | 
	
		
			
				|  |  | +                        });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        ManufacturingTemplate? template = new Client<ManufacturingTemplate>()
 | 
	
		
			
				|  |  | -                            .Load(new Filter<ManufacturingTemplate>(x => x.Code).IsEqualTo("PRS")).FirstOrDefault();
 | 
	
		
			
				|  |  | -                        if (template == null)
 | 
	
		
			
				|  |  | +                        tstages = tables["ManufacturingTemplateStage"].Rows
 | 
	
		
			
				|  |  | +                           .Select(x => x.ToObject<ManufacturingTemplateStage>()).ToArray();
 | 
	
		
			
				|  |  | +                        kanban = tables["Kanban"].Rows.FirstOrDefault()?.ToObject<Kanban>();
 | 
	
		
			
				|  |  | +                        if (kanban == null)
 | 
	
		
			
				|  |  |                          {
 | 
	
		
			
				|  |  | -                            MessageWindow.ShowMessage("[Pressing] Template does not exist!", "No template");
 | 
	
		
			
				|  |  | +                            MessageWindow.ShowMessage("Task does not exist!", "No task");
 | 
	
		
			
				|  |  |                              return;
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        string? setoutNumber = null;
 | 
	
		
			
				|  |  | -                        Kanban? kanban = null;
 | 
	
		
			
				|  |  | -                        ManufacturingTemplateStage[] tstages = Array.Empty<ManufacturingTemplateStage>();
 | 
	
		
			
				|  |  | -                        Progress.ShowModal("Creating Setout", (progress) =>
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            var kanbanFilter = new Filter<Kanban>(x => x.ID).IsEqualTo(task.ID);
 | 
	
		
			
				|  |  | -                            var tables = Client.QueryMultiple(new Dictionary<string, IQueryDef>
 | 
	
		
			
				|  |  | -                            {
 | 
	
		
			
				|  |  | -                                { "ManufacturingTemplateStage", new QueryDef<ManufacturingTemplateStage>(
 | 
	
		
			
				|  |  | -                                    new Filter<ManufacturingTemplateStage>(x => x.Template.ID).IsEqualTo(template.ID),
 | 
	
		
			
				|  |  | -                                    null,
 | 
	
		
			
				|  |  | -                                    new SortOrder<ManufacturingTemplateStage>(x => x.Sequence)) },
 | 
	
		
			
				|  |  | -                                { "Kanban", new QueryDef<Kanban>(
 | 
	
		
			
				|  |  | -                                    kanbanFilter,
 | 
	
		
			
				|  |  | -                                    null,
 | 
	
		
			
				|  |  | -                                    null) },
 | 
	
		
			
				|  |  | -                                { "Setout", new QueryDef<Setout>(
 | 
	
		
			
				|  |  | -                                    new Filter<Setout>(x => x.JobLink.ID)
 | 
	
		
			
				|  |  | -                                        .InQuery(new SubQuery<Kanban>(kanbanFilter, new Column<Kanban>(x => x.JobLink.ID))),
 | 
	
		
			
				|  |  | -                                    Columns.None<Setout>().Add(x => x.JobLink.JobNumber, x => x.Number),
 | 
	
		
			
				|  |  | -                                    null) }
 | 
	
		
			
				|  |  | -                            });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                            tstages = tables["ManufacturingTemplateStage"].Rows
 | 
	
		
			
				|  |  | -                               .Select(x => x.ToObject<ManufacturingTemplateStage>()).ToArray();
 | 
	
		
			
				|  |  | -                            kanban = tables["Kanban"].Rows.FirstOrDefault()?.ToObject<Kanban>();
 | 
	
		
			
				|  |  | -                            if (kanban == null)
 | 
	
		
			
				|  |  | -                            {
 | 
	
		
			
				|  |  | -                                MessageWindow.ShowMessage("Task does not exist!", "No task");
 | 
	
		
			
				|  |  | -                                return;
 | 
	
		
			
				|  |  | -                            }
 | 
	
		
			
				|  |  | +                        progress.Report("Creating Setouts");
 | 
	
		
			
				|  |  | +                        CoreTable setouts = tables["Setout"];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                            progress.Report("Creating Setouts");
 | 
	
		
			
				|  |  | -                            CoreTable setouts = tables["Setout"];
 | 
	
		
			
				|  |  | +                        int ireq = 0;
 | 
	
		
			
				|  |  | +                        string sreq = "";
 | 
	
		
			
				|  |  | +                        while (true)
 | 
	
		
			
				|  |  | +                        {
 | 
	
		
			
				|  |  | +                            ireq++;
 | 
	
		
			
				|  |  | +                            sreq = string.Format("{0}-{1:yyMMdd}-{2}", kanban.JobLink.JobNumber, DateTime.Now, ireq);
 | 
	
		
			
				|  |  | +                            if (!setouts.Rows.Any(r => sreq.Equals(r.Get<Setout, String>(c => c.Number))))
 | 
	
		
			
				|  |  | +                                break;
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        setoutNumber = sreq;
 | 
	
		
			
				|  |  | +                    });
 | 
	
		
			
				|  |  | +                    if (setoutNumber == null || kanban == null)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        return;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    var result = CreateSetout(
 | 
	
		
			
				|  |  | +                        task,
 | 
	
		
			
				|  |  | +                        s =>
 | 
	
		
			
				|  |  | +                        {
 | 
	
		
			
				|  |  | +                            s.Number = setoutNumber;
 | 
	
		
			
				|  |  | +                            s.JobLink.ID = task.JobID;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                            int ireq = 0;
 | 
	
		
			
				|  |  | -                            string sreq = "";
 | 
	
		
			
				|  |  | -                            while (true)
 | 
	
		
			
				|  |  | +                            var notes = kanban.Notes.ToList();
 | 
	
		
			
				|  |  | +                            var description = kanban.Summary;
 | 
	
		
			
				|  |  | +                            if (string.IsNullOrWhiteSpace(description))
 | 
	
		
			
				|  |  |                              {
 | 
	
		
			
				|  |  | -                                ireq++;
 | 
	
		
			
				|  |  | -                                sreq = string.Format("{0}-{1:yyMMdd}-{2}", kanban.JobLink.JobNumber, DateTime.Now, ireq);
 | 
	
		
			
				|  |  | -                                if (!setouts.Rows.Any(r => sreq.Equals(r.Get<Setout, String>(c => c.Number))))
 | 
	
		
			
				|  |  | -                                    break;
 | 
	
		
			
				|  |  | +                                description = CoreUtils.StripHTML(kanban.Description);
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | -                            setoutNumber = sreq;
 | 
	
		
			
				|  |  | -                        });
 | 
	
		
			
				|  |  | -                        if (setoutNumber == null || kanban == null)
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            return;
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                        var result = CreateSetout(
 | 
	
		
			
				|  |  | -                            task,
 | 
	
		
			
				|  |  | -                            s =>
 | 
	
		
			
				|  |  | +                            if (!string.IsNullOrWhiteSpace(description))
 | 
	
		
			
				|  |  |                              {
 | 
	
		
			
				|  |  | -                                s.Number = setoutNumber;
 | 
	
		
			
				|  |  | -                                s.JobLink.ID = task.JobID;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                var notes = kanban.Notes.ToList();
 | 
	
		
			
				|  |  | -                                var description = kanban.Summary;
 | 
	
		
			
				|  |  | -                                if (string.IsNullOrWhiteSpace(description))
 | 
	
		
			
				|  |  | -                                {
 | 
	
		
			
				|  |  | -                                    description = CoreUtils.StripHTML(kanban.Description);
 | 
	
		
			
				|  |  | -                                }
 | 
	
		
			
				|  |  | -                                if (!string.IsNullOrWhiteSpace(description))
 | 
	
		
			
				|  |  | -                                {
 | 
	
		
			
				|  |  | -                                    notes.Insert(0, description);
 | 
	
		
			
				|  |  | -                                }
 | 
	
		
			
				|  |  | -                                s.Description = string.Join("\n==========================================\n", notes);
 | 
	
		
			
				|  |  | +                                notes.Insert(0, description);
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                        if (result != null)
 | 
	
		
			
				|  |  | +                            s.Description = string.Join("\n==========================================\n", notes);
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                    );
 | 
	
		
			
				|  |  | +                    if (result != null)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        Progress.ShowModal("Creating Manufacturing Packet", progress =>
 | 
	
		
			
				|  |  |                          {
 | 
	
		
			
				|  |  | -                            Progress.ShowModal("Creating Manufacturing Packet", progress =>
 | 
	
		
			
				|  |  | +                            ManufacturingPacket packet = new ManufacturingPacket()
 | 
	
		
			
				|  |  |                              {
 | 
	
		
			
				|  |  | -                                ManufacturingPacket packet = new ManufacturingPacket()
 | 
	
		
			
				|  |  | +                                Serial = template.Code,
 | 
	
		
			
				|  |  | +                                Title = kanban.Title,
 | 
	
		
			
				|  |  | +                                Quantity = 1,
 | 
	
		
			
				|  |  | +                                BarcodeQty = 1,
 | 
	
		
			
				|  |  | +                                DueDate = kanban.DueDate
 | 
	
		
			
				|  |  | +                            };
 | 
	
		
			
				|  |  | +                            packet.ManufacturingTemplateLink.ID = template.ID;
 | 
	
		
			
				|  |  | +                            packet.ManufacturingTemplateLink.Code = template.Code;
 | 
	
		
			
				|  |  | +                            packet.ManufacturingTemplateLink.Factory.ID = template.Factory.ID;
 | 
	
		
			
				|  |  | +                            packet.SetoutLink.ID = result.ID;
 | 
	
		
			
				|  |  | +                            new Client<ManufacturingPacket>().Save(packet, "Created from Task");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            DoLink<ManufacturingPacketKanban, ManufacturingPacket, ManufacturingPacketLink>(task, packet.ID);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            List<ManufacturingPacketStage> pstages = new List<ManufacturingPacketStage>();
 | 
	
		
			
				|  |  | +                            foreach (var tstage in tstages)
 | 
	
		
			
				|  |  | +                            {
 | 
	
		
			
				|  |  | +                                var pstage = new ManufacturingPacketStage()
 | 
	
		
			
				|  |  |                                  {
 | 
	
		
			
				|  |  | -                                    Serial = template.Code,
 | 
	
		
			
				|  |  | -                                    Title = kanban.Title,
 | 
	
		
			
				|  |  | -                                    Quantity = 1,
 | 
	
		
			
				|  |  | -                                    BarcodeQty = 1,
 | 
	
		
			
				|  |  | -                                    DueDate = kanban.DueDate
 | 
	
		
			
				|  |  | +                                    Time = tstage.Time,
 | 
	
		
			
				|  |  | +                                    Sequence = tstage.Sequence,
 | 
	
		
			
				|  |  | +                                    SequenceType = tstage.SequenceType,
 | 
	
		
			
				|  |  | +                                    Started = DateTime.MinValue,
 | 
	
		
			
				|  |  | +                                    PercentageComplete = 0.0F,
 | 
	
		
			
				|  |  | +                                    Completed = DateTime.MinValue,
 | 
	
		
			
				|  |  | +                                    QualityChecks = tstage.QualityChecks,
 | 
	
		
			
				|  |  | +                                    QualityStatus = QualityStatus.NotChecked,
 | 
	
		
			
				|  |  | +                                    QualityNotes = "",
 | 
	
		
			
				|  |  |                                  };
 | 
	
		
			
				|  |  | -                                packet.ManufacturingTemplateLink.ID = template.ID;
 | 
	
		
			
				|  |  | -                                packet.ManufacturingTemplateLink.Code = template.Code;
 | 
	
		
			
				|  |  | -                                packet.ManufacturingTemplateLink.Factory.ID = template.Factory.ID;
 | 
	
		
			
				|  |  | -                                packet.SetoutLink.ID = result.ID;
 | 
	
		
			
				|  |  | -                                new Client<ManufacturingPacket>().Save(packet, "Created from Task");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                DoLink<ManufacturingPacketKanban, ManufacturingPacket, ManufacturingPacketLink>(task, packet.ID);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                List<ManufacturingPacketStage> pstages = new List<ManufacturingPacketStage>();
 | 
	
		
			
				|  |  | -                                foreach (var tstage in tstages)
 | 
	
		
			
				|  |  | -                                {
 | 
	
		
			
				|  |  | -                                    var pstage = new ManufacturingPacketStage()
 | 
	
		
			
				|  |  | -                                    {
 | 
	
		
			
				|  |  | -                                        Time = tstage.Time,
 | 
	
		
			
				|  |  | -                                        Sequence = tstage.Sequence,
 | 
	
		
			
				|  |  | -                                        SequenceType = tstage.SequenceType,
 | 
	
		
			
				|  |  | -                                        Started = DateTime.MinValue,
 | 
	
		
			
				|  |  | -                                        PercentageComplete = 0.0F,
 | 
	
		
			
				|  |  | -                                        Completed = DateTime.MinValue,
 | 
	
		
			
				|  |  | -                                        QualityChecks = tstage.QualityChecks,
 | 
	
		
			
				|  |  | -                                        QualityStatus = QualityStatus.NotChecked,
 | 
	
		
			
				|  |  | -                                        QualityNotes = "",
 | 
	
		
			
				|  |  | -                                    };
 | 
	
		
			
				|  |  | -                                    pstage.Parent.ID = packet.ID;
 | 
	
		
			
				|  |  | -                                    pstage.ManufacturingSectionLink.ID = tstage.Section.ID;
 | 
	
		
			
				|  |  | -                                    pstage.ManufacturingSectionLink.Name = tstage.Section.Name;
 | 
	
		
			
				|  |  | -                                    pstages.Add(pstage);
 | 
	
		
			
				|  |  | -                                }
 | 
	
		
			
				|  |  | -                                new Client<ManufacturingPacketStage>().Save(pstages, "Created from Task", (_, __) => { });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                progress.Report("Processing Documents");
 | 
	
		
			
				|  |  | -                                List<SetoutDocument> _setoutdocuments = new List<SetoutDocument>();
 | 
	
		
			
				|  |  | -                                List<KanbanDocument> _kanbandocuments = new List<KanbanDocument>();
 | 
	
		
			
				|  |  | -                                KanbanDocument[] docrefs = new Client<KanbanDocument>()
 | 
	
		
			
				|  |  | -                                    .Load(new Filter<KanbanDocument>(x => x.EntityLink.ID).IsEqualTo(kanban.ID));
 | 
	
		
			
				|  |  | -                                foreach (var docref in docrefs)
 | 
	
		
			
				|  |  | -                                {
 | 
	
		
			
				|  |  | -                                    // Convert the document to a PDF
 | 
	
		
			
				|  |  | -                                    var docid = ProcessKanbanDocument(docref);
 | 
	
		
			
				|  |  | -                                    var newdoc = new SetoutDocument();
 | 
	
		
			
				|  |  | -                                    newdoc.EntityLink.ID = result.ID;
 | 
	
		
			
				|  |  | -                                    newdoc.DocumentLink.ID = docid;
 | 
	
		
			
				|  |  | -                                    _setoutdocuments.Add(newdoc);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                    if (docid != docref.DocumentLink.ID)
 | 
	
		
			
				|  |  | -                                    {
 | 
	
		
			
				|  |  | -                                        docref.DocumentLink.ID = docid;
 | 
	
		
			
				|  |  | -                                        _kanbandocuments.Add(docref);
 | 
	
		
			
				|  |  | -                                    }
 | 
	
		
			
				|  |  | -                                }
 | 
	
		
			
				|  |  | -                                new Client<SetoutDocument>().Save(_setoutdocuments, "Converted from Task", (_, __) => { });
 | 
	
		
			
				|  |  | -                                new Client<KanbanDocument>().Save(_kanbandocuments, "Converted to PDF", (_, __) => { });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                progress.Report("Updating Task");
 | 
	
		
			
				|  |  | -                                kanban.Title = kanban.Title + " (" + result.Number + ")";
 | 
	
		
			
				|  |  | -                                new Client<Kanban>().Save(kanban, "Converting Kanban to Setout");
 | 
	
		
			
				|  |  | -                            });
 | 
	
		
			
				|  |  | -                            control.Refresh();
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | -                    menu.AddItem("Create Requisition from Task", null, models, tasks =>
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        var taskModel = tasks.First();
 | 
	
		
			
				|  |  | -                        
 | 
	
		
			
				|  |  | -                        var kanbanTable = new Client<Kanban>().Query(new Filter<Kanban>(x => x.ID).IsEqualTo(taskModel.ID));
 | 
	
		
			
				|  |  | -                        var kanban = kanbanTable.Rows.First().ToObject<Kanban>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                        var result = CreateRequisition(
 | 
	
		
			
				|  |  | -                            taskModel,
 | 
	
		
			
				|  |  | -                            r =>
 | 
	
		
			
				|  |  | -                            {
 | 
	
		
			
				|  |  | -                                r.RequestedBy.ID = kanban.ManagerLink.ID;
 | 
	
		
			
				|  |  | -                                r.Employee.ID = Guid.Empty;
 | 
	
		
			
				|  |  | -                                r.Title = kanban.Title;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                r.Request = string.IsNullOrWhiteSpace(kanban.Summary)
 | 
	
		
			
				|  |  | -                                    ? String.IsNullOrWhiteSpace(kanban.Description)
 | 
	
		
			
				|  |  | -                                        ? String.Join("\n", kanban.Notes)
 | 
	
		
			
				|  |  | -                                        : CoreUtils.StripHTML(kanban.Description)
 | 
	
		
			
				|  |  | -                                    : kanban.Summary;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                r.Notes = kanban.Notes;
 | 
	
		
			
				|  |  | -                                r.Due = kanban.DueDate;
 | 
	
		
			
				|  |  | -                                r.JobLink.ID = taskModel.JobID;
 | 
	
		
			
				|  |  | +                                pstage.Parent.ID = packet.ID;
 | 
	
		
			
				|  |  | +                                pstage.ManufacturingSectionLink.ID = tstage.Section.ID;
 | 
	
		
			
				|  |  | +                                pstage.ManufacturingSectionLink.Name = tstage.Section.Name;
 | 
	
		
			
				|  |  | +                                pstages.Add(pstage);
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                        if (result != null)
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            Progress.ShowModal("Updating Documents", progress =>
 | 
	
		
			
				|  |  | +                            new Client<ManufacturingPacketStage>().Save(pstages, "Created from Task", (_, __) => { });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            progress.Report("Processing Documents");
 | 
	
		
			
				|  |  | +                            List<SetoutDocument> _setoutdocuments = new List<SetoutDocument>();
 | 
	
		
			
				|  |  | +                            List<KanbanDocument> _kanbandocuments = new List<KanbanDocument>();
 | 
	
		
			
				|  |  | +                            KanbanDocument[] docrefs = new Client<KanbanDocument>()
 | 
	
		
			
				|  |  | +                                .Load(new Filter<KanbanDocument>(x => x.EntityLink.ID).IsEqualTo(kanban.ID));
 | 
	
		
			
				|  |  | +                            foreach (var docref in docrefs)
 | 
	
		
			
				|  |  |                              {
 | 
	
		
			
				|  |  | -                                progress.Report("Updating Documents");
 | 
	
		
			
				|  |  | -                                List<RequisitionDocument> requiDocuments = new();
 | 
	
		
			
				|  |  | -                                KanbanDocument[] kanbanDocuments = new Client<KanbanDocument>()
 | 
	
		
			
				|  |  | -                                    .Load(new Filter<KanbanDocument>(x => x.EntityLink.ID).IsEqualTo(kanban.ID));
 | 
	
		
			
				|  |  | -                                foreach (var document in kanbanDocuments)
 | 
	
		
			
				|  |  | +                                // Convert the document to a PDF
 | 
	
		
			
				|  |  | +                                var docid = ProcessKanbanDocument(docref);
 | 
	
		
			
				|  |  | +                                var newdoc = new SetoutDocument();
 | 
	
		
			
				|  |  | +                                newdoc.EntityLink.ID = result.ID;
 | 
	
		
			
				|  |  | +                                newdoc.DocumentLink.ID = docid;
 | 
	
		
			
				|  |  | +                                _setoutdocuments.Add(newdoc);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                                if (docid != docref.DocumentLink.ID)
 | 
	
		
			
				|  |  |                                  {
 | 
	
		
			
				|  |  | -                                    var newdoc = new RequisitionDocument();
 | 
	
		
			
				|  |  | -                                    newdoc.EntityLink.ID = result.ID;
 | 
	
		
			
				|  |  | -                                    newdoc.DocumentLink.ID = document.DocumentLink.ID;
 | 
	
		
			
				|  |  | -                                    requiDocuments.Add(newdoc);
 | 
	
		
			
				|  |  | +                                    docref.DocumentLink.ID = docid;
 | 
	
		
			
				|  |  | +                                    _kanbandocuments.Add(docref);
 | 
	
		
			
				|  |  |                                  }
 | 
	
		
			
				|  |  | -                                new Client<RequisitionDocument>().Save(requiDocuments, "Converted from Task", (_, __) => { });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                /*RequisitionKanban link = new();
 | 
	
		
			
				|  |  | -                                link.Entity.ID = result.ID;
 | 
	
		
			
				|  |  | -                                link.Kanban.ID = kanban.ID;
 | 
	
		
			
				|  |  | -                                new Client<RequisitionKanban>().Save(link, "Converting Task -> Requisition", (_, __) => { });*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                progress.Report("Updating Task");
 | 
	
		
			
				|  |  | -                                kanban.Status = KanbanStatus.Open;
 | 
	
		
			
				|  |  | -                                kanban.Completed = DateTime.MinValue;
 | 
	
		
			
				|  |  | -                                kanban.Title += $" (Requi #{result.Number})";
 | 
	
		
			
				|  |  | -                                new Client<Kanban>().Save(kanban, "Converted to Requisition", (_, __) => { });
 | 
	
		
			
				|  |  | -                            });
 | 
	
		
			
				|  |  | -                            MessageWindow.ShowMessage($"Created Requisition {result.Number}", "Success");
 | 
	
		
			
				|  |  | -                            control.Refresh();
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | -                    menu.AddItem("Create Delivery from Task", null, models, tasks =>
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        var result = CreateDelivery(
 | 
	
		
			
				|  |  | -                            tasks.First(),
 | 
	
		
			
				|  |  | -                            d =>
 | 
	
		
			
				|  |  | -                            {
 | 
	
		
			
				|  |  | -                                // Post-Process Requi Here
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                        if (result != null)
 | 
	
		
			
				|  |  | -                            control.Refresh();
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | -                    menu.AddItem("Create Purchase Order from Task", null, models, tasks =>
 | 
	
		
			
				|  |  | +                            new Client<SetoutDocument>().Save(_setoutdocuments, "Converted from Task", (_, __) => { });
 | 
	
		
			
				|  |  | +                            new Client<KanbanDocument>().Save(_kanbandocuments, "Converted to PDF", (_, __) => { });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            progress.Report("Updating Task");
 | 
	
		
			
				|  |  | +                            kanban.Title = kanban.Title + " (" + result.Number + ")";
 | 
	
		
			
				|  |  | +                            new Client<Kanban>().Save(kanban, "Converting Kanban to Setout");
 | 
	
		
			
				|  |  | +                        });
 | 
	
		
			
				|  |  | +                        control.Refresh();
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                menu.AddItem("Create Requisition from Task", null, models, tasks =>
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var taskModel = tasks.First();
 | 
	
		
			
				|  |  | +                    
 | 
	
		
			
				|  |  | +                    var kanbanTable = new Client<Kanban>().Query(new Filter<Kanban>(x => x.ID).IsEqualTo(taskModel.ID));
 | 
	
		
			
				|  |  | +                    var kanban = kanbanTable.Rows.First().ToObject<Kanban>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    var result = CreateRequisition(
 | 
	
		
			
				|  |  | +                        taskModel,
 | 
	
		
			
				|  |  | +                        r =>
 | 
	
		
			
				|  |  | +                        {
 | 
	
		
			
				|  |  | +                            r.RequestedBy.ID = kanban.ManagerLink.ID;
 | 
	
		
			
				|  |  | +                            r.Employee.ID = Guid.Empty;
 | 
	
		
			
				|  |  | +                            r.Title = kanban.Title;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            r.Request = string.IsNullOrWhiteSpace(kanban.Summary)
 | 
	
		
			
				|  |  | +                                ? String.IsNullOrWhiteSpace(kanban.Description)
 | 
	
		
			
				|  |  | +                                    ? String.Join("\n", kanban.Notes)
 | 
	
		
			
				|  |  | +                                    : CoreUtils.StripHTML(kanban.Description)
 | 
	
		
			
				|  |  | +                                : kanban.Summary;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            r.Notes = kanban.Notes;
 | 
	
		
			
				|  |  | +                            r.Due = kanban.DueDate;
 | 
	
		
			
				|  |  | +                            r.JobLink.ID = taskModel.JobID;
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                    );
 | 
	
		
			
				|  |  | +                    if (result != null)
 | 
	
		
			
				|  |  |                      {
 | 
	
		
			
				|  |  | -                        var result = CreateOrder(
 | 
	
		
			
				|  |  | -                            tasks.First(),
 | 
	
		
			
				|  |  | -                            p =>
 | 
	
		
			
				|  |  | +                        Progress.ShowModal("Updating Documents", progress =>
 | 
	
		
			
				|  |  | +                        {
 | 
	
		
			
				|  |  | +                            progress.Report("Updating Documents");
 | 
	
		
			
				|  |  | +                            List<RequisitionDocument> requiDocuments = new();
 | 
	
		
			
				|  |  | +                            KanbanDocument[] kanbanDocuments = new Client<KanbanDocument>()
 | 
	
		
			
				|  |  | +                                .Load(new Filter<KanbanDocument>(x => x.EntityLink.ID).IsEqualTo(kanban.ID));
 | 
	
		
			
				|  |  | +                            foreach (var document in kanbanDocuments)
 | 
	
		
			
				|  |  |                              {
 | 
	
		
			
				|  |  | -                                // Post-Process Requi Here
 | 
	
		
			
				|  |  | +                                var newdoc = new RequisitionDocument();
 | 
	
		
			
				|  |  | +                                newdoc.EntityLink.ID = result.ID;
 | 
	
		
			
				|  |  | +                                newdoc.DocumentLink.ID = document.DocumentLink.ID;
 | 
	
		
			
				|  |  | +                                requiDocuments.Add(newdoc);
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                        if (result != null)
 | 
	
		
			
				|  |  | -                            control.Refresh();
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                            new Client<RequisitionDocument>().Save(requiDocuments, "Converted from Task", (_, __) => { });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            /*RequisitionKanban link = new();
 | 
	
		
			
				|  |  | +                            link.Entity.ID = result.ID;
 | 
	
		
			
				|  |  | +                            link.Kanban.ID = kanban.ID;
 | 
	
		
			
				|  |  | +                            new Client<RequisitionKanban>().Save(link, "Converting Task -> Requisition", (_, __) => { });*/
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            progress.Report("Updating Task");
 | 
	
		
			
				|  |  | +                            kanban.Status = KanbanStatus.Open;
 | 
	
		
			
				|  |  | +                            kanban.Completed = DateTime.MinValue;
 | 
	
		
			
				|  |  | +                            kanban.Title += $" (Requi #{result.Number})";
 | 
	
		
			
				|  |  | +                            new Client<Kanban>().Save(kanban, "Converted to Requisition", (_, __) => { });
 | 
	
		
			
				|  |  | +                        });
 | 
	
		
			
				|  |  | +                        MessageWindow.ShowMessage($"Created Requisition {result.Number}", "Success");
 | 
	
		
			
				|  |  | +                        control.Refresh();
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                menu.AddItem("Create Delivery from Task", null, models, tasks =>
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var result = CreateDelivery(
 | 
	
		
			
				|  |  | +                        tasks.First(),
 | 
	
		
			
				|  |  | +                        d =>
 | 
	
		
			
				|  |  | +                        {
 | 
	
		
			
				|  |  | +                            // Post-Process Requi Here
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                    );
 | 
	
		
			
				|  |  | +                    if (result != null)
 | 
	
		
			
				|  |  | +                        control.Refresh();
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                menu.AddItem("Create Purchase Order from Task", null, models, tasks =>
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var result = CreateOrder(
 | 
	
		
			
				|  |  | +                        tasks.First(),
 | 
	
		
			
				|  |  | +                        p =>
 | 
	
		
			
				|  |  | +                        {
 | 
	
		
			
				|  |  | +                            // Post-Process Requi Here
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                    );
 | 
	
		
			
				|  |  | +                    if (result != null)
 | 
	
		
			
				|  |  | +                        control.Refresh();
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (!bLinks && canChange)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                menu.Items.Add(new Separator());
 | 
	
		
			
				|  |  | +        if (!bLinks && canChange)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            menu.Items.Add(new Separator());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                var changeStatus = new MenuItem { Header = "Change Status" };
 | 
	
		
			
				|  |  | +            var changeStatus = new MenuItem { Header = "Change Status" };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                AddChangeStatusButton(control, models, changeStatus, "Open", KanbanStatus.Open);
 | 
	
		
			
				|  |  | -                AddChangeStatusButton(control, models, changeStatus, "In Progress", KanbanStatus.InProgress);
 | 
	
		
			
				|  |  | -                AddChangeStatusButton(control, models, changeStatus, "Waiting", KanbanStatus.Waiting);
 | 
	
		
			
				|  |  | +            AddChangeStatusButton(control, models, changeStatus, "Open", KanbanStatus.Open);
 | 
	
		
			
				|  |  | +            AddChangeStatusButton(control, models, changeStatus, "In Progress", KanbanStatus.InProgress);
 | 
	
		
			
				|  |  | +            AddChangeStatusButton(control, models, changeStatus, "Waiting", KanbanStatus.Waiting);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                if (models.Any(x => x.CompletedDate.IsEmpty()))
 | 
	
		
			
				|  |  | +            if (models.Any(x => x.CompletedDate.IsEmpty()))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                var complete = new MenuItem
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    Tag = models,
 | 
	
		
			
				|  |  | +                    Header = models.Length > 1 ? "Complete Tasks" : "Complete Task"
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +                complete.Click += (o, e) =>
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    var complete = new MenuItem
 | 
	
		
			
				|  |  | +                    CompleteTask(control, e, DateTime.Now);
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +                menu.Items.Add(complete);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (Security.IsAllowed<CanSetKanbanCompletedDate>())
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var completeDate = new MenuItem
 | 
	
		
			
				|  |  |                      {
 | 
	
		
			
				|  |  |                          Tag = models,
 | 
	
		
			
				|  |  | -                        Header = models.Length > 1 ? "Complete Tasks" : "Complete Task"
 | 
	
		
			
				|  |  | -                    };
 | 
	
		
			
				|  |  | -                    complete.Click += (o, e) =>
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        CompleteTask(control, e, DateTime.Now);
 | 
	
		
			
				|  |  | +                        Header = "Set Completed Date"
 | 
	
		
			
				|  |  |                      };
 | 
	
		
			
				|  |  | -                    menu.Items.Add(complete);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    if (Security.IsAllowed<CanSetKanbanCompletedDate>())
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        var completeDate = new MenuItem
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            Tag = models,
 | 
	
		
			
				|  |  | -                            Header = "Set Completed Date"
 | 
	
		
			
				|  |  | -                        };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                        var dateItem = new MenuItem();
 | 
	
		
			
				|  |  | +                    var dateItem = new MenuItem();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        var dateCalendar = new System.Windows.Controls.Calendar { SelectedDate = DateTime.MinValue };
 | 
	
		
			
				|  |  | -                        dateCalendar.Tag = models;
 | 
	
		
			
				|  |  | -                        dateCalendar.SelectedDatesChanged += (o, e) =>
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            if (e.Source is not System.Windows.Controls.Calendar calendar) return;
 | 
	
		
			
				|  |  | -                            menu.IsOpen = false;
 | 
	
		
			
				|  |  | +                    var dateCalendar = new System.Windows.Controls.Calendar { SelectedDate = DateTime.MinValue };
 | 
	
		
			
				|  |  | +                    dateCalendar.Tag = models;
 | 
	
		
			
				|  |  | +                    dateCalendar.SelectedDatesChanged += (o, e) =>
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        if (e.Source is not System.Windows.Controls.Calendar calendar) return;
 | 
	
		
			
				|  |  | +                        menu.IsOpen = false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                            var selectedDate = calendar.SelectedDate ?? DateTime.Now;
 | 
	
		
			
				|  |  | -                            CompleteTask(control, e, selectedDate);
 | 
	
		
			
				|  |  | -                        };
 | 
	
		
			
				|  |  | +                        var selectedDate = calendar.SelectedDate ?? DateTime.Now;
 | 
	
		
			
				|  |  | +                        CompleteTask(control, e, selectedDate);
 | 
	
		
			
				|  |  | +                    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        dateItem.Header = dateCalendar;
 | 
	
		
			
				|  |  | -                        dateItem.Style = Resources["calendarItem"] as Style;
 | 
	
		
			
				|  |  | +                    dateItem.Header = dateCalendar;
 | 
	
		
			
				|  |  | +                    dateItem.Style = Resources["calendarItem"] as Style;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        completeDate.Items.Add(dateItem);
 | 
	
		
			
				|  |  | +                    completeDate.Items.Add(dateItem);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        menu.Items.Add(completeDate);
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | +                    menu.Items.Add(completeDate);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | -                else
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                menu.AddItem(models.Length > 1 ? "Archive Tasks" : "Archive Task", null, models, tasks =>
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    menu.AddItem(models.Length > 1 ? "Archive Tasks" : "Archive Task", null, models, tasks =>
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        if (!MessageWindow.ShowYesNo("Are you sure you want to remove the selected tasks from the list?", "Confirm removal"))
 | 
	
		
			
				|  |  | -                            return;
 | 
	
		
			
				|  |  | +                    if (!MessageWindow.ShowYesNo("Are you sure you want to remove the selected tasks from the list?", "Confirm removal"))
 | 
	
		
			
				|  |  | +                        return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        Progress.ShowModal("Closing Kanbans", progress =>
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            var kanbans = LoadKanbans(tasks, Columns.Required<Kanban>().Add(x => x.ID, x => x.Closed));
 | 
	
		
			
				|  |  | -                            foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  | -                                kanban.Closed = DateTime.Now;
 | 
	
		
			
				|  |  | -                            new Client<Kanban>().Save(kanbans, "Kanban Marked as Closed");
 | 
	
		
			
				|  |  | -                        });
 | 
	
		
			
				|  |  | -                        control.Refresh();
 | 
	
		
			
				|  |  | +                    Progress.ShowModal("Closing Kanbans", progress =>
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        var kanbans = LoadKanbans(tasks, Columns.Required<Kanban>().Add(x => x.ID, x => x.Closed));
 | 
	
		
			
				|  |  | +                        foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  | +                            kanban.Closed = DateTime.Now;
 | 
	
		
			
				|  |  | +                        new Client<Kanban>().Save(kanbans, "Kanban Marked as Closed");
 | 
	
		
			
				|  |  |                      });
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                    control.Refresh();
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                menu.Items.Add(changeStatus);
 | 
	
		
			
				|  |  | +            menu.Items.Add(changeStatus);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                var changeType = new MenuItem { Header = "Change Task Type", Tag = models };
 | 
	
		
			
				|  |  | +            var changeType = new MenuItem { Header = "Change Task Type", Tag = models };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                foreach(var type in KanbanTypes)
 | 
	
		
			
				|  |  | +            foreach(var type in KanbanTypes)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                changeType.AddItem($"{type.Code}: {type.Description}", null, type, type =>
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    changeType.AddItem($"{type.Code}: {type.Description}", null, type, type =>
 | 
	
		
			
				|  |  | +                    Progress.ShowModal("Changing Task Type", progress =>
 | 
	
		
			
				|  |  |                      {
 | 
	
		
			
				|  |  | -                        Progress.ShowModal("Changing Task Type", progress =>
 | 
	
		
			
				|  |  | +                        var kanbans = LoadKanbans(models, Columns.Required<Kanban>().Add(x => x.ID, x => x.Type.ID));
 | 
	
		
			
				|  |  | +                        foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  |                          {
 | 
	
		
			
				|  |  | -                            var kanbans = LoadKanbans(models, Columns.Required<Kanban>().Add(x => x.ID, x => x.Type.ID));
 | 
	
		
			
				|  |  | -                            foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  | -                            {
 | 
	
		
			
				|  |  | -                                kanban.Type.ID = type.ID;
 | 
	
		
			
				|  |  | -                            }
 | 
	
		
			
				|  |  | +                            kanban.Type.ID = type.ID;
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                            new Client<Kanban>().Save(kanbans, $"Kanban Task Type changed to {type}");
 | 
	
		
			
				|  |  | -                        });
 | 
	
		
			
				|  |  | -                        control.Refresh();
 | 
	
		
			
				|  |  | +                        new Client<Kanban>().Save(kanbans, $"Kanban Task Type changed to {type}");
 | 
	
		
			
				|  |  |                      });
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                    control.Refresh();
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                menu.Items.Add(changeType);
 | 
	
		
			
				|  |  | +            menu.Items.Add(changeType);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                var changeDueDate = new MenuItem { Header = "Change Due Date" };
 | 
	
		
			
				|  |  | +            var changeDueDate = new MenuItem { Header = "Change Due Date" };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                var calendarItem = new MenuItem();
 | 
	
		
			
				|  |  | +            var calendarItem = new MenuItem();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                var calendar = new System.Windows.Controls.Calendar { SelectedDate = models.Length == 1 ? models[0].DueDate : DateTime.Today };
 | 
	
		
			
				|  |  | -                calendar.Tag = models;
 | 
	
		
			
				|  |  | -                calendar.SelectedDatesChanged += (o, e) =>
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    if (e.Source is not System.Windows.Controls.Calendar calendar) return;
 | 
	
		
			
				|  |  | +            var calendar = new System.Windows.Controls.Calendar { SelectedDate = models.Length == 1 ? models[0].DueDate : DateTime.Today };
 | 
	
		
			
				|  |  | +            calendar.Tag = models;
 | 
	
		
			
				|  |  | +            calendar.SelectedDatesChanged += (o, e) =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                if (e.Source is not System.Windows.Controls.Calendar calendar) return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    var selectedDate = calendar.SelectedDate ?? DateTime.Now;
 | 
	
		
			
				|  |  | -                    var models = (calendar.Tag as IList<TaskModel>)!;
 | 
	
		
			
				|  |  | -                    Progress.ShowModal("Changing Due Date", progress =>
 | 
	
		
			
				|  |  | +                var selectedDate = calendar.SelectedDate ?? DateTime.Now;
 | 
	
		
			
				|  |  | +                var models = (calendar.Tag as IList<TaskModel>)!;
 | 
	
		
			
				|  |  | +                Progress.ShowModal("Changing Due Date", progress =>
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var kanbans = LoadKanbans(models, Columns.Required<Kanban>().Add(x => x.ID, x => x.DueDate));
 | 
	
		
			
				|  |  | +                    foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  |                      {
 | 
	
		
			
				|  |  | -                        var kanbans = LoadKanbans(models, Columns.Required<Kanban>().Add(x => x.ID, x => x.DueDate));
 | 
	
		
			
				|  |  | -                        foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            kanban.DueDate = selectedDate;
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | +                        kanban.DueDate = selectedDate;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        new Client<Kanban>().Save(kanbans, $"Kanban Due Date changed to {selectedDate:dd MMM yyyy}");
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | -                    control.Refresh();
 | 
	
		
			
				|  |  | +                    new Client<Kanban>().Save(kanbans, $"Kanban Due Date changed to {selectedDate:dd MMM yyyy}");
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                control.Refresh();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    menu.IsOpen = false;
 | 
	
		
			
				|  |  | -                };
 | 
	
		
			
				|  |  | +                menu.IsOpen = false;
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                calendarItem.Header = calendar;
 | 
	
		
			
				|  |  | -                calendarItem.Style = Resources["calendarItem"] as Style;
 | 
	
		
			
				|  |  | +            calendarItem.Header = calendar;
 | 
	
		
			
				|  |  | +            calendarItem.Style = Resources["calendarItem"] as Style;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                changeDueDate.Items.Add(calendarItem);
 | 
	
		
			
				|  |  | +            changeDueDate.Items.Add(calendarItem);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                menu.Items.Add(changeDueDate);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            menu.Items.Add(changeDueDate);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /// <summary>
 | 
	
		
			
				|  |  | -        /// Takes a <see cref="KanbanDocument"/>, and if it is a .txt or an image (".png", ".jpg", ".jpeg" or ".bmp"), converts to a PDF
 | 
	
		
			
				|  |  | -        /// with the content of the document, saving a new document with extension changed to ".pdf".
 | 
	
		
			
				|  |  | -        /// </summary>
 | 
	
		
			
				|  |  | -        /// <param name="docref">The original document.</param>
 | 
	
		
			
				|  |  | -        /// <returns>
 | 
	
		
			
				|  |  | -        /// The ID of the new <see cref="Document"/> or,
 | 
	
		
			
				|  |  | -        /// if not one of the given types, the original document ID.
 | 
	
		
			
				|  |  | -        /// </returns>
 | 
	
		
			
				|  |  | -        private static Guid ProcessKanbanDocument(KanbanDocument docref)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var result = docref.DocumentLink.ID;
 | 
	
		
			
				|  |  | +    /// <summary>
 | 
	
		
			
				|  |  | +    /// Takes a <see cref="KanbanDocument"/>, and if it is a .txt or an image (".png", ".jpg", ".jpeg" or ".bmp"), converts to a PDF
 | 
	
		
			
				|  |  | +    /// with the content of the document, saving a new document with extension changed to ".pdf".
 | 
	
		
			
				|  |  | +    /// </summary>
 | 
	
		
			
				|  |  | +    /// <param name="docref">The original document.</param>
 | 
	
		
			
				|  |  | +    /// <returns>
 | 
	
		
			
				|  |  | +    /// The ID of the new <see cref="Document"/> or,
 | 
	
		
			
				|  |  | +    /// if not one of the given types, the original document ID.
 | 
	
		
			
				|  |  | +    /// </returns>
 | 
	
		
			
				|  |  | +    private static Guid ProcessKanbanDocument(KanbanDocument docref)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = docref.DocumentLink.ID;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            var ext = System.IO.Path.GetExtension(docref.DocumentLink.FileName).ToLower();
 | 
	
		
			
				|  |  | +        var ext = System.IO.Path.GetExtension(docref.DocumentLink.FileName).ToLower();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (ext.EndsWith("txt"))
 | 
	
		
			
				|  |  | +        if (ext.EndsWith("txt"))
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(docref.DocumentLink.ID)).FirstOrDefault();
 | 
	
		
			
				|  |  | +            if (doc is null)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                var doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(docref.DocumentLink.ID)).FirstOrDefault();
 | 
	
		
			
				|  |  | -                if (doc is null)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    Logger.Send(LogType.Error, "", $"Document {docref.DocumentLink.ID} does not exist!");
 | 
	
		
			
				|  |  | -                    return docref.DocumentLink.ID;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                PdfDocument pdf = new PdfDocument();
 | 
	
		
			
				|  |  | -                PdfPage page = pdf.Pages.Add();
 | 
	
		
			
				|  |  | -                PdfGraphics graphics = page.Graphics;
 | 
	
		
			
				|  |  | -                PdfFont font = new PdfStandardFont(PdfFontFamily.Courier, 12);
 | 
	
		
			
				|  |  | -                String text = System.Text.Encoding.UTF8.GetString(doc.Data);
 | 
	
		
			
				|  |  | -                graphics.DrawString(text, font, PdfBrushes.Black, new PointF(0, 0));
 | 
	
		
			
				|  |  | -                MemoryStream ms = new MemoryStream();
 | 
	
		
			
				|  |  | -                pdf.Save(ms);
 | 
	
		
			
				|  |  | -                pdf.Close(true);
 | 
	
		
			
				|  |  | -                byte[] data = ms.ToArray();
 | 
	
		
			
				|  |  | -                var newdoc = new Document()
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    Data = data,
 | 
	
		
			
				|  |  | -                    FileName = System.IO.Path.ChangeExtension(docref.DocumentLink.FileName, "pdf"),
 | 
	
		
			
				|  |  | -                    CRC = CoreUtils.CalculateCRC(data),
 | 
	
		
			
				|  |  | -                    TimeStamp = DateTime.Now,
 | 
	
		
			
				|  |  | -                };
 | 
	
		
			
				|  |  | -                new Client<Document>().Save(newdoc, "Converted from Text");
 | 
	
		
			
				|  |  | -                return newdoc.ID;
 | 
	
		
			
				|  |  | +                Logger.Send(LogType.Error, "", $"Document {docref.DocumentLink.ID} does not exist!");
 | 
	
		
			
				|  |  | +                return docref.DocumentLink.ID;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            else if (ext.EndsWith("png") || ext.EndsWith("bmp") || ext.EndsWith("jpg") || ext.EndsWith("jpeg"))
 | 
	
		
			
				|  |  | +            PdfDocument pdf = new PdfDocument();
 | 
	
		
			
				|  |  | +            PdfPage page = pdf.Pages.Add();
 | 
	
		
			
				|  |  | +            PdfGraphics graphics = page.Graphics;
 | 
	
		
			
				|  |  | +            PdfFont font = new PdfStandardFont(PdfFontFamily.Courier, 12);
 | 
	
		
			
				|  |  | +            String text = System.Text.Encoding.UTF8.GetString(doc.Data);
 | 
	
		
			
				|  |  | +            graphics.DrawString(text, font, PdfBrushes.Black, new PointF(0, 0));
 | 
	
		
			
				|  |  | +            MemoryStream ms = new MemoryStream();
 | 
	
		
			
				|  |  | +            pdf.Save(ms);
 | 
	
		
			
				|  |  | +            pdf.Close(true);
 | 
	
		
			
				|  |  | +            byte[] data = ms.ToArray();
 | 
	
		
			
				|  |  | +            var newdoc = new Document()
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                var doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(docref.DocumentLink.ID)).FirstOrDefault();
 | 
	
		
			
				|  |  | -                if (doc is null)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    Logger.Send(LogType.Error, "", $"Document {docref.DocumentLink.ID} does not exist!");
 | 
	
		
			
				|  |  | -                    return docref.DocumentLink.ID;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                Data = data,
 | 
	
		
			
				|  |  | +                FileName = System.IO.Path.ChangeExtension(docref.DocumentLink.FileName, "pdf"),
 | 
	
		
			
				|  |  | +                CRC = CoreUtils.CalculateCRC(data),
 | 
	
		
			
				|  |  | +                TimeStamp = DateTime.Now,
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            new Client<Document>().Save(newdoc, "Converted from Text");
 | 
	
		
			
				|  |  | +            return newdoc.ID;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                PdfBitmap image = new PdfBitmap(new MemoryStream(doc.Data));
 | 
	
		
			
				|  |  | -                PdfDocument pdf = new PdfDocument();
 | 
	
		
			
				|  |  | -                pdf.PageSettings.Orientation = image.Height > image.Width ? PdfPageOrientation.Portrait : PdfPageOrientation.Landscape;
 | 
	
		
			
				|  |  | -                pdf.PageSettings.Size = new SizeF(image.Width, image.Height);
 | 
	
		
			
				|  |  | -                PdfPage page = pdf.Pages.Add();
 | 
	
		
			
				|  |  | -                PdfGraphics graphics = page.Graphics;
 | 
	
		
			
				|  |  | -                graphics.DrawImage(image, 0.0F, 0.0F);
 | 
	
		
			
				|  |  | -                MemoryStream ms = new MemoryStream();
 | 
	
		
			
				|  |  | -                pdf.Save(ms);
 | 
	
		
			
				|  |  | -                pdf.Close(true);
 | 
	
		
			
				|  |  | -                byte[] data = ms.ToArray();
 | 
	
		
			
				|  |  | -                var newdoc = new Document()
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    Data = data,
 | 
	
		
			
				|  |  | -                    FileName = System.IO.Path.ChangeExtension(docref.DocumentLink.FileName, "pdf"),
 | 
	
		
			
				|  |  | -                    CRC = CoreUtils.CalculateCRC(data),
 | 
	
		
			
				|  |  | -                    TimeStamp = DateTime.Now,
 | 
	
		
			
				|  |  | -                };
 | 
	
		
			
				|  |  | -                new Client<Document>().Save(newdoc, "Converted from Image");
 | 
	
		
			
				|  |  | -                return newdoc.ID;
 | 
	
		
			
				|  |  | +        else if (ext.EndsWith("png") || ext.EndsWith("bmp") || ext.EndsWith("jpg") || ext.EndsWith("jpeg"))
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(docref.DocumentLink.ID)).FirstOrDefault();
 | 
	
		
			
				|  |  | +            if (doc is null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Logger.Send(LogType.Error, "", $"Document {docref.DocumentLink.ID} does not exist!");
 | 
	
		
			
				|  |  | +                return docref.DocumentLink.ID;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  | +            PdfBitmap image = new PdfBitmap(new MemoryStream(doc.Data));
 | 
	
		
			
				|  |  | +            PdfDocument pdf = new PdfDocument();
 | 
	
		
			
				|  |  | +            pdf.PageSettings.Orientation = image.Height > image.Width ? PdfPageOrientation.Portrait : PdfPageOrientation.Landscape;
 | 
	
		
			
				|  |  | +            pdf.PageSettings.Size = new SizeF(image.Width, image.Height);
 | 
	
		
			
				|  |  | +            PdfPage page = pdf.Pages.Add();
 | 
	
		
			
				|  |  | +            PdfGraphics graphics = page.Graphics;
 | 
	
		
			
				|  |  | +            graphics.DrawImage(image, 0.0F, 0.0F);
 | 
	
		
			
				|  |  | +            MemoryStream ms = new MemoryStream();
 | 
	
		
			
				|  |  | +            pdf.Save(ms);
 | 
	
		
			
				|  |  | +            pdf.Close(true);
 | 
	
		
			
				|  |  | +            byte[] data = ms.ToArray();
 | 
	
		
			
				|  |  | +            var newdoc = new Document()
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Data = data,
 | 
	
		
			
				|  |  | +                FileName = System.IO.Path.ChangeExtension(docref.DocumentLink.FileName, "pdf"),
 | 
	
		
			
				|  |  | +                CRC = CoreUtils.CalculateCRC(data),
 | 
	
		
			
				|  |  | +                TimeStamp = DateTime.Now,
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            new Client<Document>().Save(newdoc, "Converted from Image");
 | 
	
		
			
				|  |  | +            return newdoc.ID;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        private void CreateJobSubMenu(ITaskControl control, MenuItem job, IEnumerable<TaskModel> tasks)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    private void CreateJobSubMenu(ITaskControl control, MenuItem job, IEnumerable<TaskModel> tasks)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        job.Items.Clear();
 | 
	
		
			
				|  |  | +        job.Items.Add(new MenuItem { Header = "Loading...", IsEnabled = false });
 | 
	
		
			
				|  |  | +        using (new WaitCursor())
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              job.Items.Clear();
 | 
	
		
			
				|  |  | -            job.Items.Add(new MenuItem { Header = "Loading...", IsEnabled = false });
 | 
	
		
			
				|  |  | -            using (new WaitCursor())
 | 
	
		
			
				|  |  | +            var jobs = new Client<Job>().Query(
 | 
	
		
			
				|  |  | +                LookupFactory.DefineFilter<Job>(),
 | 
	
		
			
				|  |  | +                LookupFactory.DefineColumns<Job>(),
 | 
	
		
			
				|  |  | +                LookupFactory.DefineSort<Job>()
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +            foreach (var row in jobs.Rows)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                job.Items.Clear();
 | 
	
		
			
				|  |  | -                var jobs = new Client<Job>().Query(
 | 
	
		
			
				|  |  | -                    LookupFactory.DefineFilter<Job>(),
 | 
	
		
			
				|  |  | -                    LookupFactory.DefineColumns<Job>(),
 | 
	
		
			
				|  |  | -                    LookupFactory.DefineSort<Job>()
 | 
	
		
			
				|  |  | -                );
 | 
	
		
			
				|  |  | -                foreach (var row in jobs.Rows)
 | 
	
		
			
				|  |  | +                var jobNumber = row.Get<Job, string>(x => x.JobNumber);
 | 
	
		
			
				|  |  | +                var jobName = row.Get<Job, string>(x => x.Name);
 | 
	
		
			
				|  |  | +                job.AddItem($"{jobNumber}: {jobName}", null, tasks, tasks =>
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    var jobNumber = row.Get<Job, string>(x => x.JobNumber);
 | 
	
		
			
				|  |  | -                    var jobName = row.Get<Job, string>(x => x.Name);
 | 
	
		
			
				|  |  | -                    job.AddItem($"{jobNumber}: {jobName}", null, tasks, tasks =>
 | 
	
		
			
				|  |  | +                    using (new WaitCursor())
 | 
	
		
			
				|  |  |                      {
 | 
	
		
			
				|  |  | -                        using (new WaitCursor())
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            var kanbans = LoadKanbans(tasks, Columns.Required<Kanban>().Add(x => x.ID, x => x.JobLink.ID));
 | 
	
		
			
				|  |  | -                            foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  | -                                kanban.JobLink.ID = row.Get<Job, Guid>(x => x.ID);
 | 
	
		
			
				|  |  | -                            new Client<Kanban>().Save(kanbans, "Updated Job Number");
 | 
	
		
			
				|  |  | -                            control.Refresh();
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                        var kanbans = LoadKanbans(tasks, Columns.Required<Kanban>().Add(x => x.ID, x => x.JobLink.ID));
 | 
	
		
			
				|  |  | +                        foreach (var kanban in kanbans)
 | 
	
		
			
				|  |  | +                            kanban.JobLink.ID = row.Get<Job, Guid>(x => x.ID);
 | 
	
		
			
				|  |  | +                        new Client<Kanban>().Save(kanbans, "Updated Job Number");
 | 
	
		
			
				|  |  | +                        control.Refresh();
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        #endregion
 | 
	
		
			
				|  |  | +    #endregion
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private void TaskPanels_SelectionChanged(object sender, SelectionChangedEventArgs e)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            if (!IsReady)
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | +    private void TaskPanels_SelectionChanged(object sender, SelectionChangedEventArgs e)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (!IsReady)
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (e.Source is not TabControl)
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | +        if (e.Source is not TabControl)
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (_bTabChanging)
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            try
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                _bTabChanging = true;
 | 
	
		
			
				|  |  | -                var panel = GetCurrentPanel();
 | 
	
		
			
				|  |  | -                if(panel is not null)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    KanbanSettings.ViewType = panel.KanbanViewType;
 | 
	
		
			
				|  |  | -                    new UserConfiguration<KanbanSettings>().Save(KanbanSettings);
 | 
	
		
			
				|  |  | -                    panel.Refresh();
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            finally
 | 
	
		
			
				|  |  | +        if (_bTabChanging)
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        try
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            _bTabChanging = true;
 | 
	
		
			
				|  |  | +            var panel = GetCurrentPanel();
 | 
	
		
			
				|  |  | +            if(panel is not null)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                _bTabChanging = false;
 | 
	
		
			
				|  |  | +                KanbanSettings.ViewType = panel.KanbanViewType;
 | 
	
		
			
				|  |  | +                new UserConfiguration<KanbanSettings>().Save(KanbanSettings);
 | 
	
		
			
				|  |  | +                panel.Refresh();
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        finally
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            _bTabChanging = false;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        #region Get/Save Settings
 | 
	
		
			
				|  |  | +    #region Get/Save Settings
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private KanbanSettings? _settings;
 | 
	
		
			
				|  |  | +    private KanbanSettings? _settings;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public KanbanSettings KanbanSettings
 | 
	
		
			
				|  |  | +    public KanbanSettings KanbanSettings
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        get
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            get
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                _settings ??= new UserConfiguration<KanbanSettings>().Load();
 | 
	
		
			
				|  |  | -                return _settings;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            _settings ??= new UserConfiguration<KanbanSettings>().Load();
 | 
	
		
			
				|  |  | +            return _settings;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void SaveSettings()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            if(_settings != null)
 | 
	
		
			
				|  |  | -                new UserConfiguration<KanbanSettings>().Save(_settings);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public void SaveSettings()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if(_settings != null)
 | 
	
		
			
				|  |  | +            new UserConfiguration<KanbanSettings>().Save(_settings);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        #endregion
 | 
	
		
			
				|  |  | +    #endregion
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        #region IPanel Stuff
 | 
	
		
			
				|  |  | +    #region IPanel Stuff
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public event DataModelUpdateEvent? OnUpdateDataModel;
 | 
	
		
			
				|  |  | +    public event DataModelUpdateEvent? OnUpdateDataModel;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public bool IsReady { get; set; }
 | 
	
		
			
				|  |  | +    public bool IsReady { get; set; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void CreateToolbarButtons(IPanelHost host)
 | 
	
		
			
				|  |  | +    public void CreateToolbarButtons(IPanelHost host)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        host.CreatePanelAction(
 | 
	
		
			
				|  |  | +            new PanelAction
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Caption = "New Task",
 | 
	
		
			
				|  |  | +                OnExecute = a => {
 | 
	
		
			
				|  |  | +                    if(CreateKanban(k => { }) != null)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        Refresh();
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                },
 | 
	
		
			
				|  |  | +                Image = InABox.Wpf.Resources.add
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        if (Security.CanView<KanbanType>())
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            host.CreatePanelAction(
 | 
	
		
			
				|  |  | +            host.CreateSetupAction(
 | 
	
		
			
				|  |  |                  new PanelAction
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    Caption = "New Task",
 | 
	
		
			
				|  |  | -                    OnExecute = a => {
 | 
	
		
			
				|  |  | -                        if(CreateKanban(k => { }) != null)
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            Refresh();
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    },
 | 
	
		
			
				|  |  | -                    Image = InABox.Wpf.Resources.add
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            );
 | 
	
		
			
				|  |  | -            if (Security.CanView<KanbanType>())
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                host.CreateSetupAction(
 | 
	
		
			
				|  |  | -                    new PanelAction
 | 
	
		
			
				|  |  | +                    Caption = "Task Types",
 | 
	
		
			
				|  |  | +                    Image = PRSDesktop.Resources.kanbantype,
 | 
	
		
			
				|  |  | +                    OnExecute = a =>
 | 
	
		
			
				|  |  |                      {
 | 
	
		
			
				|  |  | -                        Caption = "Task Types",
 | 
	
		
			
				|  |  | -                        Image = PRSDesktop.Resources.kanbantype,
 | 
	
		
			
				|  |  | -                        OnExecute = a =>
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            var list = new MasterList(typeof(KanbanType));
 | 
	
		
			
				|  |  | -                            list.ShowDialog();
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +                        var list = new MasterList(typeof(KanbanType));
 | 
	
		
			
				|  |  | +                        list.ShowDialog();
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public Dictionary<string, object[]> Selected()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            return new Dictionary<string, object[]>();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public Dictionary<string, object[]> Selected()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return new Dictionary<string, object[]>();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void Heartbeat(TimeSpan time)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public void Heartbeat(TimeSpan time)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private readonly Dictionary<KanbanViewType, TabItem> _viewmap = new();
 | 
	
		
			
				|  |  | +    private readonly Dictionary<KanbanViewType, TabItem> _viewmap = new();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private readonly List<ITaskControl> _initialized = new();
 | 
	
		
			
				|  |  | +    private readonly List<ITaskControl> _initialized = new();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private ITaskControl GetCurrentPanel()
 | 
	
		
			
				|  |  | +    private ITaskControl GetCurrentPanel()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = (TaskPanels.SelectedContent as ITaskControl)!;
 | 
	
		
			
				|  |  | +        if (result == null)
 | 
	
		
			
				|  |  | +            result = (TaskPanels.Items[0] as DynamicTabItem)?.Content as ITaskControl;
 | 
	
		
			
				|  |  | +        try
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var result = (TaskPanels.SelectedContent as ITaskControl)!;
 | 
	
		
			
				|  |  | -            if (result == null)
 | 
	
		
			
				|  |  | -                result = (TaskPanels.Items[0] as DynamicTabItem)?.Content as ITaskControl;
 | 
	
		
			
				|  |  | -            try
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                //if (result != null)
 | 
	
		
			
				|  |  | -                if (!_initialized.Contains(result))
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    result.Setup();
 | 
	
		
			
				|  |  | -                    result.IsReady = true;
 | 
	
		
			
				|  |  | -                    _initialized.Add(result);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            catch (Exception e)
 | 
	
		
			
				|  |  | +            //if (result != null)
 | 
	
		
			
				|  |  | +            if (!_initialized.Contains(result))
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                Logger.Send(LogType.Error, "", $"Error in TaskPanel.GetCurrentPanel: {CoreUtils.FormatException(e)}");
 | 
	
		
			
				|  |  | +                result.Setup();
 | 
	
		
			
				|  |  | +                result.IsReady = true;
 | 
	
		
			
				|  |  | +                _initialized.Add(result);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public void Setup()
 | 
	
		
			
				|  |  | +        catch (Exception e)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            _settings = new UserConfiguration<KanbanSettings>().Load();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +            Logger.Send(LogType.Error, "", $"Error in TaskPanel.GetCurrentPanel: {CoreUtils.FormatException(e)}");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            TaskPanels.SelectedItem = _viewmap[_settings.ViewType];
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            kanbanTypes = new Client<KanbanType>()
 | 
	
		
			
				|  |  | -                .Query(
 | 
	
		
			
				|  |  | -                    new Filter<KanbanType>(x => x.Hidden).IsEqualTo(false),
 | 
	
		
			
				|  |  | -                    Columns.None<KanbanType>().Add(x => x.ID, x => x.Code, x => x.Description))
 | 
	
		
			
				|  |  | -                .Rows.Select(x => x.ToObject<KanbanType>()).ToArray();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public void Setup()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        _settings = new UserConfiguration<KanbanSettings>().Load();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void Shutdown(CancelEventArgs? cancel)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void Refresh()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            if (Master == null)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                if (Equals(TaskPanels.SelectedItem, TasksPlannerTabItem))
 | 
	
		
			
				|  |  | -                    TaskPanels.SelectedItem = _viewmap[KanbanViewType.Status];
 | 
	
		
			
				|  |  | -                TasksPlannerTabItem.Visibility = Visibility.Collapsed;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else
 | 
	
		
			
				|  |  | -                TasksPlannerTabItem.Visibility = Visibility.Visible;
 | 
	
		
			
				|  |  | -            
 | 
	
		
			
				|  |  | -            GetCurrentPanel()?.Refresh();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        TaskPanels.SelectedItem = _viewmap[_settings.ViewType];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public string SectionName => GetCurrentPanel().SectionName;
 | 
	
		
			
				|  |  | +        kanbanTypes = new Client<KanbanType>()
 | 
	
		
			
				|  |  | +            .Query(
 | 
	
		
			
				|  |  | +                new Filter<KanbanType>(x => x.Hidden).IsEqualTo(false),
 | 
	
		
			
				|  |  | +                Columns.None<KanbanType>().Add(x => x.ID, x => x.Code, x => x.Description))
 | 
	
		
			
				|  |  | +            .Rows.Select(x => x.ToObject<KanbanType>()).ToArray();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public TaskPanelProperties Properties { get; set; }
 | 
	
		
			
				|  |  | +    public void Shutdown(CancelEventArgs? cancel)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public DataModel DataModel(Selection selection)
 | 
	
		
			
				|  |  | +    public void Refresh()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (Master == null)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            return GetCurrentPanel().DataModel(selection);
 | 
	
		
			
				|  |  | -            //return new AutoDataModel<Kanban>(new Filter<Kanban>(x => x.ID).IsEqualTo(Guid.Empty));
 | 
	
		
			
				|  |  | +            if (Equals(TaskPanels.SelectedItem, TasksPlannerTabItem))
 | 
	
		
			
				|  |  | +                TaskPanels.SelectedItem = _viewmap[KanbanViewType.Status];
 | 
	
		
			
				|  |  | +            TasksPlannerTabItem.Visibility = Visibility.Collapsed;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        else
 | 
	
		
			
				|  |  | +            TasksPlannerTabItem.Visibility = Visibility.Visible;
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        GetCurrentPanel()?.Refresh();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        #endregion
 | 
	
		
			
				|  |  | +    public string SectionName => GetCurrentPanel().SectionName;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        #region CRUD Functionality
 | 
	
		
			
				|  |  | +    public TaskPanelProperties Properties { get; set; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private TEntity? DoCreate<TEntity>(Action<TEntity> customise)
 | 
	
		
			
				|  |  | -            where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var result = new TEntity();
 | 
	
		
			
				|  |  | -            customise?.Invoke(result);
 | 
	
		
			
				|  |  | -            if (DoEdit(new[] { result }, null))
 | 
	
		
			
				|  |  | -                return result;
 | 
	
		
			
				|  |  | -            return null;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public DataModel DataModel(Selection selection)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return GetCurrentPanel().DataModel(selection);
 | 
	
		
			
				|  |  | +        //return new AutoDataModel<Kanban>(new Filter<Kanban>(x => x.ID).IsEqualTo(Guid.Empty));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private readonly Dictionary<Type, IDynamicGrid> _grids = new();
 | 
	
		
			
				|  |  | +    #endregion
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private readonly List<Tuple<Guid, Entity>> _entitycache = new();
 | 
	
		
			
				|  |  | +    #region CRUD Functionality
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private DynamicDataGrid<TEntity> GetGrid<TEntity>() where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            if(!_grids.TryGetValue(typeof(TEntity), out var grid))
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                grid = (DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(TEntity)) as DynamicDataGrid<TEntity>)!;
 | 
	
		
			
				|  |  | -                _grids[typeof(TEntity)] = grid;
 | 
	
		
			
				|  |  | +    private TEntity? DoCreate<TEntity>(Action<TEntity> customise)
 | 
	
		
			
				|  |  | +        where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = new TEntity();
 | 
	
		
			
				|  |  | +        customise?.Invoke(result);
 | 
	
		
			
				|  |  | +        if (DoEdit(new[] { result }, null))
 | 
	
		
			
				|  |  | +            return result;
 | 
	
		
			
				|  |  | +        return null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                if (typeof(TEntity) == typeof(Kanban))
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    CustomiseKanbanGrid((grid as DynamicDataGrid<Kanban>)!);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +    private readonly Dictionary<Type, IDynamicGrid> _grids = new();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            return (grid as DynamicDataGrid<TEntity>)!;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    private readonly List<Tuple<Guid, Entity>> _entitycache = new();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private IEnumerable<TEntity> DoLoad<TEntity>(IEnumerable<TaskModel> models, Columns<TEntity> columns)
 | 
	
		
			
				|  |  | -            where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +    private DynamicDataGrid<TEntity> GetGrid<TEntity>() where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if(!_grids.TryGetValue(typeof(TEntity), out var grid))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var result = new List<TEntity>();
 | 
	
		
			
				|  |  | -            var load = new List<Guid>();
 | 
	
		
			
				|  |  | -            foreach (var model in models)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                var entity = _entitycache.FirstOrDefault(x => Equals(x.Item1, model.ID) && x.Item2 is TEntity) as TEntity;
 | 
	
		
			
				|  |  | -                if (entity is not null)
 | 
	
		
			
				|  |  | -                    result.Add(entity);
 | 
	
		
			
				|  |  | -                else
 | 
	
		
			
				|  |  | -                    load.Add(model.ID);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            grid = (DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(TEntity)) as DynamicDataGrid<TEntity>)!;
 | 
	
		
			
				|  |  | +            _grids[typeof(TEntity)] = grid;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (load.Any())
 | 
	
		
			
				|  |  | +            if (typeof(TEntity) == typeof(Kanban))
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                var entities = new Client<TEntity>()
 | 
	
		
			
				|  |  | -                    .Query(new Filter<TEntity>(x => x.ID).InList(load.ToArray()), columns)
 | 
	
		
			
				|  |  | -                    .Rows.Select(x => x.ToObject<TEntity>()).ToList();
 | 
	
		
			
				|  |  | -                foreach (var entity in entities)
 | 
	
		
			
				|  |  | -                    _entitycache.Add(new Tuple<Guid, Entity>(entity.ID, entity));
 | 
	
		
			
				|  |  | -                result.AddRange(entities);
 | 
	
		
			
				|  |  | +                CustomiseKanbanGrid((grid as DynamicDataGrid<Kanban>)!);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private IEnumerable<TEntity> DoLoad<TEntityKanban, TEntity, TLink>(IEnumerable<TaskModel> models, Columns<TEntity> columns)
 | 
	
		
			
				|  |  | -            where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 | 
	
		
			
				|  |  | -            where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | -            where TLink : IEntityLink<TEntity>, new()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var result = DoLoad(models, columns);
 | 
	
		
			
				|  |  | -            if (!result.Any())
 | 
	
		
			
				|  |  | -                foreach (var model in models)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    result = new Client<TEntity>().Load(
 | 
	
		
			
				|  |  | -                        new Filter<TEntity>(x => x.ID).InQuery(new Filter<TEntityKanban>(x => x.Kanban.ID).IsEqualTo(model.ID),
 | 
	
		
			
				|  |  | -                            x => x.Entity.ID));
 | 
	
		
			
				|  |  | -                    foreach (var r in result)
 | 
	
		
			
				|  |  | -                        _entitycache.Add(new Tuple<Guid, Entity>(model.ID, r));
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        return (grid as DynamicDataGrid<TEntity>)!;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private void DoCache<TEntity>(Guid kanbanid, TEntity entity) where TEntity : Entity
 | 
	
		
			
				|  |  | +    private IEnumerable<TEntity> DoLoad<TEntity>(IEnumerable<TaskModel> models, Columns<TEntity> columns)
 | 
	
		
			
				|  |  | +        where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = new List<TEntity>();
 | 
	
		
			
				|  |  | +        var load = new List<Guid>();
 | 
	
		
			
				|  |  | +        foreach (var model in models)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            if (!_entitycache.Any(x => Equals(x.Item1, kanbanid) && x.Item2 is TEntity && Equals(x.Item2.ID, entity.ID)))
 | 
	
		
			
				|  |  | -                _entitycache.Add(new Tuple<Guid, Entity>(kanbanid, entity));
 | 
	
		
			
				|  |  | +            var entity = _entitycache.FirstOrDefault(x => Equals(x.Item1, model.ID) && x.Item2 is TEntity) as TEntity;
 | 
	
		
			
				|  |  | +            if (entity is not null)
 | 
	
		
			
				|  |  | +                result.Add(entity);
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  | +                load.Add(model.ID);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private bool DoEdit<TEntity>(IEnumerable<TEntity> entities, Action<TEntity>? action = null)
 | 
	
		
			
				|  |  | -            where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +        if (load.Any())
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            if (entities == null || !entities.Any())
 | 
	
		
			
				|  |  | -                return false;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +            var entities = new Client<TEntity>()
 | 
	
		
			
				|  |  | +                .Query(new Filter<TEntity>(x => x.ID).InList(load.ToArray()), columns)
 | 
	
		
			
				|  |  | +                .Rows.Select(x => x.ToObject<TEntity>()).ToList();
 | 
	
		
			
				|  |  |              foreach (var entity in entities)
 | 
	
		
			
				|  |  | -                action?.Invoke(entity);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            return GetGrid<TEntity>().EditItems(entities.ToArray());
 | 
	
		
			
				|  |  | +                _entitycache.Add(new Tuple<Guid, Entity>(entity.ID, entity));
 | 
	
		
			
				|  |  | +            result.AddRange(entities);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private void DoLink<TEntityKanban, TEntity, TLink>(TaskModel model, Guid entityid)
 | 
	
		
			
				|  |  | -            where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 | 
	
		
			
				|  |  | -            where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | -            where TLink : IEntityLink<TEntity>, new()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var linktask = Task.Run(() =>
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                var link = new TEntityKanban();
 | 
	
		
			
				|  |  | -                link.Kanban.ID = model.ID;
 | 
	
		
			
				|  |  | -                link.Entity.ID = entityid;
 | 
	
		
			
				|  |  | -                new Client<TEntityKanban>().Save(link, "");
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            var kanbantask = Task.Run(() =>
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private IEnumerable<TEntity> DoLoad<TEntityKanban, TEntity, TLink>(IEnumerable<TaskModel> models, Columns<TEntity> columns)
 | 
	
		
			
				|  |  | +        where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 | 
	
		
			
				|  |  | +        where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +        where TLink : IEntityLink<TEntity>, new()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = DoLoad(models, columns);
 | 
	
		
			
				|  |  | +        if (!result.Any())
 | 
	
		
			
				|  |  | +            foreach (var model in models)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                var kanban = LoadKanbans(
 | 
	
		
			
				|  |  | -                    new[] { model },
 | 
	
		
			
				|  |  | -                    Columns.Required<Kanban>().Add(x => x.ID, x => x.Locked)).FirstOrDefault();
 | 
	
		
			
				|  |  | -                if (kanban is not null)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    kanban.Locked = true;
 | 
	
		
			
				|  |  | -                    new Client<Kanban>().Save(kanban, "Locked because of linked " + typeof(TEntity).EntityName().Split('.').Last());
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            Task.WaitAll(linktask, kanbantask);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +                result = new Client<TEntity>().Load(
 | 
	
		
			
				|  |  | +                    new Filter<TEntity>(x => x.ID).InQuery(new Filter<TEntityKanban>(x => x.Kanban.ID).IsEqualTo(model.ID),
 | 
	
		
			
				|  |  | +                        x => x.Entity.ID));
 | 
	
		
			
				|  |  | +                foreach (var r in result)
 | 
	
		
			
				|  |  | +                    _entitycache.Add(new Tuple<Guid, Entity>(model.ID, r));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private static void DoDelete<TEntity>(IList<TEntity> entities, string auditnote)
 | 
	
		
			
				|  |  | -            where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            new Client<TEntity>().Delete(entities, auditnote);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public Kanban? CreateKanban(Action<Kanban> customise)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var result = DoCreate<Kanban>(
 | 
	
		
			
				|  |  | -                kanban =>
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    kanban.Title = "New Task";
 | 
	
		
			
				|  |  | -                    kanban.Description = "";
 | 
	
		
			
				|  |  | -                    kanban.Status = KanbanStatus.Open;
 | 
	
		
			
				|  |  | -                    kanban.DueDate = DateTime.Today;
 | 
	
		
			
				|  |  | -                    kanban.Private = false;
 | 
	
		
			
				|  |  | -                    kanban.JobLink.ID = Master?.ID ?? Guid.Empty;
 | 
	
		
			
				|  |  | -                    kanban.JobLink.Synchronise(Master ?? new Job());
 | 
	
		
			
				|  |  | -                    kanban.EmployeeLink.ID = App.EmployeeID;
 | 
	
		
			
				|  |  | -                    kanban.ManagerLink.ID = App.EmployeeID;
 | 
	
		
			
				|  |  | -                    customise?.Invoke(kanban);
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            if (result != null)
 | 
	
		
			
				|  |  | -                DoCache(result.ID, result);
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    private void DoCache<TEntity>(Guid kanbanid, TEntity entity) where TEntity : Entity
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (!_entitycache.Any(x => Equals(x.Item1, kanbanid) && x.Item2 is TEntity && Equals(x.Item2.ID, entity.ID)))
 | 
	
		
			
				|  |  | +            _entitycache.Add(new Tuple<Guid, Entity>(kanbanid, entity));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public IEnumerable<Kanban> LoadKanbans(IEnumerable<TaskModel> models, Columns<Kanban> columns)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            columns.Add(x => x.ID);
 | 
	
		
			
				|  |  | -            columns.Add(x => x.Number);
 | 
	
		
			
				|  |  | -            columns.Add(x => x.Title);
 | 
	
		
			
				|  |  | -            columns.Add(x => x.Notes);
 | 
	
		
			
				|  |  | -            columns.Add(x => x.Summary);
 | 
	
		
			
				|  |  | -            columns.Add(x => x.Completed);
 | 
	
		
			
				|  |  | -            columns.Add(x => x.DueDate);
 | 
	
		
			
				|  |  | -            columns.Add(x => x.ManagerLink.ID);
 | 
	
		
			
				|  |  | -            columns.Add(x => x.EmployeeLink.ID);
 | 
	
		
			
				|  |  | -            return DoLoad(models, columns);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    private bool DoEdit<TEntity>(IEnumerable<TEntity> entities, Action<TEntity>? action = null)
 | 
	
		
			
				|  |  | +        where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (entities == null || !entities.Any())
 | 
	
		
			
				|  |  | +            return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        foreach (var entity in entities)
 | 
	
		
			
				|  |  | +            action?.Invoke(entity);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void OnValidateKanban(object sender, Kanban[] items, List<string> errors)
 | 
	
		
			
				|  |  | +        return GetGrid<TEntity>().EditItems(entities.ToArray());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void DoLink<TEntityKanban, TEntity, TLink>(TaskModel model, Guid entityid)
 | 
	
		
			
				|  |  | +        where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 | 
	
		
			
				|  |  | +        where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +        where TLink : IEntityLink<TEntity>, new()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var linktask = Task.Run(() =>
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var link = new TEntityKanban();
 | 
	
		
			
				|  |  | +            link.Kanban.ID = model.ID;
 | 
	
		
			
				|  |  | +            link.Entity.ID = entityid;
 | 
	
		
			
				|  |  | +            new Client<TEntityKanban>().Save(link, "");
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        var kanbantask = Task.Run(() =>
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            if (Properties.RequireTaskTypes && items.Any(x => x.Type.ID == Guid.Empty))
 | 
	
		
			
				|  |  | +            var kanban = LoadKanbans(
 | 
	
		
			
				|  |  | +                new[] { model },
 | 
	
		
			
				|  |  | +                Columns.Required<Kanban>().Add(x => x.ID, x => x.Locked)).FirstOrDefault();
 | 
	
		
			
				|  |  | +            if (kanban is not null)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                errors.Add("[Task Type] may not be blank!");
 | 
	
		
			
				|  |  | +                kanban.Locked = true;
 | 
	
		
			
				|  |  | +                new Client<Kanban>().Save(kanban, "Locked because of linked " + typeof(TEntity).EntityName().Split('.').Last());
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        Task.WaitAll(linktask, kanbantask);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void CustomiseKanbanGrid(DynamicDataGrid<Kanban> grid)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            grid.OnValidate += OnValidateKanban;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    private static void DoDelete<TEntity>(IList<TEntity> entities, string auditnote)
 | 
	
		
			
				|  |  | +        where TEntity : Entity, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        new Client<TEntity>().Delete(entities, auditnote);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public bool EditKanbans(IEnumerable<TaskModel> models, Action<Kanban>? customise = null)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var entities = LoadKanbans(models, GetGrid<Kanban>().LoadEditorColumns());
 | 
	
		
			
				|  |  | -            return DoEdit(entities, customise);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public Kanban? CreateKanban(Action<Kanban> customise)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = DoCreate<Kanban>(
 | 
	
		
			
				|  |  | +            kanban =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                kanban.Title = "New Task";
 | 
	
		
			
				|  |  | +                kanban.Description = "";
 | 
	
		
			
				|  |  | +                kanban.Status = KanbanStatus.Open;
 | 
	
		
			
				|  |  | +                kanban.DueDate = DateTime.Today;
 | 
	
		
			
				|  |  | +                kanban.Private = false;
 | 
	
		
			
				|  |  | +                kanban.JobLink.ID = Master?.ID ?? Guid.Empty;
 | 
	
		
			
				|  |  | +                kanban.JobLink.Synchronise(Master ?? new Job());
 | 
	
		
			
				|  |  | +                kanban.EmployeeLink.ID = App.EmployeeID;
 | 
	
		
			
				|  |  | +                kanban.ManagerLink.ID = App.EmployeeID;
 | 
	
		
			
				|  |  | +                customise?.Invoke(kanban);
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +        if (result != null)
 | 
	
		
			
				|  |  | +            DoCache(result.ID, result);
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public IEnumerable<Kanban> LoadKanbans(IEnumerable<TaskModel> models, Columns<Kanban> columns)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        columns.Add(x => x.ID);
 | 
	
		
			
				|  |  | +        columns.Add(x => x.Number);
 | 
	
		
			
				|  |  | +        columns.Add(x => x.Title);
 | 
	
		
			
				|  |  | +        columns.Add(x => x.Notes);
 | 
	
		
			
				|  |  | +        columns.Add(x => x.Summary);
 | 
	
		
			
				|  |  | +        columns.Add(x => x.Completed);
 | 
	
		
			
				|  |  | +        columns.Add(x => x.DueDate);
 | 
	
		
			
				|  |  | +        columns.Add(x => x.ManagerLink.ID);
 | 
	
		
			
				|  |  | +        columns.Add(x => x.EmployeeLink.ID);
 | 
	
		
			
				|  |  | +        return DoLoad(models, columns);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void DeleteKanbans(IEnumerable<TaskModel> models, string auditnote)
 | 
	
		
			
				|  |  | +    public void OnValidateKanban(object sender, Kanban[] items, List<string> errors)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (Properties.RequireTaskTypes && items.Any(x => x.Type.ID == Guid.Empty))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var kanbans = models.Select(x => new Kanban { ID = x.ID }).ToList();
 | 
	
		
			
				|  |  | -            DoDelete(kanbans, auditnote);
 | 
	
		
			
				|  |  | +            errors.Add("[Task Type] may not be blank!");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public Requisition? CreateRequisition(TaskModel model, Action<Requisition>? customise)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var result = DoCreate<Requisition>(
 | 
	
		
			
				|  |  | -                requi =>
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    requi.JobLink.ID = Master?.ID ?? Guid.Empty;
 | 
	
		
			
				|  |  | -                    requi.JobLink.Synchronise(Master ?? new Job());
 | 
	
		
			
				|  |  | -                    customise?.Invoke(requi);
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            if (result != null)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                DoCache(model.ID, result);
 | 
	
		
			
				|  |  | -                DoLink<RequisitionKanban, Requisition, RequisitionLink>(model, result.ID);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +    public void CustomiseKanbanGrid(DynamicDataGrid<Kanban> grid)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        grid.OnValidate += OnValidateKanban;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public bool EditKanbans(IEnumerable<TaskModel> models, Action<Kanban>? customise = null)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var entities = LoadKanbans(models, GetGrid<Kanban>().LoadEditorColumns());
 | 
	
		
			
				|  |  | +        return DoEdit(entities, customise);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    public void DeleteKanbans(IEnumerable<TaskModel> models, string auditnote)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var kanbans = models.Select(x => new Kanban { ID = x.ID }).ToList();
 | 
	
		
			
				|  |  | +        DoDelete(kanbans, auditnote);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public bool EditRequisitions(IEnumerable<TaskModel> models, Action<Requisition>? customise = null)
 | 
	
		
			
				|  |  | +    public Requisition? CreateRequisition(TaskModel model, Action<Requisition>? customise)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = DoCreate<Requisition>(
 | 
	
		
			
				|  |  | +            requi =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                requi.JobLink.ID = Master?.ID ?? Guid.Empty;
 | 
	
		
			
				|  |  | +                requi.JobLink.Synchronise(Master ?? new Job());
 | 
	
		
			
				|  |  | +                customise?.Invoke(requi);
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +        if (result != null)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var requis = DoLoad<RequisitionKanban, Requisition, RequisitionLink>(models, GetGrid<Requisition>().LoadEditorColumns());
 | 
	
		
			
				|  |  | -            if (requis.Any())
 | 
	
		
			
				|  |  | -                return DoEdit(requis, customise);
 | 
	
		
			
				|  |  | -            return false;
 | 
	
		
			
				|  |  | +            DoCache(model.ID, result);
 | 
	
		
			
				|  |  | +            DoLink<RequisitionKanban, Requisition, RequisitionLink>(model, result.ID);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public Setout? CreateSetout(TaskModel model, Action<Setout> customise)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var result = DoCreate<Setout>(
 | 
	
		
			
				|  |  | -                setout =>
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    setout.JobLink.ID = Master?.ID ?? Guid.Empty;
 | 
	
		
			
				|  |  | -                    setout.JobLink.Synchronise(Master ?? new Job());
 | 
	
		
			
				|  |  | -                    customise?.Invoke(setout);
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            if (result != null)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                DoCache(model.ID, result);
 | 
	
		
			
				|  |  | -                //DoLink<SetoutKanban, Setout, SetoutLink>(model, result.ID);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public bool EditSetouts(IEnumerable<TaskModel> models, Action<Setout>? customise = null)
 | 
	
		
			
				|  |  | +    public bool EditRequisitions(IEnumerable<TaskModel> models, Action<Requisition>? customise = null)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var requis = DoLoad<RequisitionKanban, Requisition, RequisitionLink>(models, GetGrid<Requisition>().LoadEditorColumns());
 | 
	
		
			
				|  |  | +        if (requis.Any())
 | 
	
		
			
				|  |  | +            return DoEdit(requis, customise);
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public Setout? CreateSetout(TaskModel model, Action<Setout> customise)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = DoCreate<Setout>(
 | 
	
		
			
				|  |  | +            setout =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                setout.JobLink.ID = Master?.ID ?? Guid.Empty;
 | 
	
		
			
				|  |  | +                setout.JobLink.Synchronise(Master ?? new Job());
 | 
	
		
			
				|  |  | +                customise?.Invoke(setout);
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +        if (result != null)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var setouts = DoLoad<SetoutKanban, Setout, SetoutLink>(models, GetGrid<Setout>().LoadEditorColumns());
 | 
	
		
			
				|  |  | -            if (setouts.Any())
 | 
	
		
			
				|  |  | -                return DoEdit(setouts, customise);
 | 
	
		
			
				|  |  | -            return false;
 | 
	
		
			
				|  |  | +            DoCache(model.ID, result);
 | 
	
		
			
				|  |  | +            //DoLink<SetoutKanban, Setout, SetoutLink>(model, result.ID);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public Delivery? CreateDelivery(TaskModel model, Action<Delivery> customise)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var result = DoCreate<Delivery>(
 | 
	
		
			
				|  |  | -                delivery =>
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    delivery.Job.ID = Master?.ID ?? Guid.Empty;
 | 
	
		
			
				|  |  | -                    delivery.Job.Synchronise(Master ?? new Job());
 | 
	
		
			
				|  |  | -                    customise?.Invoke(delivery);
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            if (result != null)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                DoCache(model.ID, result);
 | 
	
		
			
				|  |  | -                DoLink<DeliveryKanban, Delivery, DeliveryLink>(model, result.ID);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public bool EditSetouts(IEnumerable<TaskModel> models, Action<Setout>? customise = null)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var setouts = DoLoad<SetoutKanban, Setout, SetoutLink>(models, GetGrid<Setout>().LoadEditorColumns());
 | 
	
		
			
				|  |  | +        if (setouts.Any())
 | 
	
		
			
				|  |  | +            return DoEdit(setouts, customise);
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public bool EditDeliveries(IEnumerable<TaskModel> models, Action<Delivery>? customise = null)
 | 
	
		
			
				|  |  | +    public Delivery? CreateDelivery(TaskModel model, Action<Delivery> customise)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = DoCreate<Delivery>(
 | 
	
		
			
				|  |  | +            delivery =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                delivery.Job.ID = Master?.ID ?? Guid.Empty;
 | 
	
		
			
				|  |  | +                delivery.Job.Synchronise(Master ?? new Job());
 | 
	
		
			
				|  |  | +                customise?.Invoke(delivery);
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +        if (result != null)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var deliveries = DoLoad<DeliveryKanban, Delivery, DeliveryLink>(models, GetGrid<Delivery>().LoadEditorColumns());
 | 
	
		
			
				|  |  | -            if (deliveries.Any())
 | 
	
		
			
				|  |  | -                return DoEdit(deliveries, customise);
 | 
	
		
			
				|  |  | -            return false;
 | 
	
		
			
				|  |  | +            DoCache(model.ID, result);
 | 
	
		
			
				|  |  | +            DoLink<DeliveryKanban, Delivery, DeliveryLink>(model, result.ID);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public PurchaseOrder? CreateOrder(TaskModel model, Action<PurchaseOrder> customise)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var result = DoCreate<PurchaseOrder>(
 | 
	
		
			
				|  |  | -                order => { customise?.Invoke(order); });
 | 
	
		
			
				|  |  | -            if (result != null)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                DoCache(model.ID, result);
 | 
	
		
			
				|  |  | -                DoLink<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(model, result.ID);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +    public bool EditDeliveries(IEnumerable<TaskModel> models, Action<Delivery>? customise = null)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var deliveries = DoLoad<DeliveryKanban, Delivery, DeliveryLink>(models, GetGrid<Delivery>().LoadEditorColumns());
 | 
	
		
			
				|  |  | +        if (deliveries.Any())
 | 
	
		
			
				|  |  | +            return DoEdit(deliveries, customise);
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public bool EditPurchaseOrders(IEnumerable<TaskModel> models, Action<PurchaseOrder>? customise = null)
 | 
	
		
			
				|  |  | +    public PurchaseOrder? CreateOrder(TaskModel model, Action<PurchaseOrder> customise)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = DoCreate<PurchaseOrder>(
 | 
	
		
			
				|  |  | +            order => { customise?.Invoke(order); });
 | 
	
		
			
				|  |  | +        if (result != null)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var orders = DoLoad<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(models, GetGrid<PurchaseOrder>().LoadEditorColumns());
 | 
	
		
			
				|  |  | -            if (orders.Any())
 | 
	
		
			
				|  |  | -                return DoEdit(orders, customise);
 | 
	
		
			
				|  |  | -            return false;
 | 
	
		
			
				|  |  | +            DoCache(model.ID, result);
 | 
	
		
			
				|  |  | +            DoLink<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(model, result.ID);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        #endregion
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        #region EntityReferences
 | 
	
		
			
				|  |  | +    public bool EditPurchaseOrders(IEnumerable<TaskModel> models, Action<PurchaseOrder>? customise = null)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var orders = DoLoad<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(models, GetGrid<PurchaseOrder>().LoadEditorColumns());
 | 
	
		
			
				|  |  | +        if (orders.Any())
 | 
	
		
			
				|  |  | +            return DoEdit(orders, customise);
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private static void AddQuery<TEntityKanban, TEntity, TLink>(MultiQuery query, Guid[] taskids)
 | 
	
		
			
				|  |  | -            where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 | 
	
		
			
				|  |  | -            where TEntity : Entity
 | 
	
		
			
				|  |  | -            where TLink : IEntityLink<TEntity>, new()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            query.Add(
 | 
	
		
			
				|  |  | -                new Filter<TEntityKanban>(x => x.Kanban.ID).InList(taskids),
 | 
	
		
			
				|  |  | -                Columns.None<TEntityKanban>().Add(x => x.Entity.ID).Add(x => x.Kanban.ID)
 | 
	
		
			
				|  |  | -            );
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    #endregion
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private static Guid[] ExtractIDs<TEntityKanban, TEntity, TLink>(MultiQuery query)
 | 
	
		
			
				|  |  | -            where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 | 
	
		
			
				|  |  | -            where TEntity : Entity
 | 
	
		
			
				|  |  | -            where TLink : IEntityLink<TEntity>, new()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var lookup = query.Get<TEntityKanban>().ToLookup<TEntityKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 | 
	
		
			
				|  |  | -            return query.Get<TEntityKanban>().ExtractValues<TEntityKanban, Guid>(x => x.Entity.ID).ToArray();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    #region EntityReferences
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public KanbanReferences[] GetReferences(IEnumerable<TaskModel> models)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var result = new List<KanbanReferences>();
 | 
	
		
			
				|  |  | +    private static void AddQuery<TEntityKanban, TEntity, TLink>(MultiQuery query, Guid[] taskids)
 | 
	
		
			
				|  |  | +        where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 | 
	
		
			
				|  |  | +        where TEntity : Entity
 | 
	
		
			
				|  |  | +        where TLink : IEntityLink<TEntity>, new()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        query.Add(
 | 
	
		
			
				|  |  | +            new Filter<TEntityKanban>(x => x.Kanban.ID).InList(taskids),
 | 
	
		
			
				|  |  | +            Columns.None<TEntityKanban>().Add(x => x.Entity.ID).Add(x => x.Kanban.ID)
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            var ids = models.Select(x => x.ID).ToArray();
 | 
	
		
			
				|  |  | +    private static Guid[] ExtractIDs<TEntityKanban, TEntity, TLink>(MultiQuery query)
 | 
	
		
			
				|  |  | +        where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 | 
	
		
			
				|  |  | +        where TEntity : Entity
 | 
	
		
			
				|  |  | +        where TLink : IEntityLink<TEntity>, new()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var lookup = query.Get<TEntityKanban>().ToLookup<TEntityKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 | 
	
		
			
				|  |  | +        return query.Get<TEntityKanban>().ExtractValues<TEntityKanban, Guid>(x => x.Entity.ID).ToArray();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            var query = new MultiQuery();
 | 
	
		
			
				|  |  | +    public KanbanReferences[] GetReferences(IEnumerable<TaskModel> models)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = new List<KanbanReferences>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            AddQuery<RequisitionKanban, Requisition, RequisitionLink>(query, ids);
 | 
	
		
			
				|  |  | -            AddQuery<SetoutKanban, Setout, SetoutLink>(query, ids);
 | 
	
		
			
				|  |  | -            AddQuery<DeliveryKanban, Delivery, DeliveryLink>(query, ids);
 | 
	
		
			
				|  |  | -            AddQuery<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(query, ids);
 | 
	
		
			
				|  |  | +        var ids = models.Select(x => x.ID).ToArray();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            query.Query();
 | 
	
		
			
				|  |  | +        var query = new MultiQuery();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            var requis = query.Get<RequisitionKanban>().ToLookup<RequisitionKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 | 
	
		
			
				|  |  | -            var setouts = query.Get<SetoutKanban>().ToLookup<SetoutKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 | 
	
		
			
				|  |  | -            var deliveries = query.Get<DeliveryKanban>().ToLookup<DeliveryKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 | 
	
		
			
				|  |  | -            var orders = query.Get<PurchaseOrderKanban>().ToLookup<PurchaseOrderKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 | 
	
		
			
				|  |  | +        AddQuery<RequisitionKanban, Requisition, RequisitionLink>(query, ids);
 | 
	
		
			
				|  |  | +        AddQuery<SetoutKanban, Setout, SetoutLink>(query, ids);
 | 
	
		
			
				|  |  | +        AddQuery<DeliveryKanban, Delivery, DeliveryLink>(query, ids);
 | 
	
		
			
				|  |  | +        AddQuery<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(query, ids);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            foreach (var id in ids)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                var references = new KanbanReferences
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    Kanban = id,
 | 
	
		
			
				|  |  | -                    Requisitions = requis.Contains(id) ? requis[id].ToArray() : Array.Empty<Guid>(),
 | 
	
		
			
				|  |  | -                    Setouts = setouts.Contains(id) ? setouts[id].ToArray() : Array.Empty<Guid>(),
 | 
	
		
			
				|  |  | -                    Deliveries = deliveries.Contains(id) ? deliveries[id].ToArray() : Array.Empty<Guid>(),
 | 
	
		
			
				|  |  | -                    Orders = orders.Contains(id) ? orders[id].ToArray() : Array.Empty<Guid>()
 | 
	
		
			
				|  |  | -                };
 | 
	
		
			
				|  |  | -                result.Add(references);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        query.Query();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            return result.ToArray();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        var requis = query.Get<RequisitionKanban>().ToLookup<RequisitionKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 | 
	
		
			
				|  |  | +        var setouts = query.Get<SetoutKanban>().ToLookup<SetoutKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 | 
	
		
			
				|  |  | +        var deliveries = query.Get<DeliveryKanban>().ToLookup<DeliveryKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 | 
	
		
			
				|  |  | +        var orders = query.Get<PurchaseOrderKanban>().ToLookup<PurchaseOrderKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public bool EditReferences(IEnumerable<TaskModel> models)
 | 
	
		
			
				|  |  | +        foreach (var id in ids)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var result = false;
 | 
	
		
			
				|  |  | -            var refs = GetReferences(models).First();
 | 
	
		
			
				|  |  | -            if (refs.ReferenceType() == typeof(Requisition))
 | 
	
		
			
				|  |  | -                result = EditRequisitions(
 | 
	
		
			
				|  |  | -                    models,
 | 
	
		
			
				|  |  | -                    requi =>
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        requi.Notes = Utility.ProcessNotes(requi.Notes, requi.Request);
 | 
	
		
			
				|  |  | -                        requi.Request = "";
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                );
 | 
	
		
			
				|  |  | -            else if (refs.ReferenceType() == typeof(Setout))
 | 
	
		
			
				|  |  | -                result = EditSetouts(models);
 | 
	
		
			
				|  |  | -            else if (refs.ReferenceType() == typeof(Delivery))
 | 
	
		
			
				|  |  | -                result = EditDeliveries(models);
 | 
	
		
			
				|  |  | -            else if (refs.ReferenceType() == typeof(PurchaseOrder))
 | 
	
		
			
				|  |  | -                result = EditPurchaseOrders(models);
 | 
	
		
			
				|  |  | -            else
 | 
	
		
			
				|  |  | -                result = EditKanbans(models);
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  | +            var references = new KanbanReferences
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Kanban = id,
 | 
	
		
			
				|  |  | +                Requisitions = requis.Contains(id) ? requis[id].ToArray() : Array.Empty<Guid>(),
 | 
	
		
			
				|  |  | +                Setouts = setouts.Contains(id) ? setouts[id].ToArray() : Array.Empty<Guid>(),
 | 
	
		
			
				|  |  | +                Deliveries = deliveries.Contains(id) ? deliveries[id].ToArray() : Array.Empty<Guid>(),
 | 
	
		
			
				|  |  | +                Orders = orders.Contains(id) ? orders[id].ToArray() : Array.Empty<Guid>()
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            result.Add(references);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        #endregion
 | 
	
		
			
				|  |  | +        return result.ToArray();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public bool EditReferences(IEnumerable<TaskModel> models)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var result = false;
 | 
	
		
			
				|  |  | +        var refs = GetReferences(models).First();
 | 
	
		
			
				|  |  | +        if (refs.ReferenceType() == typeof(Requisition))
 | 
	
		
			
				|  |  | +            result = EditRequisitions(
 | 
	
		
			
				|  |  | +                models,
 | 
	
		
			
				|  |  | +                requi =>
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    requi.Notes = Utility.ProcessNotes(requi.Notes, requi.Request);
 | 
	
		
			
				|  |  | +                    requi.Request = "";
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +        else if (refs.ReferenceType() == typeof(Setout))
 | 
	
		
			
				|  |  | +            result = EditSetouts(models);
 | 
	
		
			
				|  |  | +        else if (refs.ReferenceType() == typeof(Delivery))
 | 
	
		
			
				|  |  | +            result = EditDeliveries(models);
 | 
	
		
			
				|  |  | +        else if (refs.ReferenceType() == typeof(PurchaseOrder))
 | 
	
		
			
				|  |  | +            result = EditPurchaseOrders(models);
 | 
	
		
			
				|  |  | +        else
 | 
	
		
			
				|  |  | +            result = EditKanbans(models);
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #endregion
 | 
	
		
			
				|  |  |  }
 |