DailyReport.xaml.cs 51 KB

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