DailyReport.xaml.cs 52 KB

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