123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Globalization;
- using System.Linq;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Input;
- using System.Windows.Media.Imaging;
- using AvalonDock.Layout;
- using com.sun.org.apache.bcel.@internal.generic;
- using Comal.Classes;
- using InABox.Clients;
- using InABox.Core;
- using InABox.DynamicGrid;
- using InABox.Wpf;
- using InABox.WPF;
- using Syncfusion.UI.Xaml.Kanban;
- using Syncfusion.Windows.Tools.Controls;
- using static com.sun.tools.javac.code.Symbol;
- namespace PRSDesktop;
- public class TasksByUserEmployeeHeader : INotifyPropertyChanged
- {
- public Guid EmployeeID { get; set; }
- public string Name { get; set; }
- public BitmapImage Image { get; set; }
- public int NumTasks { get => Tasks.Count(); }
- public double NumHours { get => Tasks.Sum(x => x.EstimatedTime.TotalHours); }
- public IEnumerable<TaskModel> Tasks => Model.Categories
- .SelectMany(x => x.EmployeeCategoryDictionary.GetValueOrDefault(EmployeeID)?.Tasks ?? Enumerable.Empty<TaskModel>());
- private TasksByUserModel Model;
- public event PropertyChangedEventHandler? PropertyChanged;
- // Create the OnPropertyChanged method to raise the event
- // The calling member's name will be used as the parameter.
- protected void OnPropertyChanged([CallerMemberName] string? name = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
- if (name.Equals(nameof(Tasks)))
- {
- OnPropertyChanged(nameof(NumTasks));
- OnPropertyChanged(nameof(NumHours));
- }
- }
- public TasksByUserEmployeeHeader(Guid employeeID, string name, BitmapImage image, TasksByUserModel model)
- {
- EmployeeID = employeeID;
- Name = name;
- Image = image;
- Model = model;
- }
- public void UpdateTasks()
- {
- OnPropertyChanged(nameof(Tasks));
- }
- }
- public class TasksByUserEmployeeCategory
- {
- public Guid EmployeeID { get; set; }
- public KanbanStatus Status { get; set; }
- public SuspendableObservableCollection<TaskModel> Tasks { get; set; } = new();
- public TasksByUserEmployeeCategory(Guid employeeID, KanbanStatus status)
- {
- EmployeeID = employeeID;
- Status = status;
- }
- }
- public class TasksByUserCategory : INotifyPropertyChanged
- {
- private bool _collapsed;
- public bool Collapsed
- {
- get => _collapsed;
- set
- {
- _collapsed = value;
- OnPropertyChanged();
- }
- }
- public KanbanStatus Status { get; set; }
- public IEnumerable<TasksByUserEmployeeCategory> EmployeeCategories => EmployeeCategoryDictionary.Values;
- public Dictionary<Guid, TasksByUserEmployeeCategory> EmployeeCategoryDictionary { get; set; } = new();
- public TasksByUserCategory(KanbanStatus status, bool collapsed)
- {
- Status = status;
- Collapsed = collapsed;
- }
- public event PropertyChangedEventHandler? PropertyChanged;
- // Create the OnPropertyChanged method to raise the event
- // The calling member's name will be used as the parameter.
- protected void OnPropertyChanged([CallerMemberName] string? name = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
- }
- }
- public class TasksByUserModel
- {
- public SuspendableObservableCollection<TasksByUserEmployeeHeader> SectionHeaders { get; set; } = new();
- public SuspendableObservableCollection<TasksByUserCategory> Categories { get; set; } = new();
- }
- public partial class TasksByUserControl : UserControl, INotifyPropertyChanged, ITaskControl
- {
- private static readonly BitmapImage anonymous = PRSDesktop.Resources.anonymous.AsBitmapImage();
- public TasksByUserModel Model { get; set; } = new();
- private ILookup<Guid, Guid> TeamEmployees;
- private Dictionary<Guid, EmployeeModel> Employees;
- private bool bPopulating;
- private KanbanViewMode _mode;
- public KanbanViewMode Mode
- {
- get => _mode;
- set
- {
- _mode = value;
- OnPropertyChanged();
- }
- }
- public TasksByUserControl()
- {
- InitializeComponent();
- }
- #region INotifyPropertyChanged
- public event PropertyChangedEventHandler? PropertyChanged;
- // Create the OnPropertyChanged method to raise the event
- // The calling member's name will be used as the parameter.
- protected void OnPropertyChanged([CallerMemberName] string? name = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
- }
- #endregion
- #region Setup
- private void LoadEmployees()
- {
- var empfilter = LookupFactory.DefineFilter<Employee>();
- var results = Client.QueryMultiple(
- new KeyedQueryDef<Employee>(
- LookupFactory.DefineFilter<Employee>(),
- Columns.None<Employee>().Add(x => x.ID)
- .Add(x => x.Name)
- .Add(x => x.Thumbnail.ID),
- new SortOrder<Employee>(x => x.Name)),
- new KeyedQueryDef<Team>(
- LookupFactory.DefineFilter<Team>(),
- Columns.None<Team>().Add(x => x.ID)
- .Add(x => x.Name),
- new SortOrder<Team>(x => x.Name)),
- new KeyedQueryDef<EmployeeTeam>(
- LookupFactory.DefineFilter<EmployeeTeam>(),
- Columns.None<EmployeeTeam>().Add(x => x.EmployeeLink.ID)
- .Add(x => x.TeamLink.ID)));
- TeamEmployees = results.Get<EmployeeTeam>().ToLookup<EmployeeTeam, Guid, Guid>(x => x.TeamLink.ID, x => x.EmployeeLink.ID);
- Employees = results.GetObjects<Employee>().ToDictionary(
- x => x.ID,
- x => new EmployeeModel(x.ID, x.Name, x.Thumbnail.ID, null));
- var teams = results.GetObjects<Team>().ToDictionary(x => x.ID, x => x.Name);
- SelectedTeams.ItemsSource = teams;
- foreach (var team in Host.KanbanSettings.UserSettings.SelectedTeams)
- {
- SelectedTeams.SelectedItems.Add(teams.FirstOrDefault(x => x.Key == team));
- }
- }
- private void PopulateEmployees()
- {
- bPopulating = true;
- try
- {
- var availableemployees = new List<Guid>();
- foreach (var team in SelectedTeams.SelectedItems.Select(v => (KeyValuePair<Guid, string>)v))
- availableemployees.AddRange(TeamEmployees[team.Key].Where(x => !availableemployees.Contains(x)));
- SelectedEmployees.ItemsSource = Employees.Where(x => availableemployees.Contains(x.Key));
- SelectedEmployees.SelectedItems.Clear();
- foreach (var employee in Host.KanbanSettings.UserSettings.SelectedEmployees.Where(availableemployees.Contains))
- SelectedEmployees.SelectedItems.Add(Employees.FirstOrDefault(x => Equals(x.Key, employee)));
- }
- catch (Exception e)
- {
- }
- bPopulating = false;
- }
- private void SetupToolbar()
- {
- IncludeCompleted.Visibility = Security.IsAllowed<CanHideTaskCompletedColumn>() ? Visibility.Visible : Visibility.Collapsed;
- IncludeCompleted.IsChecked = IncludeCompleted.Visibility == Visibility.Visible ? Host.KanbanSettings.UserSettings.IncludeCompleted : true;
- IncludeObserved.IsChecked = Host.KanbanSettings.UserSettings.IncludeObserved;
- IncludeManaged.IsChecked = Host.KanbanSettings.UserSettings.IncludeManaged;
- ViewType.SelectedIndex = Host.KanbanSettings.UserSettings.CompactView ? 1 : 0;
- }
- private void PopulateKanbanTypes()
- {
- TaskType.Items.Add("");
- foreach (var kanbanType in Host.KanbanTypes)
- {
- TaskType.Items.Add(kanbanType);
- }
- }
- public void Setup()
- {
- SetupToolbar();
- SplitPanel.AnchorWidth = Host.KanbanSettings.UserSettings.AnchorWidth;
- TeamsRow.Height = new GridLength(Host.KanbanSettings.UserSettings.TeamsHeight);
- LoadEmployees();
- PopulateEmployees();
- Mode = Host.KanbanSettings.UserSettings.CompactView ? KanbanViewMode.Compact : KanbanViewMode.Full;
- PopulateKanbanTypes();
- FilterButton.SetSettings(Host.KanbanSettings.Filters, false);
- }
- #endregion
- #region Filters
- private void TaskPanelFilterButton_OnFilterRefresh()
- {
- Refresh();
- }
- private void FilterButton_OnFiltersSelected(DynamicGridSelectedFilterSettings filters)
- {
- Host.KanbanSettings.Filters = filters;
- Host.SaveSettings();
- }
- private void IncludeCompleted_Checked(object sender, RoutedEventArgs e)
- {
- if (!IsReady)
- return;
- SaveSettings();
- Refresh();
- }
- private void IncludeObserved_Checked(object sender, RoutedEventArgs e)
- {
- if (!IsReady)
- return;
- SaveSettings();
- Refresh();
- }
- private void IncludeManaged_Checked(object sender, RoutedEventArgs e)
- {
- if (!IsReady)
- return;
- SaveSettings();
- Refresh();
- }
- private void TaskType_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (!IsReady)
- return;
- FilterKanbans();
- }
- private void Search_KeyUp(object sender, KeyEventArgs e)
- {
- FilterKanbans();
- }
- #endregion
- #region Refresh
- private Filter<KanbanSubscriber> GetKanbanSubscriberFilter(Filter<KanbanSubscriber>? additional = null)
- {
- var filter = new Filter<KanbanSubscriber>(c => c.Kanban.Closed).IsEqualTo(DateTime.MinValue)
- .And(x => x.Kanban.Locked).IsEqualTo(false);
- var privateFilter = new Filter<KanbanSubscriber>(x => x.Kanban.Private).IsEqualTo(false);
- if (App.EmployeeID != Guid.Empty)
- {
- privateFilter = privateFilter.Or(x => x.Employee.ID).IsEqualTo(App.EmployeeID);
- }
- filter.And(privateFilter);
- if (Host.Master != null)
- filter = filter.And(c => c.Kanban.JobLink.ID).IsEqualTo(Host.Master.ID);
-
- if (!Host.KanbanSettings.UserSettings.IncludeCompleted)
- filter = filter.And(new Filter<KanbanSubscriber>(x => x.Kanban.Completed).IsEqualTo(DateTime.MinValue));
- var emps = Employees.Where(x => Host.KanbanSettings.UserSettings.SelectedEmployees.Contains(x.Key));
- filter = filter.And(c => c.Employee.ID).InList(emps.Select(x => x.Key).ToArray());
- if (!Host.KanbanSettings.UserSettings.IncludeObserved)
- {
- if (Host.KanbanSettings.UserSettings.IncludeManaged)
- filter = filter.And(new Filter<KanbanSubscriber>(x => x.Manager).IsEqualTo(true).Or(x => x.Assignee).IsEqualTo(true));
- else
- filter = filter.And(x => x.Assignee).IsEqualTo(true);
- }
- if (additional is not null)
- {
- return additional.And(filter);
- }
- else
- {
- return filter;
- }
- }
- private void ReloadColumns()
- {
- Model.SectionHeaders.SupressNotification = true;
- Model.SectionHeaders.Clear();
- var emps = Host.KanbanSettings.UserSettings.SelectedEmployees.Where(x => Employees.ContainsKey(x)).OrderBy(x => Employees[x].Name).ToArray();
- foreach (var employeeID in emps)
- {
- if (Employees.TryGetValue(employeeID, out var employee))
- {
- Model.SectionHeaders.Add(new TasksByUserEmployeeHeader(employeeID, employee.Name, employee.Image ?? anonymous, Model));
- }
- }
- Model.SectionHeaders.SupressNotification = false;
- Model.Categories.SupressNotification = true;
- var oldCategories = Model.Categories.ToDictionary(x => x.Status);
- Model.Categories.Clear();
- foreach (var status in _statusOrder)
- {
- if (status == KanbanStatus.Complete && !Host.KanbanSettings.UserSettings.IncludeCompleted)
- {
- continue;
- }
- var newCategory = new TasksByUserCategory(status, oldCategories.GetValueOrDefault(status)?.Collapsed ?? false);
- foreach (var employeeID in emps)
- {
- if (Employees.TryGetValue(employeeID, out var employee))
- {
- var cat = new TasksByUserEmployeeCategory(employeeID, status);
- newCategory.EmployeeCategoryDictionary[employeeID] = cat;
- var header = Model.SectionHeaders.First(x => x.EmployeeID == employeeID);
- cat.Tasks.CollectionChanged += (s, e) =>
- {
- header.UpdateTasks();
- };
- }
- }
- Model.Categories.Add(newCategory);
- }
- Model.Categories.SupressNotification = false;
- }
- private static readonly KanbanStatus[] _statusOrder = new[]
- {
- KanbanStatus.Open,
- KanbanStatus.InProgress,
- KanbanStatus.Waiting,
- KanbanStatus.Complete
- };
- private Columns<Kanban> GetKanbanColumns()
- {
- return Columns.None<Kanban>().Add(
- x => x.ID,
- x => x.DueDate,
- x => x.Completed,
- x => x.Description,
- x => x.Summary,
- x => x.Status,
- x => x.EmployeeLink.ID,
- x => x.EmployeeLink.Name,
- x => x.ManagerLink.ID,
- x => x.ManagerLink.Name,
- x => x.Notes,
- x => x.Title,
- x => x.JobLink.ID,
- x => x.JobLink.JobNumber,
- x => x.JobLink.Name,
- x => x.Type.ID,
- x => x.Type.Code,
- x => x.Number,
- x => x.Attachments,
- x => x.Locked,
- x => x.EstimatedTime);
- }
- private IEnumerable<KanbanSubscriber> LoadSubscribers(Filter<KanbanSubscriber>? filter = null)
- {
- filter = GetKanbanSubscriberFilter(filter);
- var kanbanFilter = new Filter<Kanban>(x => x.ID).InQuery(filter, x => x.Kanban.ID);
- var buttonFilter = FilterButton.GetFilter();
- if(buttonFilter is not null)
- {
- kanbanFilter.And(buttonFilter);
- }
- var results = Client.QueryMultiple(
- new KeyedQueryDef<KanbanSubscriber>(
- filter,
- Columns.None<KanbanSubscriber>().Add(x => x.ID, x => x.Employee.ID, x => x.Kanban.ID),
- new SortOrder<KanbanSubscriber>(x => x.Kanban.DueDate) { Direction = SortDirection.Ascending }),
- new KeyedQueryDef<Kanban>(
- kanbanFilter,
- GetKanbanColumns()));
- var kanbans = results.GetObjects<Kanban>().ToDictionary(x => x.ID);
- return results.GetObjects<KanbanSubscriber>().Select(x =>
- {
- if (kanbans.TryGetValue(x.Kanban.ID, out var kanban))
- {
- x.Kanban.Synchronise(kanban);
- return x;
- }
- else
- {
- return null;
- }
- }).NotNull();
- }
- public void Refresh()
- {
- using (new WaitCursor())
- {
- var models = CreateModels(LoadSubscribers()).ToList();
- ReloadColumns();
- AllTasks = models.OrderBy(x => x.DueDate).ToList();
- FilterKanbans();
- }
- }
- /// <summary>
- /// Take the full list of kanbans loaded from the database, and filter based on the search UI elements, filtering into the columns.
- /// </summary>
- private void FilterKanbans()
- {
- IEnumerable<TaskModel> filtered = AllTasks;
- if (TaskType.SelectedItem is KanbanType kanbanType)
- {
- filtered = filtered.Where(x => x.Type.ID == kanbanType.ID);
- }
- if (!string.IsNullOrWhiteSpace(Search.Text))
- {
- var searches = Search.Text.Split();
- filtered = filtered.Where(x => x.Search(searches));
- }
- var categoryMap = Model.Categories.ToDictionary(x => x.Status, x => x.EmployeeCategoryDictionary);
- foreach(var category in Model.Categories)
- {
- foreach(var empCat in category.EmployeeCategories)
- {
- empCat.Tasks.Clear();
- }
- }
- SelectedTasks.Clear();
- foreach (var task in filtered)
- {
- if(categoryMap.TryGetValue(task.Status, out var categoryDict))
- {
- if (categoryDict.TryGetValue(task.EmployeeCategory, out var employeeCategory))
- {
- employeeCategory.Tasks.Add(task);
- if (task.Checked)
- {
- SelectedTasks.Add(task);
- }
- }
- }
- }
- }
- private IEnumerable<TaskModel> CreateModels(IEnumerable<KanbanSubscriber> subscribers)
- {
- foreach(var subscriber in subscribers)
- {
- var kanban = subscriber.Kanban;
- var model = new TaskModel
- {
- Title = kanban.Title,
- ID = kanban.ID,
- Description = kanban.Summary ?? "",
- EmployeeCategory = subscriber.Employee.ID,
- Status = kanban.Status,
- Attachments = kanban.Attachments > 0,
- DueDate = kanban.DueDate,
- CompletedDate = kanban.Completed,
- Locked = kanban.Locked,
- EstimatedTime = kanban.EstimatedTime,
- EmployeeID = kanban.EmployeeLink.ID,
- ManagerID = kanban.ManagerLink.ID,
- JobID = kanban.JobLink.ID,
- JobNumber = kanban.JobLink.JobNumber?.Trim() ?? "",
- JobName = kanban.JobLink.Name,
- Type = new KanbanType
- {
- ID = kanban.Type.ID,
- Code = kanban.Type.Code
- },
- Number = kanban.Number,
- Checked = SelectedTasks.Any(x => x.ID == kanban.ID)
- };
- var colour = subscriber.Employee.ID == kanban.EmployeeLink.ID
- ? TaskModel.KanbanColor(
- kanban.DueDate,
- kanban.Completed)
- : subscriber.Employee.ID == kanban.ManagerLink.ID
- ? Color.Silver
- : Color.Plum;
- if (kanban.Locked)
- {
- colour = colour.MixColors(0.5F, Color.White);
- }
- model.Color = System.Windows.Media.Color.FromArgb(colour.A, colour.R, colour.G, colour.B);
- var notes = new List<List<string>> { new() };
- var kanbanNotes = kanban.Notes;
- if (kanbanNotes != null)
- {
- foreach (var line in kanbanNotes)
- {
- if (line == "===================================")
- {
- notes.Add(new());
- }
- else
- {
- notes.Last().Add(line);
- }
- }
- }
- model.Notes = string.Join("\n===================================\n", notes.Reverse<List<string>>().Select(x => string.Join('\n', x)));
- SetTaskModelAssignedTo(model, kanban, subscriber.Employee.ID);
- yield return model;
- }
- }
- private static void SetTaskModelAssignedTo(TaskModel model, IKanban kanban, Guid subscriberID)
- {
- var employeeString = kanban.EmployeeLink.ID == subscriberID
- ? ""
- : kanban.EmployeeLink.ID == Guid.Empty
- ? " to (Unallocated)"
- : " to " + kanban.EmployeeLink.Name;
- var managerString = kanban.ManagerLink.ID == Guid.Empty || kanban.ManagerLink.ID == subscriberID
- ? ""
- : " by " + kanban.ManagerLink.Name;
- model.AssignedTo = !string.IsNullOrEmpty(employeeString) || !managerString.IsNullOrWhiteSpace()
- ? $"Assigned{employeeString}{managerString}"
- : "";
- }
- #endregion
- #region Kanban
- private readonly List<TaskModel> SelectedTasks = new();
- private List<TaskModel> AllTasks { get; set; } = new();
- private void DoEdit(TaskModel task)
- {
- var result = Host.EditReferences(new[] { task });
- if (result)
- {
- Refresh();
- }
- }
- 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 KanbanResources.OpenTaskMenuCommandArgs args) return;
- Host.PopulateMenu(this, args.Model, args.Menu);
- }
- 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 = true;
- }
- private void ItemsControl_DragOver(object sender, DragEventArgs e)
- {
- if (sender is not FrameworkElement element || element.Tag is not TasksByUserEmployeeCategory category) return;
- e.Effects = DragDropEffects.None;
- if (e.Data.GetDataPresent(typeof(TaskModel)))
- {
- var model = e.Data.GetData(typeof(TaskModel)) as TaskModel;
- if (model is not null
- && (model.Status != category.Status || model.EmployeeCategory != category.EmployeeID)
- && !SelectedTasks.Any(x => x.Locked)
- && SelectedTasks.Concat(CoreUtils.One(model)).Any(x => x.IsAssignee))
- {
- e.Effects = DragDropEffects.Move;
- }
- }
- }
- private void ItemsControl_Drop(object sender, DragEventArgs e)
- {
- if (sender is not FrameworkElement element || element.Tag is not TasksByUserEmployeeCategory category) return;
- if (e.Data.GetDataPresent(typeof(TaskModel)))
- {
- var models = SelectedModels(e.Data.GetData(typeof(TaskModel)) as TaskModel)
- .Where(x => (!x.Status.Equals(category.Status) || x.EmployeeID != category.EmployeeID) && x.IsAssignee)
- .ToList();
- if (!models.Any())
- {
- return;
- }
- var changingCategory = models.Any(x => !x.Status.Equals(category.Status));
- var completing = changingCategory && category.Status == KanbanStatus.Complete;
- var completed = DateTime.Now;
- if (completing)
- {
- if (!MessageWindow.ShowYesNo($"Are you sure you want to complete the selected tasks?", "Confirm Completion"))
- return;
- }
- var kanbans = Host.LoadKanbans(models, Columns.Required<Kanban>().Add(x => x.ID, x => x.EmployeeLink.ID, x => x.Private, x => x.Number, x => x.Status));
- var subscribers = new ClientKanbanSubscriberSet(kanbans.Select(x => x.ID));
- foreach(var kanban in kanbans)
- {
- if (!kanban.Private)
- {
- kanban.EmployeeLink.ID = category.EmployeeID;
- subscribers.EnsureAssignee(kanban.ID, kanban.EmployeeLink.ID);
- kanban.Status = category.Status;
- if (completing)
- {
- kanban.Completed = completed;
- }
- }
- else
- {
- MessageBox.Show($"Cannot change assignee for task {kanban.Number} because it is private.");
- models.RemoveAll(x => x.ID == kanban.ID);
- }
- }
- Client.Save(kanbans.Where(x => x.IsChanged()), $"Task Employee Updated");
- subscribers.Save(true);
- var kanbanIDs = models.Select(x => x.ID).ToArray();
- AllTasks.RemoveAll(x => kanbanIDs.Contains(x.ID));
- AllTasks.AddRange(CreateModels(LoadSubscribers(new Filter<KanbanSubscriber>(x => x.Kanban.ID).InList(kanbanIDs))));
- AllTasks.Sort((x, y) => x.DueDate.CompareTo(y.DueDate));
- FilterKanbans();
- }
- }
- #endregion
- #region ITaskControl
- public ITaskHost Host { get; set; }
- public KanbanViewType KanbanViewType => KanbanViewType.User;
- public bool IsReady { get; set; }
- public string SectionName => "Task List";
- public DataModel DataModel(Selection selection)
- {
- var ids = SelectedModels().Select(x => x.ID).ToArray();
- return new AutoDataModel<Kanban>(new Filter<Kanban>(x => x.ID).InList(ids));
- }
- public IEnumerable<TaskModel> SelectedModels(TaskModel? sender = null)
- {
- if (sender is null)
- {
- return SelectedTasks;
- }
- else
- {
- var result = SelectedTasks.ToList();
- if (!result.Contains(sender))
- {
- result.Add(sender);
- }
- return result;
- }
- }
- #endregion
- #region Settings
- private void SaveSettings()
- {
- Host.KanbanSettings.UserSettings.AnchorWidth = SplitPanel.AnchorWidth;
- Host.KanbanSettings.UserSettings.TeamsHeight = SelectedTeams.ActualHeight;
- var teams = SelectedTeams.SelectedItems.Select(x => ((KeyValuePair<Guid, string>)x).Key);
- Host.KanbanSettings.UserSettings.SelectedTeams = teams.ToArray();
- var emps = SelectedEmployees.SelectedItems.Select(x => ((KeyValuePair<Guid, EmployeeModel>)x).Key);
- emps = emps.Where(e => TeamEmployees.Any(t => t.Contains(e)));
- Host.KanbanSettings.UserSettings.SelectedEmployees = emps.ToArray();
- Host.KanbanSettings.UserSettings.IncludeCompleted = IncludeCompleted.IsChecked == true;
- Host.KanbanSettings.UserSettings.IncludeObserved = IncludeObserved.IsChecked == true;
- Host.KanbanSettings.UserSettings.IncludeManaged = IncludeManaged.IsChecked == true;
- Host.SaveSettings();
- }
- private void SplitPanel_OnChanged(object sender, DynamicSplitPanelSettings e)
- {
- if (!IsReady || Equals(Host.KanbanSettings.UserSettings.AnchorWidth, e.AnchorWidth))
- return;
- SaveSettings();
- }
- private void SelectedTeams_ItemChecked(object sender, ItemCheckedEventArgs e)
- {
- if (!IsReady)
- return;
- PopulateEmployees();
- SaveSettings();
- Refresh();
- }
- private void SelectedTeams_SizeChanged(object sender, SizeChangedEventArgs e)
- {
- if (!IsReady || Equals(Host.KanbanSettings.UserSettings.TeamsHeight, SelectedTeams.ActualHeight))
- return;
- SaveSettings();
- }
- private void SelectedEmployees_ItemChecked(object sender, ItemCheckedEventArgs e)
- {
- if (!IsReady || bPopulating || sender != SelectedEmployees)
- return;
- SaveSettings();
- Refresh();
- }
- private void ViewType_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (!IsReady)
- return;
- Mode = ViewType.SelectedIndex switch
- {
- 0 => KanbanViewMode.Full,
- 1 => KanbanViewMode.Compact,
- _ => KanbanViewMode.Full
- };
- if (IsReady)
- {
- Host.KanbanSettings.UserSettings.CompactView = Mode == KanbanViewMode.Compact;
- Host.SaveSettings();
- }
- }
- #endregion
- private void Export_Click(object sender, RoutedEventArgs e)
- {
- var form = new DynamicExportForm(typeof(Kanban), GetKanbanColumns().ColumnNames());
- if (form.ShowDialog() != true)
- return;
- var export = Client.Query(
- new Filter<Kanban>(x => x.ID).InQuery(GetKanbanSubscriberFilter(), x => x.Kanban.ID),
- Columns.None<Kanban>().Add(form.Fields),
- LookupFactory.DefineSort<Kanban>()
- );
- var employee = "Tasks for " + string.Join(',', Employees.Where(x => Host.KanbanSettings.UserSettings.SelectedEmployees.Contains(x.Key)).Select(x => x.Value.Name));
- ExcelExporter.DoExport<Kanban>(
- export,
- string.Format(
- "{0} ({1:dd-MMM-yy})",
- employee,
- DateTime.Today
- )
- );
- }
- private void FoldButton_Click(object sender, RoutedEventArgs e)
- {
- if (sender is not FrameworkElement element || element.Tag is not TasksByUserCategory category) return;
- category.Collapsed = !category.Collapsed;
- }
- }
|