DailyReport.xaml.cs 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Globalization;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. using System.Windows;
  8. using System.Windows.Controls;
  9. using System.Windows.Data;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using Comal.Classes;
  13. using InABox.Clients;
  14. using InABox.Configuration;
  15. using InABox.Core;
  16. using InABox.DynamicGrid;
  17. using InABox.WPF;
  18. using InABox.Wpf;
  19. using PRS.Shared;
  20. namespace PRSDesktop
  21. {
  22. public class HTMLConverter : IValueConverter
  23. {
  24. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  25. {
  26. var str = value as string;
  27. return CoreUtils.StripHTML(str);
  28. }
  29. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  30. {
  31. throw new NotImplementedException();
  32. }
  33. }
  34. public class HideIfMineConverter : IValueConverter
  35. {
  36. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  37. {
  38. var guid = (Guid)value;
  39. return guid.Equals(ClientFactory.UserGuid) ? Visibility.Collapsed : Visibility.Visible;
  40. }
  41. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  42. {
  43. throw new NotImplementedException();
  44. }
  45. }
  46. public class DueDateToColorConverter : IValueConverter
  47. {
  48. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  49. {
  50. var duedate = (DateTime)value;
  51. return duedate < DateTime.Today
  52. ? "Salmon"
  53. : duedate < DateTime.Today.AddDays(7)
  54. ? "LightYellow"
  55. : "LightGreen";
  56. }
  57. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  58. {
  59. throw new NotImplementedException();
  60. }
  61. }
  62. public class DateIsInListConverter : IMultiValueConverter
  63. {
  64. public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  65. {
  66. if (values.Length < 2 || !(values[0] is DateTime) || !(values[1] is IEnumerable<HighlightedDate>))
  67. return false;
  68. var date = (DateTime)values[0];
  69. var dateList = (IEnumerable<HighlightedDate>)values[1];
  70. return dateList.Any(hd => hd.Date.Equals(date));
  71. }
  72. public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  73. {
  74. throw new NotImplementedException();
  75. }
  76. }
  77. public class HighlightedDateDescriptionConverter : IMultiValueConverter
  78. {
  79. public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  80. {
  81. if (values.Length < 2 || !(values[0] is DateTime) || !(values[1] is IEnumerable<HighlightedDate>))
  82. return false;
  83. var date = (DateTime)values[0];
  84. var dateList = (IEnumerable<HighlightedDate>)values[1];
  85. var highlightedDate = dateList.FirstOrDefault(hd => hd.Date.Equals(date));
  86. return highlightedDate != null ? highlightedDate.Description : "";
  87. }
  88. public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  89. {
  90. throw new NotImplementedException();
  91. }
  92. }
  93. public class HighlightDatePicker : DatePicker
  94. {
  95. public static readonly DependencyProperty HighlightedDatesProperty =
  96. DependencyProperty.Register("HighlightedDates", typeof(IList<HighlightedDate>), typeof(HighlightDatePicker));
  97. public static readonly DependencyProperty HighlightBrushProperty = DependencyProperty.Register("HighlightBrush", typeof(Brush),
  98. typeof(HighlightDatePicker), new PropertyMetadata(Brushes.Orange));
  99. static HighlightDatePicker()
  100. {
  101. DefaultStyleKeyProperty.OverrideMetadata(typeof(HighlightDatePicker), new FrameworkPropertyMetadata(typeof(HighlightDatePicker)));
  102. }
  103. public IList<HighlightedDate> HighlightedDates
  104. {
  105. get => (IList<HighlightedDate>)GetValue(HighlightedDatesProperty);
  106. set => SetValue(HighlightedDatesProperty, value);
  107. }
  108. public Brush HighlightBrush
  109. {
  110. get => (Brush)GetValue(HighlightBrushProperty);
  111. set => SetValue(HighlightBrushProperty, value);
  112. }
  113. }
  114. public class HighlightedDate
  115. {
  116. public HighlightedDate(DateTime date, string description)
  117. {
  118. Date = date;
  119. Description = description;
  120. }
  121. public DateTime Date { get; set; }
  122. public string Description { get; set; }
  123. }
  124. public class RequiredReport
  125. {
  126. public RequiredReport(Guid id, DateTime date, TimeSpan start, TimeSpan finish, string notes)
  127. {
  128. ID = id;
  129. Date = date;
  130. Start = start;
  131. Finish = finish;
  132. Notes = notes;
  133. }
  134. public Guid ID { get; set; }
  135. public DateTime Date { get; set; }
  136. public TimeSpan Start { get; set; }
  137. public TimeSpan Finish { get; set; }
  138. public string Notes { get; set; }
  139. }
  140. public class TimeSheetConfirmedArgs : EventArgs
  141. {
  142. public DateTime Date { get; set; }
  143. }
  144. public delegate void TimeSheetConfirmedEvent(TimeSheetConfirmedArgs e);
  145. /// <summary>
  146. /// Interaction logic for DailyReport.xaml
  147. /// </summary>
  148. public partial class DailyReport : UserControl, IPanel<Assignment>, IDynamicEditorHost
  149. {
  150. private DailyActivityScreenSettings _settings;
  151. private KanbanStatus _taskcategory = KanbanStatus.Open;
  152. private bool bProgramaticallyChanging = false;
  153. private bool bSelectingAssignment;
  154. private AssignmentModel copiedAssignment;
  155. private TaskGrid kg = new();
  156. private MenuItem MoveToComplete;
  157. private MenuItem MoveToCurrent;
  158. private MenuItem MoveToOpen;
  159. private MenuItem MoveToWaiting;
  160. private int RequiredReportIndex;
  161. private readonly List<RequiredReport> RequiredReports = new();
  162. private Assignment SelectedAssignment;
  163. private Point startPoint;
  164. private CalendarSettings Calendar_OnLoadSettings(object sender)
  165. {
  166. var settings = new CalendarSettings();
  167. settings.SettingsVisible = CalendarSettingsVisibility.Disabled;
  168. settings.AssignmentType = CalendarAssignmentType.Automatic;
  169. settings.CalendarView = CalendarViewType.Day;
  170. settings.BackgroundType = CalendarBackgroundType.Automatic;
  171. settings.TimeInterval = CalendarTimeInterval.FifteenMinutes;
  172. settings.EmployeeSelection = new EmployeeSelectorData(new Guid[] { Guid.Empty }, new Guid[] { Employee.ID });
  173. settings.Zoom = _settings.Zoom;
  174. return settings;
  175. }
  176. private void Calendar_OnSaveSettings(object sender, CalendarSettings properties)
  177. {
  178. _settings.Zoom = properties.Zoom;
  179. new UserConfiguration<DailyActivityScreenSettings>().Save(_settings);
  180. }
  181. public DailyReport()
  182. {
  183. InitializeComponent();
  184. ImportEmails.Visibility = Security.CanImport<Email>() ? Visibility.Visible : Visibility.Collapsed;
  185. ImportEmailsImage.Source = PRSDesktop.Resources.target.AsBitmapImage();
  186. ProcessWindowTrackers.Visibility = Security.IsAllowed<MonitorApplicationWindows>() ? Visibility.Visible : Visibility.Collapsed;
  187. ImportHistoryImage.Source = PRSDesktop.Resources.email.AsBitmapImage();
  188. ConfirmTimeSheetImage.Source = PRSDesktop.Resources.tick.AsBitmapImage();
  189. }
  190. #region IDynamicEditorHost
  191. public IEnumerable<DynamicGridColumn> Columns { get; } = InitialiseColumns();
  192. private static DynamicGridColumns InitialiseColumns()
  193. {
  194. var columns = new DynamicGridColumns();
  195. columns.ExtractColumns(typeof(Assignment));
  196. return columns;
  197. }
  198. public void LoadColumns(string column, Dictionary<string, string> columns)
  199. {
  200. //columns.Clear(); commented this out as OtherColumns was being cleared and never loading the required properties. Do we need to clear them?
  201. var comps = column.Split('.').ToList();
  202. comps.RemoveAt(comps.Count - 1);
  203. var prefix = string.Format("{0}.", string.Join(".", comps));
  204. var cols = Columns.Where(x => !x.ColumnName.Equals(column) && x.ColumnName.StartsWith(prefix));
  205. foreach (var col in cols)
  206. columns[col.ColumnName.Replace(prefix, "")] = col.ColumnName;
  207. }
  208. public void LoadLookups(ILookupEditorControl editor)
  209. {
  210. if (editor == Activity) Activity_OnDefineLookups(editor);
  211. else if (editor == Kanban) Task_OnDefineLookups(editor);
  212. else if (editor == ITP) ITP_OnDefineLookups(editor);
  213. }
  214. public Type GetEditorType() => typeof(Assignment);
  215. BaseObject[] IDynamicEditorHost.GetItems() => new[] { SelectedAssignment };
  216. public BaseEditor? GetEditor(DynamicGridColumn column) => column.Editor.CloneEditor();
  217. #endregion
  218. public void Setup()
  219. {
  220. Calendar.DisableUpdate();
  221. try
  222. {
  223. Parallel.ForEach(
  224. new Action[]
  225. {
  226. () => _settings = new UserConfiguration<DailyActivityScreenSettings>().Load(),
  227. () => Employee = new Client<Employee>().Load(new Filter<Employee>(x => x.UserLink.ID).IsEqualTo(ClientFactory.UserGuid)).FirstOrDefault(),
  228. },
  229. (a => a())
  230. );
  231. Calendar.Setup();
  232. LoadRequiredReports();
  233. if (!RequiredReports.Any())
  234. {
  235. var start = TimeSpan.FromHours(6);
  236. var finish = TimeSpan.FromHours(18);
  237. var blocks = Calendar.GetRoster(Employee.ID, DateTime.Today)?.GetBlocks(DateTime.Today, TimeSpan.FromSeconds(0), TimeSpan.FromDays(1));
  238. if (blocks?.Any() == true)
  239. {
  240. start = blocks.Aggregate(TimeSpan.FromDays(1), (time, block) => time.Ticks < block.Start.Ticks ? time : block.Start);
  241. finish = blocks.Aggregate(TimeSpan.Zero, (time, block) => time.Ticks > block.Finish.Ticks ? time : block.Start);
  242. }
  243. RequiredReports.Add(new RequiredReport(Guid.Empty, DateTime.Today, start, finish, ""));
  244. ConfirmDock.Visibility = Visibility.Collapsed;
  245. }
  246. ConfigureEditor(Title, new TextBoxEditor());
  247. ConfigureEditor(ActivityNotes, new MemoEditor());
  248. ConfigureEditor(Start, new TimeOfDayEditor());
  249. ConfigureEditor(Duration, new TimeOfDayEditor());
  250. ConfigureEditor(Finish, new TimeOfDayEditor());
  251. ConfigureEditor(Notes, new MemoEditor());
  252. Activity.EditorDefinition = DatabaseSchema.Property(typeof(Assignment), CoreUtils.GetFullPropertyName<Assignment,Guid>(c=>c.ActivityLink.ID,".")).Editor as ILookupEditor;
  253. Activity.OtherColumns["Color"] = CoreUtils.GetFullPropertyName<Assignment,String>(c=>c.ActivityLink.Color,".");
  254. Activity.OtherColumns["Description"] = CoreUtils.GetFullPropertyName<Assignment,String>(c=>c.ActivityLink.Description,".");
  255. ConfigureEditor(Activity);
  256. ITP.EditorDefinition = DatabaseSchema.Property(typeof(Assignment), "ITP.ID").Editor as ILookupEditor;
  257. ITP.OtherColumns["Code"] = "ITP.Code";
  258. //ConfigureEditor(ITP);
  259. Kanban.EditorDefinition = DatabaseSchema.Property(typeof(Assignment), "Task.ID").Editor as ILookupEditor;
  260. Kanban.OtherColumns["JobLink.ID"] = "JobLink.ID";
  261. Kanban.OtherColumns["JobLink.JobNumber"] = "JobLink.JobNumber";
  262. Kanban.OtherColumns["JobLink.Name"] = "JobLink.Name";
  263. ConfigureEditor(Kanban);
  264. Job.EditorDefinition = DatabaseSchema.Property(typeof(Assignment), "JobLink.ID").Editor as CodePopupEditor;
  265. Job.OtherColumns["JobNumber"] = "JobLink.JobNumber";
  266. Job.OtherColumns["Name"] = "JobLink.Name";
  267. ConfigureEditor(Job);
  268. GotoCurrentRequiredReport();
  269. LoadKanbans(KanbanStatus.Open);
  270. }
  271. finally
  272. {
  273. Calendar.EnableUpdate();
  274. Calendar.Refresh();
  275. }
  276. }
  277. public void Shutdown(CancelEventArgs? cancel)
  278. {
  279. }
  280. private void LoadRequiredReports()
  281. {
  282. var unconfirmed = new Client<TimeSheet>().Query(
  283. new Filter<TimeSheet>(x => x.EmployeeLink.ID).IsEqualTo(Employee.ID).And(x => x.Confirmed).IsEqualTo(DateTime.MinValue)
  284. .And(x => x.LeaveRequestLink).NotLinkValid(),
  285. new Columns<TimeSheet>(x => x.ID, x => x.Date, x => x.Start, x => x.Finish, x => x.Notes),
  286. new SortOrder<TimeSheet>(x => x.Date)
  287. );
  288. var id = Guid.Empty;
  289. var date = DateTime.MinValue;
  290. var start = TimeSpan.MaxValue;
  291. var end = TimeSpan.MinValue;
  292. var notes = new List<string>();
  293. foreach (var row in unconfirmed.Rows)
  294. {
  295. var curid = row.Get<TimeSheet, Guid>(x => x.ID);
  296. var curdate = row.Get<TimeSheet, DateTime>(c => c.Date).Date;
  297. var curstart = row.Get<TimeSheet, TimeSpan>(c => c.Start);
  298. var curend = row.Get<TimeSheet, TimeSpan>(c => c.Finish);
  299. var curnotes = row.Get<TimeSheet, string>(c => c.Notes);
  300. if (date != curdate)
  301. {
  302. if (id != Guid.Empty)
  303. RequiredReports.Add(new RequiredReport(id, date, start, end, string.Join("\n===================================\n", notes)));
  304. id = curid;
  305. date = curdate;
  306. start = TimeSpan.MaxValue;
  307. end = TimeSpan.MinValue;
  308. notes.Clear();
  309. }
  310. start = start > curstart ? curstart : start;
  311. end = end < curend ? curend : end;
  312. if (!string.IsNullOrEmpty(curnotes))
  313. notes.Add(curnotes);
  314. }
  315. if (id != Guid.Empty)
  316. RequiredReports.Add(new RequiredReport(id, date, start, end, string.Join("\n===================================\n", notes)));
  317. }
  318. public Employee Employee { get; set; }
  319. public event DataModelUpdateEvent? OnUpdateDataModel;
  320. public bool IsReady { get; set; }
  321. public void CreateToolbarButtons(IPanelHost host)
  322. {
  323. }
  324. public string SectionName => "Daily Report";
  325. public DataModel DataModel(Selection selected) => Calendar.DataModel(selected);
  326. public void Heartbeat(TimeSpan time)
  327. {
  328. }
  329. public void Refresh()
  330. {
  331. RefreshAssignments();
  332. LoadKanbans();
  333. }
  334. public Dictionary<string, object[]> Selected()
  335. {
  336. return new Dictionary<string, object[]>();
  337. }
  338. public event TimeSheetConfirmedEvent OnTimeSheetConfirmed;
  339. private void PopulateFavourites(ItemsControl menu, RoutedEventHandler action, DateTime time, bool filltime)
  340. {
  341. menu.Items.RemoveAt(0);
  342. var create = new MenuItem { Header = "Create New Assignment" };
  343. create.Tag = new Tuple<DateTime, AssignmentFavourite?>(time, null);
  344. create.Click += action;
  345. menu.Items.Insert(0,create);
  346. if (_settings.Favourites?.Any() == true)
  347. {
  348. menu.Items.Insert(1,new Separator());
  349. int i = 2;
  350. foreach (var favourite in _settings.Favourites)
  351. {
  352. var fav = new MenuItem { Header = favourite.Title };
  353. fav.Tag = new Tuple<DateTime, AssignmentFavourite?>(time, favourite);
  354. fav.Click += action;
  355. menu.Items.Insert(i,fav);
  356. i++;
  357. }
  358. }
  359. }
  360. private void Assignments_OnCustomiseContextMenu(object sender, ICalendarDataEventArgs args)
  361. {
  362. if (sender is not ContextMenu menu)
  363. return;
  364. if (args is CalendarDataEventArgs<CalendarTimeSlot> slot)
  365. {
  366. PopulateFavourites(menu, CreateAssignment_Click, slot.Item.Time, false);
  367. }
  368. else if (args is CalendarDataEventArgs<AssignmentModel> model)
  369. {
  370. menu.Items.Insert(1,new Separator());
  371. var SetAsFavouriteMenu = new MenuItem { Header = GetFavourite(model.Item) == null ? "Set As Favourite" : "Update Favourite"};
  372. SetAsFavouriteMenu.Click += (o, args) => SetAsFavourite(model.Item);
  373. menu.Items.Insert(2,SetAsFavouriteMenu);
  374. if (_settings.Favourites.Any())
  375. {
  376. var ManageFavouritesMenu = new MenuItem { Header = "Manage Favourites" };
  377. ManageFavouritesMenu.Click += ManageFavourites_Click;
  378. menu.Items.Insert(3,ManageFavouritesMenu);
  379. }
  380. }
  381. }
  382. private AssignmentFavourite? GetFavourite(AssignmentModel? model)
  383. {
  384. return model == null ? null : _settings.Favourites.FirstOrDefault(x => string.Equals(x.Title, model.Subject));
  385. }
  386. private void SetAsFavourite(AssignmentModel? model)
  387. {
  388. if (model == null)
  389. {
  390. MessageBox.Show("Please select an Assignment first!");
  391. return;
  392. }
  393. var bCreated = false;
  394. var favourite = GetFavourite(model);
  395. if (favourite == null)
  396. {
  397. bCreated = true;
  398. favourite = new AssignmentFavourite { Title = model.Subject };
  399. _settings.Favourites.Add(favourite);
  400. }
  401. favourite.JobID = model.JobID;
  402. favourite.JobNumber = model.JobNumber;
  403. favourite.ITPID = model.ItpID;
  404. favourite.ITPCode = model.ItpCode;
  405. favourite.ActivityID = model.ActivityID;
  406. favourite.ActivityColor = model.Color;
  407. favourite.ActivityName = model.ActivityCode;
  408. new UserConfiguration<DailyActivityScreenSettings>().Save(_settings);
  409. MessageBox.Show(bCreated ? "Favourite Created!" : "Favourite Updated!");
  410. }
  411. private void ManageFavourites_Click(object sender, RoutedEventArgs e)
  412. {
  413. new DailyReportFavouriteWindow(_settings.Favourites).ShowDialog();
  414. new UserConfiguration<DailyActivityScreenSettings>().Save(_settings);
  415. }
  416. private void ViewEmailInterfaceForm_Click(object sender, RoutedEventArgs e)
  417. {
  418. var form = new EmailInterfaceForm { FromDate = Calendar.SelectedDate, ToDate = Calendar.SelectedDate };
  419. form.ShowDialog();
  420. //UpdateDayButtons();
  421. }
  422. private void ProcessWindowTrackerMenu_Click(object sender, RoutedEventArgs e)
  423. {
  424. var history = new WindowTrackerSummary(Employee.ID, Calendar.SelectedDate);
  425. history.ShowDialog();
  426. //UpdateDayButtons();
  427. }
  428. private void CreateAssignment_Click(object sender, RoutedEventArgs e)
  429. {
  430. var fav = (sender as MenuItem)?.Tag as Tuple<DateTime, AssignmentFavourite?>;
  431. var start = fav != null ? fav.Item1.TimeOfDay : Calendar.SelectedDate.TimeOfDay;
  432. CreateNewAssignment(start, fav?.Item2);
  433. }
  434. private void CreateNewAssignment(TimeSpan start, AssignmentFavourite? favourite)
  435. {
  436. CalendarDataEvent populate = (sender, args) => PopulateFavourite(args.Item as Assignment, favourite);
  437. Calendar.ItemCreated += populate;
  438. var ass = Calendar.CreateAssignment(new CalendarTimeSlot(Employee.ID, Calendar.SelectedDate.Add(start)));
  439. Calendar.ItemCreated -= populate;
  440. SelectAssignment(ass);
  441. }
  442. private void PopulateFavourite(Assignment? assignment, AssignmentFavourite? favourite)
  443. {
  444. if (assignment == null)
  445. return;
  446. assignment.Title = favourite != null ? favourite.Title : "";
  447. assignment.JobLink.ID = favourite != null ? favourite.JobID : Guid.Empty;
  448. assignment.ITP.ID = favourite != null ? favourite.ITPID : Guid.Empty;
  449. assignment.ActivityLink.ID = favourite != null ? favourite.ActivityID : Guid.Empty;
  450. assignment.ActivityLink.Color = favourite != null ? favourite.ActivityColor : "";
  451. new Client<Assignment>().Save(assignment, "Created by Daily Report");
  452. }
  453. private void RefreshAssignments()
  454. {
  455. Calendar.Refresh();
  456. }
  457. private void Assignments_OnSelectionChanged(object sender, ICalendarDataEventArgs args)
  458. {
  459. if (args is CalendarDataEventArgs<Assignment> ass)
  460. {
  461. CheckandSaveAssignment();
  462. SelectAssignment(ass.Item);
  463. }
  464. else
  465. SelectAssignment(null);
  466. }
  467. private void CheckandSaveAssignment()
  468. {
  469. if (SelectedAssignment != null && SelectedAssignment.IsChanged())
  470. {
  471. new Client<Assignment>().Save(SelectedAssignment, "", (o, e) => { });
  472. //SelectedAssignment.CommitChanges();
  473. }
  474. }
  475. private void SelectAssignment(Assignment? assignment)
  476. {
  477. Logger.Send(LogType.Information, ClientFactory.UserID, "Into Assignment_SelectionChanged()");
  478. bSelectingAssignment = true;
  479. try
  480. {
  481. SelectedAssignment = assignment;
  482. var bOK = assignment != null;
  483. //Logger.Send(LogType.Information, ClientFactory.UserID, "ASC (1/9): Setting Title");
  484. SetEditorValue(Title, bOK ? assignment.Title : "", bOK);
  485. //Logger.Send(LogType.Information, ClientFactory.UserID, "ASC (2/9): Setting Description");
  486. SetEditorValue(ActivityNotes, bOK ? assignment.Description : "", bOK);
  487. //Logger.Send(LogType.Information, ClientFactory.UserID, "ASC (3/9): Setting Start/Duration/Finish");
  488. SetEditorValue(Start, bOK ? assignment.Actual.Start : TimeSpan.MinValue, bOK);
  489. SetEditorValue(Duration, bOK ? assignment.Actual.Finish - assignment.Actual.Start : TimeSpan.MinValue, bOK);
  490. SetEditorValue(Finish, bOK ? assignment.Actual.Finish : TimeSpan.MinValue, bOK);
  491. var jobid = Job.Value;
  492. //Logger.Send(LogType.Information, ClientFactory.UserID, "ASC (4/9): Setting JobLink");
  493. SetEditorValue(Job, bOK ? assignment.JobLink.ID : Guid.Empty, bOK);
  494. if (bOK && !Equals(jobid, Job.Value))
  495. //Logger.Send(LogType.Information, ClientFactory.UserID, "ASC (5/9): Configuring ITP");
  496. ConfigureEditor(ITP);
  497. //Logger.Send(LogType.Information, ClientFactory.UserID, "ASC (6/9): Setting ITP");
  498. SetEditorValue(ITP, bOK ? assignment.ITP.ID : Guid.Empty, bOK);
  499. //if (bOK)
  500. //{
  501. // //Logger.Send(LogType.Information, ClientFactory.UserID, "ASC (7/9): Configuring Activity");
  502. // ConfigureEditor(Activity);
  503. //}
  504. //Logger.Send(LogType.Information, ClientFactory.UserID, "ASC (8/9): Setting Activity");
  505. //SetEditorValue(Activity, bOK ? assignment.ActivityLink.ID : Guid.Empty, bOK);
  506. Activity.Value = bOK ? assignment.ActivityLink.ID : Guid.Empty;
  507. Activity.IsEnabled = bOK;
  508. //if (bOK)
  509. //{
  510. // //Logger.Send(LogType.Information, ClientFactory.UserID, "ASC (9/9): Configuring Task");
  511. // ConfigureEditor(Kanban);
  512. //}
  513. //Logger.Send(LogType.Information, ClientFactory.UserID, "ASC (8/9): Setting Task");
  514. //SetEditorValue(Kanban, bOK ? assignment.Task.ID : Guid.Empty, bOK);
  515. Kanban.Value = bOK ? assignment.Task.ID : Guid.Empty;
  516. Kanban.IsEnabled = bOK;
  517. Job.IsEnabled = bOK ? !assignment.Task.IsValid() : false;
  518. if (assignment != null)
  519. {
  520. if (string.IsNullOrWhiteSpace(Title.Value))
  521. Title.SetFocus();
  522. else
  523. Notes.SetFocus();
  524. }
  525. }
  526. finally
  527. {
  528. bSelectingAssignment = false;
  529. }
  530. Logger.Send(LogType.Information, ClientFactory.UserID, "Out Of Assignment_SelectionChanged()");
  531. }
  532. private void ConfigureEditor(BaseDynamicEditorControl editor, BaseEditor? definition = null)
  533. {
  534. editor.Host = this;
  535. if (definition != null)
  536. editor.EditorDefinition = definition;
  537. editor.Configure();
  538. editor.Loaded = true;
  539. }
  540. private void SetEditorValue(BaseDynamicEditorControl editor, object value, bool enabled)
  541. {
  542. editor.Loaded = false;
  543. editor.SetValue(editor.ColumnName, value);
  544. editor.IsEnabled = enabled;
  545. editor.Loaded = true;
  546. }
  547. private void Assignments_OnItemChanged(object sender, ICalendarDataEventArgs args)
  548. {
  549. if (args is CalendarDataEventArgs<Assignment> ass)
  550. {
  551. if (ass.Item.ID == Guid.Empty)
  552. using (new WaitCursor())
  553. {
  554. ass.Item.Actual.Duration = new TimeSpan(0, 30, 0);
  555. new Client<Assignment>().Save(ass.Item, "Created from Daily Report Drag & Drop");
  556. }
  557. }
  558. }
  559. private void EditorValueChanged(IDynamicEditorControl sender, Dictionary<string, object> values)
  560. {
  561. if (SelectedAssignment == null || bSelectingAssignment)
  562. return;
  563. DumpAssignmentValues(SelectedAssignment);
  564. var before = SelectedAssignment.GetValues(true);
  565. foreach (var key in values.Keys)
  566. {
  567. CoreUtils.SetPropertyValue(SelectedAssignment, key, values[key]);
  568. if (key.Equals("Task.ID"))
  569. {
  570. Job.IsEnabled = values[key] == null || ((Guid)values[key]).Equals(Guid.Empty);
  571. if (values.ContainsKey("Job.ID"))
  572. SelectedAssignment.JobLink.ID = (Guid) values["Job.ID"];
  573. }
  574. if (key.Equals("JobLink.ID"))
  575. {
  576. ConfigureEditor(ITP);
  577. SelectedAssignment.ITP.ID = Guid.Empty;
  578. }
  579. }
  580. var after = SelectedAssignment.GetValues(true);
  581. var changes = before.Keys.Where(x =>
  582. !values.Keys.Contains(x) && ((before[x] == null && after[x] != null) || (before[x] != null && !before[x].Equals(after[x]))));
  583. foreach (var change in changes)
  584. if (change.Equals("Actual.Start"))
  585. SetEditorValue(Start, SelectedAssignment.Actual.Start, Start.IsEnabled);
  586. else if (change.Equals("Actual.Duration"))
  587. SetEditorValue(Duration, SelectedAssignment.Actual.Duration, Duration.IsEnabled);
  588. else if (change.Equals("Actual.Finish"))
  589. SetEditorValue(Finish, SelectedAssignment.Actual.Finish, Finish.IsEnabled);
  590. if (SelectedAssignment.Actual.Duration < new TimeSpan(0, 15, 0))
  591. {
  592. SelectedAssignment.Actual.Duration = new TimeSpan(0, 15, 0);
  593. SetEditorValue(Duration, SelectedAssignment.Actual.Duration, Duration.IsEnabled);
  594. SelectedAssignment.Actual.Finish = SelectedAssignment.Actual.Start.Add(SelectedAssignment.Actual.Duration);
  595. SetEditorValue(Finish, SelectedAssignment.Actual.Finish, Finish.IsEnabled);
  596. }
  597. if (SelectedAssignment.IsChanged())
  598. {
  599. new Client<Assignment>().Save(SelectedAssignment, "",
  600. (o, e) =>
  601. {
  602. if (e != null)
  603. Logger.Send(LogType.Error, "", String.Format("Error Updating Assignment: {0}\n{1}", e.Message, e.StackTrace));
  604. }
  605. );
  606. Calendar.UpdateAssignment(SelectedAssignment);
  607. }
  608. }
  609. private void DumpAssignmentValues(Assignment assignment)
  610. {
  611. Logger.Send(LogType.Information, "",
  612. string.Format("Updating Assignment: Start:{0} Duration={1} Finish={2}", assignment.Actual.Start, assignment.Actual.Duration, assignment.Actual.Finish));
  613. }
  614. private void TimeSheetEditorValueChanged(IDynamicEditorControl sender, Dictionary<string, object> values)
  615. {
  616. if (RequiredReportIndex < 0 || RequiredReportIndex >= RequiredReports.Count)
  617. return;
  618. var report = RequiredReports[RequiredReportIndex];
  619. report.Notes = sender.GetValue(sender.ColumnName) as string;
  620. var timesheet = new TimeSheet
  621. {
  622. ID = report.ID,
  623. Notes = report.Notes
  624. };
  625. new Client<TimeSheet>().Save(timesheet, "", (o, e) => { });
  626. }
  627. private void Activity_OnDefineLookups(ILookupEditorControl sender)
  628. {
  629. var colname = sender.ColumnName;
  630. var assignment = new Assignment();
  631. assignment.EmployeeLink.ID = Employee.ID;
  632. var values = sender.LookupEditorDefinition.Values(typeof(Assignment), colname, new[] { assignment });
  633. sender.LoadLookups(values);
  634. }
  635. private void Task_OnDefineLookups(ILookupEditorControl sender)
  636. {
  637. var colname = sender.ColumnName;
  638. var assignment = new Assignment();
  639. assignment.EmployeeLink.ID = Employee.ID;
  640. var values = sender.LookupEditorDefinition.Values(typeof(Assignment), colname, new[] { assignment });
  641. sender.LoadLookups(values);
  642. }
  643. private void ITP_OnDefineLookups(ILookupEditorControl sender)
  644. {
  645. var colname = sender.ColumnName;
  646. var values = sender.LookupEditorDefinition.Values(typeof(Assignment), colname, SelectedAssignment == null ? new Assignment[] { } : new[] { SelectedAssignment });
  647. sender.LoadLookups(values);
  648. }
  649. private void FirstDay_Click(object sender, RoutedEventArgs e)
  650. {
  651. RequiredReportIndex = 0;
  652. GotoCurrentRequiredReport();
  653. }
  654. private void SetCurrentDay(DateTime date)
  655. {
  656. bProgramaticallyChanging = true;
  657. DatePicker.SelectedDate = date;
  658. bProgramaticallyChanging = false;
  659. ConfigureBookingsList();
  660. }
  661. private void PrevDay_Click(object sender, RoutedEventArgs e)
  662. {
  663. var requiredreport = RequiredReports.OrderBy(x => x.Date).LastOrDefault(x => x.Date < DatePicker.SelectedDate);
  664. if (requiredreport != null)
  665. SetCurrentDay(requiredreport.Date);
  666. }
  667. private void NextDay_Click(object sender, RoutedEventArgs e)
  668. {
  669. var requiredreport = RequiredReports.OrderBy(x => x.Date).FirstOrDefault(x => x.Date > DatePicker.SelectedDate);
  670. if (requiredreport != null)
  671. SetCurrentDay(requiredreport.Date);
  672. }
  673. private void LastDay_Click(object sender, RoutedEventArgs e)
  674. {
  675. RequiredReportIndex = RequiredReports.Count - 1;
  676. GotoCurrentRequiredReport();
  677. }
  678. private void DatePicker_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
  679. {
  680. if (!bProgramaticallyChanging)
  681. ConfigureBookingsList();
  682. }
  683. private void ConfigureBookingsList()
  684. {
  685. DatePicker.HighlightedDates = RequiredReports.Select(x => new HighlightedDate(x.Date, "Report Required")).ToList();
  686. FirstDay.IsEnabled = RequiredReports.Count > 0 && DatePicker.SelectedDate > RequiredReports[0].Date; //RequiredReportIndex > 0;
  687. FirstDay.Content = new Image
  688. {
  689. Source = FirstDay.IsEnabled
  690. ? PRSDesktop.Resources.first.AsBitmapImage(32, 32)
  691. : PRSDesktop.Resources.first.Fade(0.2F).AsBitmapImage(32, 32)
  692. };
  693. PrevDay.IsEnabled = RequiredReports.Count > 0 && DatePicker.SelectedDate > RequiredReports[0].Date; //RequiredReportIndex > 0;
  694. PrevDay.Content = new Image
  695. {
  696. Source = PrevDay.IsEnabled
  697. ? PRSDesktop.Resources.back.AsBitmapImage(32, 32)
  698. : PRSDesktop.Resources.back.Fade(0.2F).AsBitmapImage(32, 32)
  699. };
  700. NextDay.IsEnabled =
  701. RequiredReports.Count > 0 &&
  702. DatePicker.SelectedDate < RequiredReports[RequiredReports.Count - 1].Date; //RequiredReportIndex < RequiredReports.Count - 1;
  703. NextDay.Content = new Image
  704. {
  705. Source = NextDay.IsEnabled
  706. ? PRSDesktop.Resources.next.AsBitmapImage(32, 32)
  707. : PRSDesktop.Resources.next.Fade(0.2F).AsBitmapImage(32, 32)
  708. };
  709. LastDay.IsEnabled =
  710. RequiredReports.Count > 0 &&
  711. DatePicker.SelectedDate < RequiredReports[RequiredReports.Count - 1].Date; //RequiredReportIndex < RequiredReports.Count - 1;
  712. LastDay.Content = new Image
  713. {
  714. Source = LastDay.IsEnabled
  715. ? PRSDesktop.Resources.last.AsBitmapImage(32, 32)
  716. : PRSDesktop.Resources.last.Fade(0.2F).AsBitmapImage(32, 32)
  717. };
  718. Calendar.DisableUpdate();
  719. Calendar.SelectedDate = DatePicker.SelectedDate.Value.Date; // RequiredReports[RequiredReportIndex].Item2.Date;
  720. //Assignments.Refresh();
  721. //Assignments.StartHour = 0;
  722. //Assignments.EndHour = 24;
  723. var start = TimeSpan.FromHours(6);
  724. var finish = TimeSpan.FromHours(18);
  725. if ((DatePicker.SelectedDate.Value == DateTime.Today) && (DateTime.Now.TimeOfDay > finish))
  726. finish = DateTime.Now.TimeOfDay;
  727. String notes = "";
  728. var blocks = Calendar.GetRoster(Employee.ID, DatePicker.SelectedDate.Value)?.GetBlocks(DatePicker.SelectedDate.Value, TimeSpan.FromSeconds(0), TimeSpan.FromDays(1));
  729. if (blocks?.Any() == true)
  730. {
  731. start = blocks.Aggregate(start, (time, block) => time.Ticks < block.Start.Ticks ? time : block.Start);
  732. finish = blocks.Aggregate(finish, (time, block) => time.Ticks > block.Finish.Ticks ? time : block.Start);
  733. }
  734. var requiredreport = RequiredReports.FirstOrDefault(x => x.Date.Equals(DatePicker.SelectedDate)); //[RequiredReportIndex];
  735. if (requiredreport != null)
  736. {
  737. start = start > requiredreport.Start ? requiredreport.Start : start;
  738. finish = finish < requiredreport.Finish ? requiredreport.Finish : finish;
  739. notes = requiredreport.Notes;
  740. }
  741. else
  742. {
  743. var row = new Client<TimeSheet>().Query(
  744. new Filter<TimeSheet>(x => x.Date).IsEqualTo(DatePicker.SelectedDate.Value).And(x => x.EmployeeLink.UserLink.ID).IsEqualTo(ClientFactory.UserGuid),
  745. new Columns<TimeSheet>(
  746. x => x.Start,
  747. x => x.Finish,
  748. x => x.Notes
  749. )
  750. ).Rows.FirstOrDefault();
  751. if (row != null)
  752. {
  753. notes = row.Get<TimeSheet, string>(x => x.Notes);
  754. var tstart = row.Get<TimeSheet, TimeSpan>(x => x.Start);
  755. start = start > tstart ? tstart : start;
  756. var tfinish = row.Get<TimeSheet, TimeSpan>(x => x.Finish);
  757. finish = finish < tfinish ? tfinish : finish;
  758. }
  759. }
  760. if (IsReady)
  761. {
  762. Calendar.EnableUpdate();
  763. Calendar.Refresh();
  764. Calendar.DisableUpdate();
  765. }
  766. Calendar.GetActiveWindow(Employee.ID, DatePicker.SelectedDate.Value, ref start, ref finish);
  767. Calendar.StartHour = start.Floor(TimeSpan.FromHours(1)).Hours;
  768. Calendar.EndHour = finish.Ceiling(TimeSpan.FromHours(1)).Hours;
  769. Calendar.EnableUpdate();
  770. Notes.Value = notes;
  771. SelectAssignment(null);
  772. EnableScreen(requiredreport != null);
  773. }
  774. private void EnableScreen(bool enabled)
  775. {
  776. Title.IsEnabled = enabled && (SelectedAssignment != null);
  777. ActivityNotes.IsEnabled = enabled && (SelectedAssignment != null);
  778. Start.IsEnabled = enabled && (SelectedAssignment != null);
  779. Duration.IsEnabled = enabled && (SelectedAssignment != null);
  780. Finish.IsEnabled = enabled && (SelectedAssignment != null);
  781. Kanban.IsEnabled = enabled && (SelectedAssignment != null);
  782. ITP.IsEnabled = enabled && (SelectedAssignment != null);
  783. Job.IsEnabled = enabled && (SelectedAssignment != null);
  784. Activity.IsEnabled = enabled && (SelectedAssignment != null);
  785. Notes.IsEnabled = enabled;
  786. ProcessWindowTrackers.IsEnabled = enabled;
  787. ImportEmails.IsEnabled = enabled;
  788. ConfirmTimesheet.IsEnabled = enabled;
  789. Calendar.IsEnabled = enabled;
  790. }
  791. private void Splitpanel_OnChanged(object sender, DynamicSplitPanelSettings e)
  792. {
  793. _settings.ActivityColumnWidth = e.AnchorWidth;
  794. new UserConfiguration<DailyActivityScreenSettings>().Save(_settings);
  795. }
  796. private void ConfirmTimesheet_Click(object sender, RoutedEventArgs e)
  797. {
  798. var bBlankActivities = false;
  799. var bOverlapping = true;
  800. var rows = Calendar.GetAssignments(Employee.ID, DatePicker.SelectedDate.Value);
  801. foreach (var row in rows)
  802. {
  803. var id = row.Get<Assignment, Guid>(c => c.ID);
  804. var date = row.Get<Assignment, DateTime>(c => c.Date);
  805. var start = row.Get<Assignment, TimeSpan>(c => c.Actual.Start);
  806. var finish = row.Get<Assignment, TimeSpan>(c => c.Actual.Finish);
  807. if (rows.Any(r =>
  808. r.Get<Assignment, Guid>(c => c.ID) != id
  809. && r.Get<Assignment, DateTime>(c => c.Date) == date
  810. && r.Get<Assignment, TimeSpan>(c => c.Actual.Finish) > start
  811. && r.Get<Assignment, TimeSpan>(c => c.Actual.Start) < finish
  812. ))
  813. bOverlapping = false;
  814. if (Security.IsAllowed<RequireActivityCodesOnDailyReports>())
  815. bBlankActivities = rows.Any(r => !Entity.IsEntityLinkValid<Assignment, AssignmentActivityLink>(x => x.ActivityLink, r));
  816. }
  817. if (!bOverlapping)
  818. {
  819. MessageBox.Show("This report contains overlapping blocks!\n\nPlease correct before confirming this timesheet.");
  820. return;
  821. }
  822. if (bBlankActivities)
  823. {
  824. MessageBox.Show("All Daily Report entries must have a valid Activity Code!\n\nPlease correct before confirming this timesheet.");
  825. return;
  826. }
  827. if (MessageBox.Show(
  828. "Confirming your timesheet will prevent you from making any further changes or additions.\n\nAre you sure you want to do this?",
  829. "Confirm TimeSheet", MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes)
  830. return;
  831. using (new WaitCursor())
  832. {
  833. var timesheets = new Client<TimeSheet>().Query(
  834. new Filter<TimeSheet>(x => x.EmployeeLink.ID).IsEqualTo(Employee.ID).And(x => x.Date).IsEqualTo(Calendar.SelectedDate),
  835. new Columns<TimeSheet>(x => x.ID, x => x.Confirmed)
  836. ).Rows.Select(r => r.ToObject<TimeSheet>()).ToArray();
  837. for (var i = 0; i < timesheets.Length; i++) timesheets[i].Confirmed = DateTime.Now;
  838. new Client<TimeSheet>().Save(timesheets, "Confirmed by Daily Activity Report");
  839. RequiredReports.RemoveAll(x => x.Date.Equals(Calendar.SelectedDate));
  840. if (!RequiredReports.Any())
  841. {
  842. var start = TimeSpan.FromSeconds(0);
  843. var finish = TimeSpan.FromDays(1);
  844. var blocks = Calendar.GetRoster(Employee.ID, DatePicker.SelectedDate.Value)?.GetBlocks(DatePicker.SelectedDate.Value, start, finish);
  845. if (blocks?.Any() == true)
  846. {
  847. start = blocks.Aggregate(start, (time, block) => time.Ticks < block.Start.Ticks ? time : block.Start);
  848. finish = blocks.Aggregate(finish, (time, block) => time.Ticks > block.Finish.Ticks ? time : block.Start);
  849. }
  850. RequiredReports.Add(new RequiredReport(Guid.Empty, DateTime.Today, start, finish, ""));
  851. ConfirmDock.Visibility = Visibility.Collapsed;
  852. }
  853. GotoCurrentRequiredReport();
  854. OnTimeSheetConfirmed?.Invoke(new TimeSheetConfirmedArgs { Date = Calendar.SelectedDate });
  855. }
  856. }
  857. private void GotoCurrentRequiredReport()
  858. {
  859. if (RequiredReportIndex >= RequiredReports.Count)
  860. RequiredReportIndex = RequiredReports.Count - 1;
  861. SetCurrentDay(RequiredReports[RequiredReportIndex].Date);
  862. }
  863. private void LoadKanbans(KanbanStatus? category = null)
  864. {
  865. if (category.HasValue)
  866. _taskcategory = category.Value;
  867. Tasks.ItemsSource = null;
  868. var filter = new Filter<KanbanSubscriber>(x => x.Kanban.Closed).IsEqualTo(DateTime.MinValue)
  869. .And(x => x.Kanban.Status).IsEqualTo(_taskcategory);
  870. if (ShowPublicTasks.IsChecked != true)
  871. filter = filter.And(x => x.Kanban.Private).IsEqualTo(true);
  872. filter = filter.And(x => x.Employee.UserLink.ID).IsEqualTo(ClientFactory.UserGuid);
  873. filter = filter.And(x => x.Assignee).IsEqualTo(true);
  874. new Client<KanbanSubscriber>().Query(
  875. filter,
  876. new Columns<KanbanSubscriber>
  877. (
  878. x => x.Kanban.ID,
  879. x => x.Kanban.DueDate,
  880. x => x.Kanban.Completed,
  881. x => x.Kanban.Description,
  882. x => x.Kanban.Summary,
  883. x => x.Kanban.Status,
  884. x => x.Kanban.EmployeeLink.ID,
  885. x => x.Kanban.EmployeeLink.UserLink.ID,
  886. x => x.Kanban.EmployeeLink.Name,
  887. x => x.Kanban.ManagerLink.ID,
  888. x => x.Kanban.ManagerLink.UserLink.ID,
  889. x => x.Kanban.ManagerLink.Name,
  890. x => x.Kanban.Notes,
  891. x => x.Kanban.Title,
  892. x => x.Kanban.JobLink.ID,
  893. x => x.Kanban.JobLink.JobNumber,
  894. x => x.Kanban.JobLink.Name,
  895. x => x.Kanban.Type.Code,
  896. x => x.Kanban.Number
  897. ),
  898. new SortOrder<KanbanSubscriber>(x => x.Kanban.DueDate),
  899. (kanbans, error) =>
  900. {
  901. Dispatcher.Invoke(() =>
  902. {
  903. foreach (var column in kanbans.Columns)
  904. column.ColumnName = column.ColumnName.Replace("Kanban.", "");
  905. Tasks.ItemsSource = kanbans.Rows.Select(x => x.ToObject<Kanban>());
  906. });
  907. }
  908. );
  909. }
  910. private void OpenTasks_Click(object sender, RoutedEventArgs e)
  911. {
  912. LoadKanbans(KanbanStatus.Open);
  913. CurrentTasks.SetValue(Grid.RowProperty, 6);
  914. WaitingTasks.SetValue(Grid.RowProperty, 7);
  915. ClosedTasks.SetValue(Grid.RowProperty, 8);
  916. }
  917. private void CurrentTasks_Click(object sender, RoutedEventArgs e)
  918. {
  919. LoadKanbans(KanbanStatus.InProgress);
  920. CurrentTasks.SetValue(Grid.RowProperty, 2);
  921. WaitingTasks.SetValue(Grid.RowProperty, 7);
  922. ClosedTasks.SetValue(Grid.RowProperty, 8);
  923. }
  924. private void WaitingTasks_Click(object sender, RoutedEventArgs e)
  925. {
  926. LoadKanbans(KanbanStatus.Waiting);
  927. CurrentTasks.SetValue(Grid.RowProperty, 2);
  928. WaitingTasks.SetValue(Grid.RowProperty, 3);
  929. ClosedTasks.SetValue(Grid.RowProperty, 8);
  930. }
  931. private void ClosedTasks_Click(object sender, RoutedEventArgs e)
  932. {
  933. LoadKanbans(KanbanStatus.Complete);
  934. CurrentTasks.SetValue(Grid.RowProperty, 2);
  935. WaitingTasks.SetValue(Grid.RowProperty, 3);
  936. ClosedTasks.SetValue(Grid.RowProperty, 4);
  937. }
  938. private void Tasks_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  939. {
  940. var startPoint = e.GetPosition(null);
  941. }
  942. // Helper to search up the VisualTree
  943. private static T FindAncestor<T>(DependencyObject current)
  944. where T : DependencyObject
  945. {
  946. try
  947. {
  948. do
  949. {
  950. if (current is T) return (T)current;
  951. current = VisualTreeHelper.GetParent(current);
  952. } while (current != null);
  953. }
  954. catch (Exception e)
  955. {
  956. Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
  957. }
  958. return null;
  959. }
  960. private void Tasks_MouseMove(object sender, MouseEventArgs e)
  961. {
  962. // Get the current mouse position
  963. var mousePos = e.GetPosition(null);
  964. var diff = startPoint - mousePos;
  965. if (e.LeftButton == MouseButtonState.Pressed &&
  966. (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
  967. Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
  968. {
  969. // Get the dragged ListViewItem
  970. var listView = sender as ListView;
  971. var depobj = (DependencyObject)e.OriginalSource;
  972. var kanban = listView.SelectedItem as Kanban;
  973. if (kanban != null)
  974. {
  975. var dragData = new DataObject("Comal.Classes.Kanban", kanban);
  976. DragDrop.DoDragDrop(depobj, dragData, DragDropEffects.Move);
  977. }
  978. }
  979. }
  980. private void NewTask_Click(object sender, RoutedEventArgs e)
  981. {
  982. var task = new Kanban();
  983. task.EmployeeLink.ID = Employee.ID;
  984. task.ManagerLink.ID = Employee.ID;
  985. task.Private = true;
  986. task.Status = KanbanStatus.Open;
  987. if(DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(Kanban)).EditItems(new[] { task }))
  988. {
  989. using (new WaitCursor())
  990. {
  991. /*var task = new Kanban();
  992. task.Title = form.Title;
  993. task.Description = form.Description;
  994. task.DueDate = DateTime.Today;
  995. task.EmployeeLink.ID = Employee.ID;
  996. task.ManagerLink.ID = Employee.ID;
  997. task.Category = "Open";
  998. task.Private = true;*/
  999. new Client<Kanban>().Save(task, "Created from Daily Report screen");
  1000. /*var subscriber = new KanbanSubscriber();
  1001. subscriber.Kanban.ID = task.ID;
  1002. subscriber.Employee.ID = Employee.ID;
  1003. subscriber.Assignee = true;
  1004. subscriber.Manager = true;
  1005. new Client<KanbanSubscriber>().Save(subscriber, "");*/
  1006. LoadKanbans();
  1007. }
  1008. }
  1009. //var form = new QuickTask();
  1010. //if (form.ShowDialog() == true)
  1011. }
  1012. private void ShowPublicTasks_Checked(object sender, RoutedEventArgs e)
  1013. {
  1014. LoadKanbans();
  1015. }
  1016. private void Tasks_MouseDoubleClick(object sender, MouseButtonEventArgs e)
  1017. {
  1018. var listview = sender as ListView;
  1019. if (listview == null)
  1020. return;
  1021. var kanban = listview.SelectedItem as Kanban;
  1022. if (kanban == null)
  1023. return;
  1024. if (kg == null)
  1025. kg = new TaskGrid();
  1026. var bEdited = kg.EditItems(new[] { kanban });
  1027. if (bEdited)
  1028. LoadKanbans();
  1029. }
  1030. private void TaskMenu_ContextMenuOpening(object sender, ContextMenuEventArgs e)
  1031. {
  1032. var kanban = (sender as Border).Tag as Kanban;
  1033. var menu = (sender as Border).ContextMenu;
  1034. menu.Items.Clear();
  1035. if (_taskcategory != KanbanStatus.Open)
  1036. MoveToOpen = CreateTaskMenu(menu, "Move To [Open Tasks]", kanban, MoveTask_Click);
  1037. if (_taskcategory != KanbanStatus.InProgress)
  1038. MoveToCurrent = CreateTaskMenu(menu, "Move To [Tasks In Progress]", kanban, MoveTask_Click);
  1039. else
  1040. menu.Items.Add(new Separator());
  1041. if (_taskcategory != KanbanStatus.Waiting)
  1042. MoveToWaiting = CreateTaskMenu(menu, "Move To [Waiting For Others]", kanban, MoveTask_Click);
  1043. else
  1044. menu.Items.Add(new Separator());
  1045. if (_taskcategory != KanbanStatus.Complete)
  1046. MoveToComplete = CreateTaskMenu(menu, "Move To [Completed Tasks]", kanban, MoveTask_Click);
  1047. menu.Items.Add(new Separator());
  1048. CreateTaskMenu(menu, "Change Due Date", kanban, ChangeKanbanDueDate_Click);
  1049. }
  1050. private MenuItem CreateTaskMenu(ContextMenu menu, string header, Kanban kanban, RoutedEventHandler action)
  1051. {
  1052. var item = new MenuItem();
  1053. item.Header = header;
  1054. item.Tag = kanban;
  1055. item.Click += action;
  1056. menu.Items.Add(item);
  1057. return item;
  1058. }
  1059. private void ChangeKanbanDueDate_Click(object sender, RoutedEventArgs e)
  1060. {
  1061. var kanban = (sender as MenuItem)?.Tag as Kanban;
  1062. var date = kanban.DueDate;
  1063. if (DateEdit.Execute("Change Due Date", ref date))
  1064. {
  1065. kanban.DueDate = date;
  1066. new Client<Kanban>().Save(kanban, "");
  1067. LoadKanbans();
  1068. }
  1069. }
  1070. private void MoveTask_Click(object sender, RoutedEventArgs e)
  1071. {
  1072. var kanban = (sender as MenuItem)?.Tag as Kanban;
  1073. if (kanban == null)
  1074. return;
  1075. var category = sender == MoveToComplete
  1076. ? KanbanStatus.Complete
  1077. : sender == MoveToWaiting
  1078. ? KanbanStatus.Waiting
  1079. : sender == MoveToCurrent
  1080. ? KanbanStatus.InProgress
  1081. : KanbanStatus.Open;
  1082. kanban.Status = category;
  1083. new Client<Kanban>().Save(kanban, "");
  1084. LoadKanbans();
  1085. }
  1086. private void Assignments_OnItemEditing(object sender, ICalendarHandledEventArgs args)
  1087. {
  1088. args.Status = CalendarHandledStatus.Handled;
  1089. }
  1090. }
  1091. }