123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- using Comal.Classes;
- using InABox.Clients;
- using InABox.Core;
- using InABox.WPF;
- using NPOI.SS.Formula.Functions;
- using Syncfusion.UI.Xaml.Kanban;
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using System.Windows.Navigation;
- using System.Windows.Shapes;
- namespace PRSDesktop;
- public class TasksByStatusColumn
- {
- public string Category { get; }
- public string Title { get; }
- public int NumTasks { get => Tasks.Count; }
- public double NumHours { get => Tasks.Sum(x => x.EstimatedTime.TotalHours); }
- public List<TaskModel> Tasks { get; }
- public TasksByStatusColumn(string category, string title)
- {
- Category = category;
- Title = title;
- }
- }
- public class EmployeeModel
- {
- public Guid ID { get; set; }
- public string Name { get; set; }
- public BitmapImage? Image { get; set; }
- public Guid ThumbnailID { get; set; }
- public EmployeeModel(Guid id, string name, Guid thumbnail, BitmapImage? image)
- {
- ID = id;
- Name = name;
- Image = image;
- ThumbnailID = thumbnail;
- }
- }
- /// <summary>
- /// Interaction logic for TasksByStatusControl.xaml
- /// </summary>
- public partial class TasksByStatusControl : UserControl, ITaskControl
- {
- public List<TasksByStatusColumn> Columns = new();
- private List<EmployeeModel> Employees = new();
- public TasksByStatusControl()
- {
- InitializeComponent();
- }
- #region Setup
- public void Setup()
- {
- var employeesTask = LoadEmployees();
- var kanbanTypesTask = Task.Run(() => LoadKanbanTypes());
- SetupToolbar();
- SetupColumns();
- employeesTask.Wait();
- SetupEmployeeList();
- kanbanTypesTask.Wait();
- SetupKanbanTypesLookup(kanbanTypesTask.Result);
- }
- private void SetupToolbar()
- {
- IncludeCompleted.Visibility = Security.IsAllowed<CanHideTaskCompletedColumn>() ? Visibility.Visible : Visibility.Collapsed;
- IncludeCompleted.IsChecked = IncludeCompleted.Visibility == Visibility.Visible ? Host.KanbanSettings.StatusSettings.IncludeCompleted : true;
- IncludeObserved.IsChecked = Host.KanbanSettings.StatusSettings.IncludeObserved;
- ViewType.SelectedIndex = Host.KanbanSettings.StatusSettings.CompactView ? 1 : 0;
- }
- #endregion
- #region Columns
- private void SetupColumns()
- {
- Columns.Clear();
- Columns.Add(new TasksByStatusColumn("Open", "To Do"));
- Columns.Add(new TasksByStatusColumn("In Progress", "In Progress"));
- Columns.Add(new TasksByStatusColumn("Waiting", "Waiting for Others"));
- if (Host.KanbanSettings.StatusSettings.IncludeCompleted)
- Columns.Add(new TasksByStatusColumn("Complete", "Completed"));
- }
- private void Column_ContextMenuOpening(object sender, ContextMenuEventArgs e)
- {
- if (sender is not FrameworkElement element || element.Tag is not TasksByStatusColumn column) return;
- var menu = element.ContextMenu;
- menu.Items.Clear();
- menu.AddItem("New Task", null, CreateTask);
- menu.AddItem($"Select all {column.Title} tasks", null, column, SelectAll);
- menu.AddItem($"Deselect all {column.Title} tasks", null, column, DeselectAll);
- }
- private void SelectColumn(TasksByStatusColumn column, bool selected)
- {
- SelectedTasks.Clear();
- if (selected)
- {
- SelectedTasks.AddRange(column.Tasks);
- foreach (var task in Tasks)
- task.Checked = string.Equals(task.Category, column.Category) ? selected : !selected;
- }
- FilterKanbans();
- }
- private void DeselectAll(TasksByStatusColumn column)
- {
- SelectColumn(column, false);
- }
- private void SelectAll(TasksByStatusColumn column)
- {
- SelectColumn(column, true);
- }
- #endregion
- #region Kanban Types
- private IEnumerable<KanbanType> LoadKanbanTypes()
- {
- return Client.Query(
- new Filter<KanbanType>(x => x.Hidden).IsEqualTo(false),
- new Columns<KanbanType>(x => x.ID, x => x.Description),
- new SortOrder<KanbanType>(x => x.Description))
- .ToObjects<KanbanType>();
- }
- private void SetupKanbanTypesLookup(IEnumerable<KanbanType> kanbanTypes)
- {
- if (ClientFactory.IsSupported<KanbanType>())
- {
- var tasktypes = new Dictionary<Guid, string>
- {
- { CoreUtils.FullGuid, "All Types" },
- { Guid.Empty, "Unallocated Types" }
- };
- foreach(var type in kanbanTypes)
- {
- tasktypes.Add(type.ID, type.Description);
- }
- TaskTypes.ItemsSource = tasktypes;
- if (tasktypes.ContainsKey(Host.KanbanSettings.StatusSettings.SelectedType))
- TaskTypes.SelectedValue = Host.KanbanSettings.StatusSettings.SelectedType;
- else
- TaskTypes.SelectedValue = CoreUtils.FullGuid;
- TaskTypesLabel.Visibility = Visibility.Visible;
- TaskTypes.Visibility = Visibility.Visible;
- }
- else
- {
- TaskTypesLabel.Visibility = Visibility.Collapsed;
- TaskTypes.Visibility = Visibility.Collapsed;
- }
- }
- #endregion
- #region Employees
- private EmployeeModel SelectedEmployee;
- private async Task LoadEmployees()
- {
- Employees.Clear();
- var employeeFilter = Security.IsAllowed<CanViewOthersTasks>()
- ? new Filter<Employee>(x => x.CanAllocateTasks).IsEqualTo(true)
- .And(new Filter<Employee>(x => x.FinishDate).IsEqualTo(DateTime.MinValue)
- .Or(x => x.FinishDate).IsGreaterThan(DateTime.Today))
- : new Filter<Employee>(x => x.ID).IsEqualTo(App.EmployeeID);
- var employees = await Task.Run(() => Client.Query<Employee>(
- employeeFilter,
- new Columns<Employee>(x => x.ID)
- .Add(x => x.Thumbnail.ID)
- .Add(x => x.Name)));
- var anonymous = PRSDesktop.Resources.anonymous.AsBitmapImage();
- if (Security.IsAllowed<CanViewOthersTasks>())
- {
- Employees.Add(new EmployeeModel(CoreUtils.FullGuid, "All Staff", Guid.Empty, PRSDesktop.Resources.everyone.AsBitmapImage()));
- Employees.Add(new EmployeeModel(Guid.Empty, "Unallocated", Guid.Empty, null));
- }
- EmployeeModel? selected = null;
- foreach (var employee in employees.ToObjects<Employee>())
- {
- var name = employee.ID == App.EmployeeID ? "My Tasks" : employee.Name;
- var model = new EmployeeModel(employee.ID, name, employee.Thumbnail.ID, anonymous);
- if (employee.ID == App.EmployeeID)
- {
- Employees.Insert(0, model);
- selected = model;
- }
- else
- {
- Employees.Add(model);
- }
- }
- }
- private void SetupEmployeeList()
- {
- if (Security.IsAllowed<CanViewOthersTasks>())
- {
- EmployeeListColumn.Width = new GridLength(1.0F, GridUnitType.Auto);
- var thumbnails = Employees
- .Select(e => e.ThumbnailID)
- .Where(x => x != Guid.Empty).ToArray();
- EmployeeList.ItemsSource = Employees;
- SelectedEmployee = Employees.First();
- EmployeeList.SelectedItem = SelectedEmployee;
- if (thumbnails.Any())
- new Client<Document>().Query(
- new Filter<Document>(x => x.ID).InList(thumbnails),
- new Columns<Document>(x => x.ID, x => x.Data),
- null,
- (data, error) =>
- {
- if (data != null)
- ProcessThumbnails(data);
- }
- );
- }
- else
- {
- EmployeeListColumn.Width = new GridLength(0.0F, GridUnitType.Pixel);
- EmployeeList.ItemsSource = Employees;
- SelectedEmployee = Employees.First();
- EmployeeList.SelectedItem = SelectedEmployee;
- }
- }
- private bool _updatingEmployees = false;
- private void ProcessThumbnails(CoreTable data)
- {
- Dispatcher.Invoke(() =>
- {
- foreach (var row in data.Rows)
- {
- var id = row.Get<Document, Guid>(x => x.ID);
- var model = Employees.FirstOrDefault(x => x.ThumbnailID.Equals(id));
- if (model != null)
- {
- model.Image = new BitmapImage();
- model.Image.LoadImage(row.Get<Document, byte[]>(x => x.Data));
- }
- }
- _updatingEmployees = true;
- EmployeeList.ItemsSource = null;
- EmployeeList.ItemsSource = Employees;
- SelectedEmployee = Employees.First();
- EmployeeList.SelectedItem = SelectedEmployee;
- _updatingEmployees = false;
- });
- }
- #endregion
- #region Kanbans
- private IEnumerable<TaskModel> Tasks => Columns.SelectMany(x => x.Tasks);
- private readonly List<TaskModel> SelectedTasks = new();
- private void CreateTask()
- {
- var result = Host.CreateKanban(
- kanban =>
- {
- kanban.EmployeeLink.ID = SelectedEmployee.ID != CoreUtils.FullGuid ? SelectedEmployee.ID : App.EmployeeID;
- kanban.ManagerLink.ID = App.EmployeeID;
- kanban.ManagerLink.UserLink.ID = ClientFactory.UserGuid;
- });
- if (result != null)
- Refresh(true);
- }
- private void DoEdit(TaskModel task)
- {
- var result = Host.EditReferences(new[] { task });
- if (result)
- {
- Refresh(true);
- }
- }
- private void EditTask_Executed(object sender, ExecutedRoutedEventArgs e)
- {
- if (e.Parameter is not TaskModel model) return;
- DoEdit(model);
- }
- private void OpenTaskMenu_Executed(object sender, ExecutedRoutedEventArgs e)
- {
- if (e.Parameter is not TaskModel model) return;
- Host.PopulateMenu(this, sender as ContextMenu);
- }
- private void SelectTask_Executed(object sender, ExecutedRoutedEventArgs e)
- {
- if (e.Parameter is not TaskModel model) return;
- if (!SelectedTasks.Remove(model))
- {
- SelectedTasks.Add(model);
- }
- }
- private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
- {
- e.CanExecute = e.Parameter is TaskModel;
- }
- #endregion
- public void Refresh(bool resetselection)
- {
- }
- #region ITaskControl
- public ITaskHost Host { get; set; }
- public KanbanViewType KanbanViewType => KanbanViewType.Status;
- public bool IsReady { get; set; }
- public string SectionName => "Tasks By Status";
- public DataModel DataModel(Selection selection)
- {
- var ids = SelectedModels().Select(x => Guid.Parse(x.ID)).ToArray();
- return new AutoDataModel<Kanban>(new Filter<Kanban>(x => x.ID).InList(ids));
- }
- public IEnumerable<TaskModel> SelectedModels(TaskModel? sender = null)
- {
- return Enumerable.Empty<TaskModel>();
- }
- #endregion
- private void Employees_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- }
- private void TaskTypesLabel_OnClick(object sender, RoutedEventArgs e)
- {
- }
- private void TaskTypes_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- }
- private void JobFilterBtn_OnClick(object sender, RoutedEventArgs e)
- {
- }
- private void Export_Click(object sender, RoutedEventArgs e)
- {
- }
- private void IncludeCompleted_Checked(object sender, RoutedEventArgs e)
- {
- }
- private void IncludeObserved_Checked(object sender, RoutedEventArgs e)
- {
- }
- private void IncludeLocked_Checked(object sender, RoutedEventArgs e)
- {
- }
- private void ViewType_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- }
- private void Search_KeyUp(object sender, KeyEventArgs e)
- {
- }
- }
|