123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Linq;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using Comal.Classes;
- using InABox.Clients;
- using InABox.Core;
- using InABox.DynamicGrid;
- using InABox.WPF;
- using Syncfusion.Windows.Controls.Gantt;
- using Syncfusion.Windows.Controls.Grid;
- using GridSelectionMode = Syncfusion.Windows.Controls.Grid.GridSelectionMode;
- namespace PRSDesktop
- {
- /// <summary>
- /// Interaction logic for TaskPlannerControl.xaml
- /// </summary>
- public partial class TaskPlannerControl : UserControl, ITaskControl
- {
- private enum Suppress
- {
- This
- }
-
- private CoreTable _kanbans;
- private CoreTable _relationships;
- private readonly ObservableCollection<Resource> _resources = new();
- private CoreTable _stages;
- private readonly ObservableCollection<GanttTask> _tasks = new();
- private bool bLoading;
- public TaskPlannerControl()
- {
- using (new EventSuppressor(Suppress.This))
- {
- InitializeComponent();
- Gantt.ItemsSource = _tasks;
- Gantt.ResourceCollection = _resources;
- }
- }
- public void Setup()
- {
- LoadKanbanTypes();
- }
- private void LoadKanbanTypes()
- {
- using (new EventSuppressor(Suppress.This))
- {
- var types = new Dictionary<Guid, string>
- {
- { CoreUtils.FullGuid, "All Task Types" },
- { Guid.Empty, "Uncategorized Tasks" }
- };
- new Client<KanbanType>().Query(new Filter<KanbanType>(x => x.Hidden).IsEqualTo(false))
- .IntoDictionary<Kanban, Guid>(types, x => x.ID, x => x.Description);
- SelectedType.ItemsSource = types;
- }
- }
- public void Refresh(bool resetselection)
- {
- Refresh();
- }
- public void Shutdown()
- {
- }
- private void Gantt_TemplateApplied(object sender, TemplateAppliedEventArgs args)
- {
- if (Gantt.GanttGrid != null)
- {
- Gantt.GanttGrid.Model.Options.ListBoxSelectionMode = GridSelectionMode.One;
- Gantt.GanttGrid.Model.Sizer.AllowAutoCalculateSize = true;
- Gantt.GanttGrid.Model.Sizer.ListenToSizeChanged = true;
- Gantt.GanttGrid.Model.Options.ColumnSizer = GridControlLengthUnitType.Star;
- Gantt.GanttGrid.RowHeaderWidth = 0;
- Gantt.GanttGrid.ShowRowHeader = false;
- CreateGanttColumns();
- //Gantt.GanttGrid.ReadOnly = true;
- }
- }
- private void CreateGanttColumns()
- {
- if (Gantt.GanttGrid == null)
- return;
- Gantt.GanttGrid.Columns.Clear();
- //Gantt.GanttGrid.Columns.Add(new Syncfusion.Windows.Controls.Grid.GridTreeColumn("TaskId") { Width = 60F, HeaderText = "#", StyleInfo = new Syncfusion.Windows.Controls.Grid.GridStyleInfo() { VerticalAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center } });
- Gantt.GanttGrid.Columns.Add(new GridTreeColumn("TaskName")
- {
- Width = 220F, PercentWidth = 100F, HeaderText = "Description",
- StyleInfo = new GridStyleInfo { VerticalAlignment = VerticalAlignment.Center }
- });
- Gantt.GanttGrid.Columns.Add(new GridTreeColumn("StartDate")
- {
- Width = 70F, HeaderText = "Start",
- StyleInfo = new GridStyleInfo
- { VerticalAlignment = VerticalAlignment.Center, Format = "dd MMM yy", HorizontalAlignment = HorizontalAlignment.Center }
- });
- Gantt.GanttGrid.Columns.Add(new GridTreeColumn("Manpower")
- {
- Width = 60F, HeaderText = "Hrs",
- StyleInfo = new GridStyleInfo { VerticalAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center }
- });
- Gantt.GanttGrid.Columns.Add(new GridTreeColumn("Percentage")
- {
- Width = 40F, HeaderText = "%",
- StyleInfo = new GridStyleInfo
- { VerticalAlignment = VerticalAlignment.Center, Format = "#0.##%", HorizontalAlignment = HorizontalAlignment.Center }
- });
- Gantt.GanttGrid.Columns.Add(new GridTreeColumn("FinishDate")
- {
- Width = 70F, HeaderText = "Due",
- StyleInfo = new GridStyleInfo
- { VerticalAlignment = VerticalAlignment.Center, Format = "dd MMM yy", HorizontalAlignment = HorizontalAlignment.Center }
- });
- }
- private void LoadData()
- {
- var query = new MultiQuery();
- query.Add(
- new QueryDef<Kanban>(
- new Filter<Kanban>(x => x.Closed).IsEqualTo(DateTime.MinValue).And(x => x.JobLink.ID).IsEqualTo(Host.ParentID),
- new Columns<Kanban>
- (
- x => x.ID,
- x => x.Created,
- x => x.DueDate,
- x => x.Completed,
- x => x.Description,
- x => x.Summary,
- x => x.Category,
- x => x.EmployeeLink.ID,
- x => x.EmployeeLink.Name,
- x => x.ManagerLink.ID,
- x => x.Title,
- x => x.Notes,
- x => x.Number,
- x => x.Attachments,
- x => x.Type.Code,
- x => x.StartDate,
- x => x.EstimatedTime,
- x => x.ActualTime,
- x => x.Type.ID
- ),
- new SortOrder<Kanban>(x => x.DueDate).ThenBy(x => x.StartDate)
- ),
- typeof(Kanban)
- );
- query.Add(
- new QueryDef<JobStage>(
- new Filter<JobStage>(x => x.Job.ID).IsEqualTo(Host.ParentID),
- null,
- null
- ),
- typeof(JobStage)
- );
- query.Add(
- new QueryDef<KanbanRelationship>(
- new Filter<KanbanRelationship>(x => x.Parent.ID).IsEqualTo(Host.ParentID),
- new Columns<KanbanRelationship>(
- x => x.ID,
- x => x.Predecessor.ID,
- x => x.Successor.ID,
- x => x.Type,
- x => x.Parent.ID
- ),
- null
- ),
- typeof(KanbanRelationship)
- );
- query.Query();
- _kanbans = query.Get(typeof(Kanban));
- _stages = query.Get(typeof(JobStage));
- _relationships = query.Get(typeof(KanbanRelationship));
- }
- public void Refresh()
- {
- bLoading = true;
- using (new WaitCursor())
- {
- try
- {
- LoadData();
- _tasks.Clear();
- var startmarker = new GanttTask
- {
- StartDate = DateTime.Today,
- FinishDate = DateTime.Today,
- TaskName = "Start of Job",
- IsMileStone = true
- };
- var endmarker = new GanttTask
- {
- StartDate = DateTime.Today,
- FinishDate = DateTime.Today,
- TaskName = "End of Job",
- IsMileStone = true
- };
- var curstart = DateTime.MaxValue;
- var curend = DateTime.MinValue;
- _tasks.Add(startmarker);
- foreach (var row in _kanbans.Rows)
- if ((Host.KanbanSettings.PlannerSettings.IncludeCompleted || row.Get<Kanban, DateTime>(c => c.Completed).IsEmpty()) &&
- (Host.KanbanSettings.PlannerSettings.SelectedType == CoreUtils.FullGuid ||
- row.Get<Kanban, Guid>(c => c.Type.ID) == Host.KanbanSettings.PlannerSettings.SelectedType))
- {
- var task = new GanttTask();
- LoadTask(row, task);
- if (task.StartDate < curstart)
- curstart = task.StartDate;
- if (task.FinishDate > curend)
- curend = task.FinishDate;
- _tasks.Add(task);
- }
- _tasks.Add(endmarker);
- foreach (var row in _relationships.Rows)
- {
- var predtask = _tasks.FirstOrDefault(x => x.ID == row.Get<KanbanRelationship, Guid>(c => c.Predecessor.ID));
- var succtask = _tasks.FirstOrDefault(x => x.ID == row.Get<KanbanRelationship, Guid>(c => c.Successor.ID));
- if (predtask != null && succtask != null)
- {
- var type = row.Get<KanbanRelationship, GanttRelationshipType>(x => x.Type);
- var relationship = type == GanttRelationshipType.FinishToFinish
- ? GanttTaskRelationship.FinishToFinish
- : type == GanttRelationshipType.FinishToStart
- ? GanttTaskRelationship.FinishToStart
- : type == GanttRelationshipType.StartToFinish
- ? GanttTaskRelationship.StartToFinish
- : GanttTaskRelationship.StartToStart;
- succtask.Predecessor.Add(new Predecessor { GanttTaskIndex = predtask.TaskId, GanttTaskRelationship = relationship });
- }
- }
- var _striplines = new List<StripLineInfo>();
- foreach (var row in _stages.Rows)
- {
- if (!_striplines.Any())
- {
- var startline = new StripLineInfo();
- startline.Content = "Start of Job";
- startline.StartDate = row.Get<JobStage, DateTime>(c => c.StartDate);
- startline.EndDate = startline.StartDate;
- startline.HorizontalContentAlignment = HorizontalAlignment.Center;
- startline.VerticalContentAlignment = VerticalAlignment.Center;
- startline.Background = Brushes.Gold;
- startline.RepeatBehavior = Repeat.None;
- _striplines.Add(startline);
- }
- var stripline = new StripLineInfo();
- stripline.Content = row.Get<JobStage, string>(c => c.Name);
- stripline.StartDate = row.Get<JobStage, DateTime>(c => c.EndDate);
- stripline.EndDate = stripline.StartDate;
- stripline.HorizontalContentAlignment = HorizontalAlignment.Center;
- stripline.VerticalContentAlignment = VerticalAlignment.Center;
- stripline.Background = Brushes.Gold;
- stripline.RepeatBehavior = Repeat.None;
- _striplines.Add(stripline);
- if (stripline.StartDate < curstart)
- curstart = stripline.StartDate;
- if (stripline.EndDate > curend)
- curend = stripline.EndDate;
- }
- Gantt.StripLines = _striplines;
- Gantt.ShowStripLines = true;
- Gantt.UseOnDemandSchedule = true;
- if (curstart != DateTime.MaxValue)
- {
- startmarker.StartDate = curstart.Date;
- startmarker.FinishDate = curstart.Date;
- }
- if (curend != DateTime.MinValue)
- {
- endmarker.StartDate = curend.Date.AddDays(1);
- endmarker.FinishDate = curend.AddDays(1);
- }
- }
- finally
- {
- bLoading = false;
- }
- foreach (var task in _tasks)
- task.PropertyChanged += Task_PropertyChanged;
- }
- }
- private void LoadTask(CoreRow row, GanttTask task)
- {
- var start = row.Get<Kanban, DateTime>(x => x.StartDate);
- if (start.IsEmpty())
- start = row.Get<Kanban, DateTime>(x => x.Created);
- var estimated = row.Get<Kanban, TimeSpan>(x => x.EstimatedTime);
- if (estimated.TotalMilliseconds == 0L)
- estimated = TimeSpan.FromHours(1);
- var actual = row.Get<Kanban, TimeSpan>(x => x.ActualTime);
- var progress = estimated.TotalMilliseconds != 0L ? actual.TotalMilliseconds * 100L / estimated.TotalMilliseconds : 0F;
- task.TaskId = row.Get<Kanban, int>(c => c.Number);
- task.ID = row.Get<Kanban, Guid>(x => x.ID);
- task.TaskName = string.Format("{0} - {1}", row.Get<Kanban, int>(c => c.Number), row.Get<Kanban, string>(x => x.Title));
- task.StartDate = start.Date;
- task.FinishDate = row.Get<Kanban, DateTime>(x => x.DueDate).Date.AddDays(1).AddMilliseconds(-1);
- task.Manpower = estimated;
- task.Percentage = progress;
- task.IsMileStone = false;
- var empid = row.EntityLinkID<Kanban, EmployeeLink>(x => x.EmployeeLink) ?? Guid.Empty;
- if (empid != Guid.Empty)
- {
- var resource = _resources.FirstOrDefault(x => (x as GanttResource).Guid == empid) as GanttResource;
- if (resource == null)
- {
- resource = new GanttResource
- {
- ID = _resources.Count,
- Guid = empid,
- Name = row.Get<Kanban, string>(c => c.EmployeeLink.Name)
- };
- _resources.Add(resource);
- }
- task.Resources = new ObservableCollection<Resource> { resource };
- }
- }
- private void Task_PropertyChanged(object sender, PropertyChangedEventArgs args)
- {
- if (bLoading)
- return;
- if (!string.Equals(args.PropertyName, "StartDate") && !string.Equals(args.PropertyName, "FinishDate"))
- return;
- var row = _kanbans.Rows.FirstOrDefault(r => r.Get<Kanban, Guid>(x => x.ID) == ((GanttTask)sender).ID);
- var kanban = row?.ToObject<Kanban>();
- var task = sender as GanttTask;
- var bChanged = false;
- if (task != null && kanban != null)
- {
- if (string.Equals(args.PropertyName, "FinishDate"))
- {
- kanban.DueDate = task.FinishDate.Date;
- bChanged = true;
- }
- else if (string.Equals(args.PropertyName, "StartDate"))
- {
- kanban.StartDate = task.StartDate.Date;
- bChanged = true;
- }
- }
- if (bChanged)
- {
- row.Set<Kanban, DateTime>(x => x.DueDate, kanban.DueDate.Date);
- row.Set<Kanban, DateTime>(x => x.StartDate, kanban.StartDate.Date);
- new Client<Kanban>().Save(kanban, "Updated by Planner", (o, e) => { });
- }
- }
- private void Gantt_RelationshipEstablished(object sender, GanttRelationshipEstablishedEventArgs args)
- {
- var pred = args.StartTask as GanttTask;
- var succ = args.EndTask as GanttTask;
- if (pred == null || pred.IsMileStone)
- throw new Exception("Cannot make a connection here");
- if (succ == null || succ.IsMileStone)
- throw new Exception("Cannot make a connection here");
- var relationship = new KanbanRelationship();
- relationship.Parent.ID = Host.ParentID;
- relationship.Predecessor.ID = pred.ID;
- relationship.Successor.ID = succ.ID;
- relationship.Type = args.Relationship == GanttTaskRelationship.FinishToFinish
- ? GanttRelationshipType.FinishToFinish
- : args.Relationship == GanttTaskRelationship.FinishToStart
- ? GanttRelationshipType.FinishToStart
- : args.Relationship == GanttTaskRelationship.StartToFinish
- ? GanttRelationshipType.StartToFinish
- : GanttRelationshipType.StartToStart;
- new Client<KanbanRelationship>().Save(relationship, "", (o, e) =>
- {
- var row = _relationships.NewRow();
- _relationships.LoadRow(row, relationship);
- _relationships.Rows.Add(row);
- });
- }
- private void GanttContextMenu_Opened(object sender, RoutedEventArgs e)
- {
- var task = Gantt.SelectedItems.FirstOrDefault() as GanttTask;
- UnlinkTaskMenu.IsEnabled = task != null && task.Predecessor.Any();
- UnlinkTaskMenu.Tag = task;
- }
- private void UnlinkTaskMenu_Click(object sender, RoutedEventArgs args)
- {
- var successor = (sender as MenuItem).Tag as GanttTask;
- if (successor == null)
- return;
- var deletes = new List<KanbanRelationship>();
- foreach (var link in successor.Predecessor)
- {
- var predecessor = _tasks.FirstOrDefault(x => x.TaskId == link.GanttTaskIndex);
- if (predecessor != null)
- {
- var rows = _relationships.Rows.Where(r =>
- r.Get<KanbanRelationship, Guid>(c => c.Successor.ID).Equals(successor.ID) &&
- r.Get<KanbanRelationship, Guid>(c => c.Predecessor.ID).Equals(predecessor.ID)).ToArray();
- foreach (var row in rows)
- {
- deletes.Add(row.ToObject<KanbanRelationship>());
- _relationships.Rows.Remove(row);
- }
- }
- }
- if (deletes.Any())
- new Client<KanbanRelationship>().Delete(deletes, "", (o, e) => { });
- successor.Predecessor.Clear();
- }
- private void EditTask_Click(object sender, RoutedEventArgs e)
- {
- DoEditTask();
- }
- private void DoEditTask()
- {
- var task = Gantt.SelectedItems.FirstOrDefault() as GanttTask;
- if (task == null)
- return;
- var row = _kanbans.Rows.FirstOrDefault(r => r.Get<Kanban, Guid>(x => x.ID) == task.ID);
- var kanban = row?.ToObject<Kanban>();
- if (kanban != null)
- {
- var bOK = new KanbanGrid().EditItems(new[] { kanban });
- if (bOK)
- {
- _kanbans.LoadRow(row, kanban);
- LoadTask(row, task);
- }
- }
- }
- private void AddTask_Click(object sender, RoutedEventArgs e)
- {
- var kanban = new Kanban();
- kanban.JobLink.ID = Host.ParentID;
- var bOK = new KanbanGrid().EditItems(new[] { kanban });
- if (bOK)
- {
- var row = _kanbans.NewRow();
- _kanbans.LoadRow(row, kanban);
- var task = new GanttTask();
- LoadTask(row, task);
- _tasks.Add(task);
- task.PropertyChanged += Task_PropertyChanged;
- }
- }
- private void SelectedType_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (EventSuppressor.IsSet(Suppress.This))
- {
- Host.KanbanSettings.PlannerSettings.SelectedType = SelectedType.SelectedValue == null ? Guid.Empty : (Guid)SelectedType.SelectedValue;
- Host.SaveSettings();
- Refresh();
- }
- }
- private void IncludeCompleted_Checked(object sender, RoutedEventArgs e)
- {
- Host.KanbanSettings.PlannerSettings.IncludeCompleted = IncludeCompleted.IsChecked == true;
- Host.SaveSettings();
- Refresh();
- }
- #region ITaskControl Support
- public KanbanView KanbanView => KanbanView.Planner;
- public ITaskHost Host { get; set; }
- public bool IsReady { get; set; }
- public string SectionName => "Task Planner";
- public DataModel DataModel(Selection selection)
- {
- return new AutoDataModel<Kanban>(new Filter<Kanban>(x => x.ID).IsEqualTo(Guid.Empty));
- }
- public IEnumerable<TaskModel> SelectedModels(TaskModel sender = null)
- {
- MessageBox.Show("TaskPlannerControl.SelectedModels() is not Implemented!");
- return new TaskModel[] { };
- }
- #endregion
- private void TaskTypeButton_OnClick(object sender, RoutedEventArgs e)
- {
- var list = new MasterList(typeof(KanbanType));
- list.ShowDialog();
- LoadKanbanTypes();
- }
- }
- }
|