DailyReport.xaml.cs 52 KB

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