DailyReport.xaml.cs 52 KB

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