DailyReport.xaml.cs 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274
  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 KanbanGrid 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() { ImmediateUpdates = false });
  230. ConfigureEditor(ActivityNotes, new MemoEditor() { ImmediateUpdates = false});
  231. ConfigureEditor(Start, new TimeOfDayEditor());
  232. ConfigureEditor(Duration, new TimeOfDayEditor());
  233. ConfigureEditor(Finish, new TimeOfDayEditor());
  234. ConfigureEditor(Notes, new MemoEditor() { ImmediateUpdates = false });
  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. Notes = report.Notes
  598. }.SetID(report.ID);
  599. new Client<TimeSheet>().Save(timesheet, "", (o, e) => { });
  600. }
  601. private void Activity_OnDefineLookups(ILookupEditorControl sender)
  602. {
  603. var colname = sender.ColumnName;
  604. var assignment = new Assignment();
  605. assignment.EmployeeLink.ID = Employee.ID;
  606. var values = sender.LookupEditorDefinition.Values(colname, new[] { assignment });
  607. sender.LoadLookups(values);
  608. }
  609. private void Task_OnDefineLookups(ILookupEditorControl sender)
  610. {
  611. var colname = sender.ColumnName;
  612. var assignment = new Assignment();
  613. assignment.EmployeeLink.ID = Employee.ID;
  614. var values = sender.LookupEditorDefinition.Values(colname, new[] { assignment });
  615. sender.LoadLookups(values);
  616. }
  617. private void ITP_OnDefineLookups(ILookupEditorControl sender)
  618. {
  619. var colname = sender.ColumnName;
  620. var values = sender.LookupEditorDefinition.Values(colname, SelectedAssignment == null ? new Assignment[] { } : new[] { SelectedAssignment });
  621. sender.LoadLookups(values);
  622. }
  623. private void FirstDay_Click(object sender, RoutedEventArgs e)
  624. {
  625. RequiredReportIndex = 0;
  626. GotoCurrentRequiredReport();
  627. }
  628. private void SetCurrentDay(DateTime date)
  629. {
  630. bProgramaticallyChanging = true;
  631. DatePicker.SelectedDate = date;
  632. bProgramaticallyChanging = false;
  633. ConfigureBookingsList();
  634. }
  635. private void PrevDay_Click(object sender, RoutedEventArgs e)
  636. {
  637. var requiredreport = RequiredReports.OrderBy(x => x.Date).LastOrDefault(x => x.Date < DatePicker.SelectedDate);
  638. if (requiredreport != null)
  639. SetCurrentDay(requiredreport.Date);
  640. }
  641. private void NextDay_Click(object sender, RoutedEventArgs e)
  642. {
  643. var requiredreport = RequiredReports.OrderBy(x => x.Date).FirstOrDefault(x => x.Date > DatePicker.SelectedDate);
  644. if (requiredreport != null)
  645. SetCurrentDay(requiredreport.Date);
  646. }
  647. private void LastDay_Click(object sender, RoutedEventArgs e)
  648. {
  649. RequiredReportIndex = RequiredReports.Count - 1;
  650. GotoCurrentRequiredReport();
  651. }
  652. private void DatePicker_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
  653. {
  654. if (!bProgramaticallyChanging)
  655. ConfigureBookingsList();
  656. }
  657. private void ConfigureBookingsList()
  658. {
  659. DatePicker.HighlightedDates = RequiredReports.Select(x => new HighlightedDate(x.Date, "Report Required")).ToList();
  660. FirstDay.IsEnabled = RequiredReports.Count > 0 && DatePicker.SelectedDate > RequiredReports[0].Date; //RequiredReportIndex > 0;
  661. FirstDay.Content = new Image
  662. {
  663. Source = FirstDay.IsEnabled
  664. ? PRSDesktop.Resources.first.AsBitmapImage(32, 32)
  665. : PRSDesktop.Resources.first.Fade(0.2F).AsBitmapImage(32, 32)
  666. };
  667. PrevDay.IsEnabled = RequiredReports.Count > 0 && DatePicker.SelectedDate > RequiredReports[0].Date; //RequiredReportIndex > 0;
  668. PrevDay.Content = new Image
  669. {
  670. Source = PrevDay.IsEnabled
  671. ? PRSDesktop.Resources.back.AsBitmapImage(32, 32)
  672. : PRSDesktop.Resources.back.Fade(0.2F).AsBitmapImage(32, 32)
  673. };
  674. NextDay.IsEnabled =
  675. RequiredReports.Count > 0 &&
  676. DatePicker.SelectedDate < RequiredReports[RequiredReports.Count - 1].Date; //RequiredReportIndex < RequiredReports.Count - 1;
  677. NextDay.Content = new Image
  678. {
  679. Source = NextDay.IsEnabled
  680. ? PRSDesktop.Resources.next.AsBitmapImage(32, 32)
  681. : PRSDesktop.Resources.next.Fade(0.2F).AsBitmapImage(32, 32)
  682. };
  683. LastDay.IsEnabled =
  684. RequiredReports.Count > 0 &&
  685. DatePicker.SelectedDate < RequiredReports[RequiredReports.Count - 1].Date; //RequiredReportIndex < RequiredReports.Count - 1;
  686. LastDay.Content = new Image
  687. {
  688. Source = LastDay.IsEnabled
  689. ? PRSDesktop.Resources.last.AsBitmapImage(32, 32)
  690. : PRSDesktop.Resources.last.Fade(0.2F).AsBitmapImage(32, 32)
  691. };
  692. Calendar.DisableUpdate();
  693. Calendar.SelectedDate = DatePicker.SelectedDate.Value.Date; // RequiredReports[RequiredReportIndex].Item2.Date;
  694. //Assignments.Refresh();
  695. //Assignments.StartHour = 0;
  696. //Assignments.EndHour = 24;
  697. var start = TimeSpan.FromHours(6);
  698. var finish = TimeSpan.FromHours(18);
  699. if ((DatePicker.SelectedDate.Value == DateTime.Today) && (DateTime.Now.TimeOfDay > finish))
  700. finish = DateTime.Now.TimeOfDay;
  701. String notes = "";
  702. var blocks = Calendar.GetRoster(Employee.ID, DatePicker.SelectedDate.Value)?.GetBlocks(DatePicker.SelectedDate.Value, TimeSpan.FromSeconds(0), TimeSpan.FromDays(1));
  703. if (blocks?.Any() == true)
  704. {
  705. start = blocks.Aggregate(start, (time, block) => time.Ticks < block.Start.Ticks ? time : block.Start);
  706. finish = blocks.Aggregate(finish, (time, block) => time.Ticks > block.Finish.Ticks ? time : block.Start);
  707. }
  708. var requiredreport = RequiredReports.FirstOrDefault(x => x.Date.Equals(DatePicker.SelectedDate)); //[RequiredReportIndex];
  709. if (requiredreport != null)
  710. {
  711. start = start > requiredreport.Start ? requiredreport.Start : start;
  712. finish = finish < requiredreport.Finish ? requiredreport.Finish : finish;
  713. notes = requiredreport.Notes;
  714. }
  715. else
  716. {
  717. var row = new Client<TimeSheet>().Query(
  718. new Filter<TimeSheet>(x => x.Date).IsEqualTo(DatePicker.SelectedDate.Value).And(x => x.EmployeeLink.UserLink.ID).IsEqualTo(ClientFactory.UserGuid),
  719. InABox.Core.Columns.None<TimeSheet>().Add(
  720. x => x.Start,
  721. x => x.Finish,
  722. x => x.Notes
  723. )
  724. ).Rows.FirstOrDefault();
  725. if (row != null)
  726. {
  727. notes = row.Get<TimeSheet, string>(x => x.Notes);
  728. var tstart = row.Get<TimeSheet, TimeSpan>(x => x.Start);
  729. start = start > tstart ? tstart : start;
  730. var tfinish = row.Get<TimeSheet, TimeSpan>(x => x.Finish);
  731. finish = finish < tfinish ? tfinish : finish;
  732. }
  733. }
  734. if (IsReady)
  735. {
  736. Calendar.EnableUpdate();
  737. Calendar.Refresh();
  738. Calendar.DisableUpdate();
  739. }
  740. Calendar.GetActiveWindow(Employee.ID, DatePicker.SelectedDate.Value, ref start, ref finish);
  741. Calendar.StartHour = start.Floor(TimeSpan.FromHours(1)).Hours;
  742. Calendar.EndHour = finish.Ceiling(TimeSpan.FromHours(1)).Hours;
  743. Calendar.EnableUpdate();
  744. Notes.Value = notes;
  745. SelectAssignment(null);
  746. EnableScreen(requiredreport != null);
  747. }
  748. private void EnableScreen(bool enabled)
  749. {
  750. Title.IsEnabled = enabled && (SelectedAssignment != null);
  751. ActivityNotes.IsEnabled = enabled && (SelectedAssignment != null);
  752. Start.IsEnabled = enabled && (SelectedAssignment != null);
  753. Duration.IsEnabled = enabled && (SelectedAssignment != null);
  754. Finish.IsEnabled = enabled && (SelectedAssignment != null);
  755. Kanban.IsEnabled = enabled && (SelectedAssignment != null);
  756. ITP.IsEnabled = enabled && (SelectedAssignment != null);
  757. Job.IsEnabled = enabled && (SelectedAssignment != null);
  758. Activity.IsEnabled = enabled && (SelectedAssignment != null);
  759. Notes.IsEnabled = enabled;
  760. ProcessWindowTrackers.IsEnabled = enabled;
  761. ImportEmails.IsEnabled = enabled;
  762. ConfirmTimesheet.IsEnabled = enabled;
  763. Calendar.IsEnabled = enabled;
  764. }
  765. private void Splitpanel_OnChanged(object sender, DynamicSplitPanelSettings e)
  766. {
  767. _settings.ActivityColumnWidth = e.AnchorWidth;
  768. new UserConfiguration<DailyActivityScreenSettings>().Save(_settings);
  769. }
  770. private void ConfirmTimesheet_Click(object sender, RoutedEventArgs e)
  771. {
  772. var bBlankActivities = false;
  773. var bOverlapping = true;
  774. var rows = Calendar.GetAssignments(Employee.ID, DatePicker.SelectedDate.Value);
  775. foreach (var row in rows)
  776. {
  777. var id = row.Get<Assignment, Guid>(c => c.ID);
  778. var date = row.Get<Assignment, DateTime>(c => c.Date);
  779. var start = row.Get<Assignment, TimeSpan>(c => c.Actual.Start);
  780. var finish = row.Get<Assignment, TimeSpan>(c => c.Actual.Finish);
  781. if (rows.Any(r =>
  782. r.Get<Assignment, Guid>(c => c.ID) != id
  783. && r.Get<Assignment, DateTime>(c => c.Date) == date
  784. && r.Get<Assignment, TimeSpan>(c => c.Actual.Finish) > start
  785. && r.Get<Assignment, TimeSpan>(c => c.Actual.Start) < finish
  786. ))
  787. bOverlapping = false;
  788. if (Security.IsAllowed<RequireActivityCodesOnDailyReports>())
  789. bBlankActivities = rows.Any(r => !Entity.IsEntityLinkValid<Assignment, AssignmentActivityLink>(x => x.ActivityLink, r));
  790. }
  791. if (!bOverlapping)
  792. {
  793. MessageBox.Show("This report contains overlapping blocks!\n\nPlease correct before confirming this timesheet.");
  794. return;
  795. }
  796. if (bBlankActivities)
  797. {
  798. MessageBox.Show("All Daily Report entries must have a valid Activity Code!\n\nPlease correct before confirming this timesheet.");
  799. return;
  800. }
  801. if (MessageBox.Show(
  802. "Confirming your timesheet will prevent you from making any further changes or additions.\n\nAre you sure you want to do this?",
  803. "Confirm TimeSheet", MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes)
  804. return;
  805. using (new WaitCursor())
  806. {
  807. var timesheets = new Client<TimeSheet>().Query(
  808. new Filter<TimeSheet>(x => x.EmployeeLink.ID).IsEqualTo(Employee.ID).And(x => x.Date).IsEqualTo(Calendar.SelectedDate),
  809. InABox.Core.Columns.None<TimeSheet>().Add(x => x.ID, x => x.Confirmed)
  810. ).Rows.Select(r => r.ToObject<TimeSheet>()).ToArray();
  811. for (var i = 0; i < timesheets.Length; i++) timesheets[i].Confirmed = DateTime.Now;
  812. new Client<TimeSheet>().Save(timesheets, "Confirmed by Daily Activity Report");
  813. RequiredReports.RemoveAll(x => x.Date.Equals(Calendar.SelectedDate));
  814. if (!RequiredReports.Any())
  815. {
  816. var start = TimeSpan.FromSeconds(0);
  817. var finish = TimeSpan.FromDays(1);
  818. var blocks = Calendar.GetRoster(Employee.ID, DatePicker.SelectedDate.Value)?.GetBlocks(DatePicker.SelectedDate.Value, start, finish);
  819. if (blocks?.Any() == true)
  820. {
  821. start = blocks.Aggregate(start, (time, block) => time.Ticks < block.Start.Ticks ? time : block.Start);
  822. finish = blocks.Aggregate(finish, (time, block) => time.Ticks > block.Finish.Ticks ? time : block.Start);
  823. }
  824. RequiredReports.Add(new RequiredReport(Guid.Empty, DateTime.Today, start, finish, ""));
  825. ConfirmDock.Visibility = Visibility.Collapsed;
  826. }
  827. GotoCurrentRequiredReport();
  828. OnTimeSheetConfirmed?.Invoke(new TimeSheetConfirmedArgs { Date = Calendar.SelectedDate });
  829. }
  830. }
  831. private void GotoCurrentRequiredReport()
  832. {
  833. if (RequiredReportIndex >= RequiredReports.Count)
  834. RequiredReportIndex = RequiredReports.Count - 1;
  835. SetCurrentDay(RequiredReports[RequiredReportIndex].Date);
  836. }
  837. private void LoadKanbans(KanbanStatus? category = null)
  838. {
  839. if (category.HasValue)
  840. _taskcategory = category.Value;
  841. Tasks.ItemsSource = null;
  842. var filter = new Filter<KanbanSubscriber>(x => x.Kanban.Closed).IsEqualTo(DateTime.MinValue)
  843. .And(x => x.Kanban.Status).IsEqualTo(_taskcategory);
  844. if (ShowPublicTasks.IsChecked != true)
  845. filter = filter.And(x => x.Kanban.Private).IsEqualTo(true);
  846. filter = filter.And(x => x.Employee.UserLink.ID).IsEqualTo(ClientFactory.UserGuid);
  847. filter = filter.And(x => x.Assignee).IsEqualTo(true);
  848. new Client<KanbanSubscriber>().Query(
  849. filter,
  850. InABox.Core.Columns.None<KanbanSubscriber>().Add(
  851. x => x.Kanban.ID,
  852. x => x.Kanban.DueDate,
  853. x => x.Kanban.Completed,
  854. x => x.Kanban.Description,
  855. x => x.Kanban.Summary,
  856. x => x.Kanban.Status,
  857. x => x.Kanban.EmployeeLink.ID,
  858. x => x.Kanban.EmployeeLink.UserLink.ID,
  859. x => x.Kanban.EmployeeLink.Name,
  860. x => x.Kanban.ManagerLink.ID,
  861. x => x.Kanban.ManagerLink.UserLink.ID,
  862. x => x.Kanban.ManagerLink.Name,
  863. x => x.Kanban.Notes,
  864. x => x.Kanban.Title,
  865. x => x.Kanban.JobLink.ID,
  866. x => x.Kanban.JobLink.JobNumber,
  867. x => x.Kanban.JobLink.Name,
  868. x => x.Kanban.Type.Code,
  869. x => x.Kanban.Number
  870. ),
  871. new SortOrder<KanbanSubscriber>(x => x.Kanban.DueDate),
  872. CoreRange.All,
  873. (kanbans, error) =>
  874. {
  875. Dispatcher.Invoke(() =>
  876. {
  877. foreach (var column in kanbans.Columns)
  878. column.ColumnName = column.ColumnName.Replace("Kanban.", "");
  879. Tasks.ItemsSource = kanbans.Rows.Select(x => x.ToObject<Kanban>());
  880. });
  881. }
  882. );
  883. }
  884. private void OpenTasks_Click(object sender, RoutedEventArgs e)
  885. {
  886. LoadKanbans(KanbanStatus.Open);
  887. CurrentTasks.SetValue(Grid.RowProperty, 6);
  888. WaitingTasks.SetValue(Grid.RowProperty, 7);
  889. ClosedTasks.SetValue(Grid.RowProperty, 8);
  890. }
  891. private void CurrentTasks_Click(object sender, RoutedEventArgs e)
  892. {
  893. LoadKanbans(KanbanStatus.InProgress);
  894. CurrentTasks.SetValue(Grid.RowProperty, 2);
  895. WaitingTasks.SetValue(Grid.RowProperty, 7);
  896. ClosedTasks.SetValue(Grid.RowProperty, 8);
  897. }
  898. private void WaitingTasks_Click(object sender, RoutedEventArgs e)
  899. {
  900. LoadKanbans(KanbanStatus.Waiting);
  901. CurrentTasks.SetValue(Grid.RowProperty, 2);
  902. WaitingTasks.SetValue(Grid.RowProperty, 3);
  903. ClosedTasks.SetValue(Grid.RowProperty, 8);
  904. }
  905. private void ClosedTasks_Click(object sender, RoutedEventArgs e)
  906. {
  907. LoadKanbans(KanbanStatus.Complete);
  908. CurrentTasks.SetValue(Grid.RowProperty, 2);
  909. WaitingTasks.SetValue(Grid.RowProperty, 3);
  910. ClosedTasks.SetValue(Grid.RowProperty, 4);
  911. }
  912. private void Tasks_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  913. {
  914. var startPoint = e.GetPosition(null);
  915. }
  916. // Helper to search up the VisualTree
  917. private static T FindAncestor<T>(DependencyObject current)
  918. where T : DependencyObject
  919. {
  920. try
  921. {
  922. do
  923. {
  924. if (current is T) return (T)current;
  925. current = VisualTreeHelper.GetParent(current);
  926. } while (current != null);
  927. }
  928. catch (Exception e)
  929. {
  930. Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
  931. }
  932. return null;
  933. }
  934. private void Tasks_MouseMove(object sender, MouseEventArgs e)
  935. {
  936. // Get the current mouse position
  937. var mousePos = e.GetPosition(null);
  938. var diff = startPoint - mousePos;
  939. if (e.LeftButton == MouseButtonState.Pressed &&
  940. (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
  941. Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
  942. {
  943. // Get the dragged ListViewItem
  944. var listView = sender as ListView;
  945. var depobj = (DependencyObject)e.OriginalSource;
  946. var kanban = listView.SelectedItem as Kanban;
  947. if (kanban != null)
  948. {
  949. var dragData = new DataObject("Comal.Classes.Kanban", kanban);
  950. DragDrop.DoDragDrop(depobj, dragData, DragDropEffects.Move);
  951. }
  952. }
  953. }
  954. private void NewTask_Click(object sender, RoutedEventArgs e)
  955. {
  956. var task = new Kanban();
  957. task.EmployeeLink.ID = Employee.ID;
  958. task.ManagerLink.ID = Employee.ID;
  959. task.Private = true;
  960. task.Status = KanbanStatus.Open;
  961. if(DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(Kanban)).EditItems(new[] { task }))
  962. {
  963. using (new WaitCursor())
  964. {
  965. /*var task = new Kanban();
  966. task.Title = form.Title;
  967. task.Description = form.Description;
  968. task.DueDate = DateTime.Today;
  969. task.EmployeeLink.ID = Employee.ID;
  970. task.ManagerLink.ID = Employee.ID;
  971. task.Category = "Open";
  972. task.Private = true;*/
  973. new Client<Kanban>().Save(task, "Created from Daily Report screen");
  974. /*var subscriber = new KanbanSubscriber();
  975. subscriber.Kanban.ID = task.ID;
  976. subscriber.Employee.ID = Employee.ID;
  977. subscriber.Assignee = true;
  978. subscriber.Manager = true;
  979. new Client<KanbanSubscriber>().Save(subscriber, "");*/
  980. LoadKanbans();
  981. }
  982. }
  983. //var form = new QuickTask();
  984. //if (form.ShowDialog() == true)
  985. }
  986. private void ShowPublicTasks_Checked(object sender, RoutedEventArgs e)
  987. {
  988. LoadKanbans();
  989. }
  990. private void Tasks_MouseDoubleClick(object sender, MouseButtonEventArgs e)
  991. {
  992. var listview = sender as ListView;
  993. if (listview == null)
  994. return;
  995. var kanban = listview.SelectedItem as Kanban;
  996. if (kanban == null)
  997. return;
  998. kg ??= new KanbanGrid();
  999. var bEdited = kg.EditItems(new[] { kanban });
  1000. if (bEdited)
  1001. LoadKanbans();
  1002. }
  1003. private void TaskMenu_ContextMenuOpening(object sender, ContextMenuEventArgs e)
  1004. {
  1005. var kanban = (sender as Border).Tag as Kanban;
  1006. var menu = (sender as Border).ContextMenu;
  1007. menu.Items.Clear();
  1008. if (_taskcategory != KanbanStatus.Open)
  1009. MoveToOpen = CreateTaskMenu(menu, "Move To [Open Tasks]", kanban, MoveTask_Click);
  1010. if (_taskcategory != KanbanStatus.InProgress)
  1011. MoveToCurrent = CreateTaskMenu(menu, "Move To [Tasks In Progress]", kanban, MoveTask_Click);
  1012. else
  1013. menu.Items.Add(new Separator());
  1014. if (_taskcategory != KanbanStatus.Waiting)
  1015. MoveToWaiting = CreateTaskMenu(menu, "Move To [Waiting For Others]", kanban, MoveTask_Click);
  1016. else
  1017. menu.Items.Add(new Separator());
  1018. if (_taskcategory != KanbanStatus.Complete)
  1019. MoveToComplete = CreateTaskMenu(menu, "Move To [Completed Tasks]", kanban, MoveTask_Click);
  1020. menu.Items.Add(new Separator());
  1021. CreateTaskMenu(menu, "Change Due Date", kanban, ChangeKanbanDueDate_Click);
  1022. }
  1023. private MenuItem CreateTaskMenu(ContextMenu menu, string header, Kanban kanban, RoutedEventHandler action)
  1024. {
  1025. var item = new MenuItem();
  1026. item.Header = header;
  1027. item.Tag = kanban;
  1028. item.Click += action;
  1029. menu.Items.Add(item);
  1030. return item;
  1031. }
  1032. private void ChangeKanbanDueDate_Click(object sender, RoutedEventArgs e)
  1033. {
  1034. var kanban = (sender as MenuItem)?.Tag as Kanban;
  1035. var date = kanban.DueDate;
  1036. if (DateEdit.Execute("Change Due Date", ref date))
  1037. {
  1038. kanban.DueDate = date;
  1039. new Client<Kanban>().Save(kanban, "");
  1040. LoadKanbans();
  1041. }
  1042. }
  1043. private void MoveTask_Click(object sender, RoutedEventArgs e)
  1044. {
  1045. var kanban = (sender as MenuItem)?.Tag as Kanban;
  1046. if (kanban == null)
  1047. return;
  1048. var category = sender == MoveToComplete
  1049. ? KanbanStatus.Complete
  1050. : sender == MoveToWaiting
  1051. ? KanbanStatus.Waiting
  1052. : sender == MoveToCurrent
  1053. ? KanbanStatus.InProgress
  1054. : KanbanStatus.Open;
  1055. kanban.Status = category;
  1056. new Client<Kanban>().Save(kanban, "");
  1057. LoadKanbans();
  1058. }
  1059. private void Assignments_OnItemEditing(object sender, ICalendarHandledEventArgs args)
  1060. {
  1061. args.Status = CalendarHandledStatus.Handled;
  1062. }
  1063. }
  1064. }