AssignmentView2.xaml.cs 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Input;
  9. using System.Windows.Media;
  10. using System.Windows.Media.Imaging;
  11. using System.Windows.Threading;
  12. using com.sun.jmx.mbeanserver;
  13. using Comal.Classes;
  14. using InABox.Clients;
  15. using InABox.Configuration;
  16. using InABox.Core;
  17. using InABox.DynamicGrid;
  18. using InABox.WPF;
  19. using Syncfusion.UI.Xaml.Scheduler;
  20. using Action = System.Action;
  21. using SelectionChangedEventArgs = System.Windows.Controls.SelectionChangedEventArgs;
  22. namespace PRSDesktop
  23. {
  24. public partial class AssignmentView2 : UserControl
  25. {
  26. #region Private Fields
  27. private class AssignmentViewModel : ScheduleAppointment, IAssignmentViewModel
  28. {
  29. public Guid AssignmentID { get; set; }
  30. public Guid EmployeeID { get; set; }
  31. public Brush AppointmentForeground { get; set; }
  32. public int Number { get; set; }
  33. public string JobNumber { get; set; }
  34. public BitmapImage Completed { get; set; }
  35. public BitmapImage HasDelivery { get; set; }
  36. public BitmapImage Locked { get; set; }
  37. public BitmapImage TimeSheet { get; set; }
  38. }
  39. private readonly BitmapImage back = PRSDesktop.Resources.back.AsBitmapImage(32, 32);
  40. private readonly BitmapImage box = PRSDesktop.Resources.box_sml.AsBitmapImage(32, 32);
  41. private readonly BitmapImage first = PRSDesktop.Resources.first.AsBitmapImage(32, 32);
  42. private readonly BitmapImage last = PRSDesktop.Resources.last.AsBitmapImage(32, 32);
  43. private readonly BitmapImage locked = PRSDesktop.Resources.lock_sml.AsBitmapImage(32, 32);
  44. private readonly BitmapImage next = PRSDesktop.Resources.next.AsBitmapImage(32, 32);
  45. private readonly BitmapImage tick = PRSDesktop.Resources.tick_sml.AsBitmapImage(32, 32);
  46. private readonly BitmapImage timesheet = PRSDesktop.Resources.clock_sml.AsBitmapImage(32, 32);
  47. private bool bReady = false;
  48. private Dictionary<Guid, String> _teams = new Dictionary<Guid, string>() { { CoreUtils.FullGuid, "All Teams" } };
  49. private CoreTable _employees = new CoreTable(typeof(EmployeeTeam));
  50. private CoreTable _assignments = new CoreTable(typeof(Assignment));
  51. private Guid _selectedassignment = Guid.Empty;
  52. private DateTime _selecteddate = DateTime.MinValue;
  53. private Guid _selectedteam = Guid.Empty;
  54. private Guid[] _selectedemployees = new Guid[] { };
  55. private double _zoom = 100.0D;
  56. private bool _sidebaropen = false;
  57. private AssignmentGrid _assignmentgrid = null;
  58. #endregion
  59. #region Events
  60. public event CustomiseAssignments CustomiseAssignments;
  61. public event CustomiseAssignmentsContextMenu CustomiseContextMenu;
  62. public event AssignmentSelectionChangedEvent AssignmentSelectionChanged;
  63. public event AssignmentChangedEvent AssignmentChanged;
  64. public event AssignmentViewSettingsChanged SettingsChanged;
  65. #endregion
  66. public AssignmentView2()
  67. {
  68. InitializeComponent();
  69. Loaded += OnLoaded;
  70. PrevMonth.Content = new Image { Source = first };
  71. PrevDay.Content = new Image { Source = back };
  72. NextDay.Content = new Image { Source = next };
  73. NextMonth.Content = new Image { Source = last };
  74. }
  75. private void OnLoaded(object sender, RoutedEventArgs args)
  76. {
  77. Loaded -= OnLoaded;
  78. UpdateUI(UpdateDateVisible);
  79. UpdateUI(UpdateCanShowHideSideBar);
  80. UpdateUI(UpdateTimeInterval);
  81. UpdateUI(UpdateStartHour);
  82. UpdateUI(UpdateEndHour);
  83. UpdateUI(UpdateWorkingHourColors);
  84. }
  85. #region Settings
  86. private void DoSettingsChanged()
  87. {
  88. var settings = new AssignmentViewSettings()
  89. {
  90. SelectedDate = this.SelectedDate,
  91. SelectedTeam = this.SelectedTeam,
  92. SelectedEmployees = this.SelectedEmployees,
  93. Zoom = this.Zoom,
  94. SideBarOpen = this.SideBarOpen
  95. };
  96. SettingsChanged?.Invoke(this, settings);
  97. }
  98. #endregion
  99. #region Public Properties
  100. public DateTime SelectedDate
  101. {
  102. get => _selecteddate;
  103. set
  104. {
  105. if (value != _selecteddate)
  106. {
  107. _selecteddate = value;
  108. UpdateUI(UpdateSelectedDate);
  109. DoSettingsChanged();
  110. }
  111. }
  112. }
  113. public Guid SelectedTeam
  114. {
  115. get => _selectedteam;
  116. set
  117. {
  118. if (value != _selectedteam)
  119. {
  120. _selectedteam = value;
  121. UpdateUI(UpdateSelectedTeam);
  122. DoSettingsChanged();
  123. }
  124. }
  125. }
  126. public Guid[] SelectedEmployees
  127. {
  128. get => _selectedemployees;
  129. set
  130. {
  131. if (new HashSet<Guid>(value).SetEquals(_selectedemployees) == false)
  132. {
  133. _selectedemployees = value;
  134. UpdateUI(UpdateSelectedEmployees);
  135. DoSettingsChanged();
  136. }
  137. }
  138. }
  139. public double Zoom
  140. {
  141. get => _zoom;
  142. set
  143. {
  144. if (Math.Abs(value - _zoom) > 0.001D)
  145. {
  146. _zoom = value;
  147. UpdateUI(UpdateZoom);
  148. DoSettingsChanged();
  149. }
  150. }
  151. }
  152. public bool SideBarOpen
  153. {
  154. get => _sidebaropen;
  155. set
  156. {
  157. if (value != _sidebaropen)
  158. {
  159. _sidebaropen = value;
  160. UpdateUI(UpdateSideBarOpen);
  161. DoSettingsChanged();
  162. }
  163. }
  164. }
  165. public int StartHour
  166. {
  167. get => (int)GetValue(StartHourProperty);
  168. set
  169. {
  170. if (value != StartHour)
  171. {
  172. SetValue(StartHourProperty, value);
  173. UpdateUI(UpdateStartHour);
  174. }
  175. }
  176. }
  177. public int EndHour
  178. {
  179. get => (int)GetValue(EndHourProperty);
  180. set
  181. {
  182. if (value != EndHour)
  183. {
  184. SetValue(EndHourProperty, value);
  185. UpdateUI(UpdateEndHour);
  186. }
  187. }
  188. }
  189. public Color WorkingHourColor
  190. {
  191. get => (Color)GetValue(WorkingHourColorProperty);
  192. set
  193. {
  194. if (!Color.Equals(value, WorkingHourColor))
  195. {
  196. SetValue(WorkingHourColorProperty, value);
  197. UpdateUI(UpdateWorkingHourColors);
  198. }
  199. }
  200. }
  201. public Color NonWorkingHourColor
  202. {
  203. get => (Color)GetValue(NonWorkingHourColorProperty);
  204. set
  205. {
  206. if (Color.Equals(value, NonWorkingHourColor))
  207. {
  208. SetValue(NonWorkingHourColorProperty, value);
  209. UpdateUI(UpdateWorkingHourColors);
  210. }
  211. }
  212. }
  213. public AssignmentViewTimeInterval TimeInterval
  214. {
  215. get => (AssignmentViewTimeInterval)GetValue(TimeIntervalProperty);
  216. set
  217. {
  218. if (value != TimeInterval)
  219. {
  220. SetValue(TimeIntervalProperty, value);
  221. UpdateUI(UpdateTimeInterval);
  222. }
  223. }
  224. }
  225. public bool CanShowHideSideBar
  226. {
  227. get => (bool)GetValue(CanShowHideSideBarProperty);
  228. set
  229. {
  230. if (value != CanShowHideSideBar)
  231. {
  232. SetValue(CanShowHideSideBarProperty, value);
  233. UpdateUI(UpdateCanShowHideSideBar);
  234. }
  235. }
  236. }
  237. public bool DateVisible
  238. {
  239. get => (bool)GetValue(DateVisibleProperty);
  240. set
  241. {
  242. if (value != DateVisible)
  243. {
  244. SetValue(DateVisibleProperty, value);
  245. UpdateUI(UpdateDateVisible);
  246. }
  247. }
  248. }
  249. #endregion
  250. #region Dependency Properties
  251. public static readonly DependencyProperty StartHourProperty =
  252. DependencyProperty.Register(
  253. "StartHour",
  254. typeof(int),
  255. typeof(AssignmentView2),
  256. new PropertyMetadata(6)
  257. );
  258. public static readonly DependencyProperty EndHourProperty =
  259. DependencyProperty.Register(
  260. "EndHour",
  261. typeof(int),
  262. typeof(AssignmentView2),
  263. new PropertyMetadata(18)
  264. );
  265. public static readonly DependencyProperty WorkingHourColorProperty =
  266. DependencyProperty.Register(
  267. "WorkingHourColor",
  268. typeof(Color),
  269. typeof(AssignmentView2),
  270. new PropertyMetadata(Colors.Transparent)
  271. );
  272. public static readonly DependencyProperty NonWorkingHourColorProperty =
  273. DependencyProperty.Register(
  274. "NonWorkingHourColor",
  275. typeof(Color),
  276. typeof(AssignmentView2),
  277. new PropertyMetadata(Colors.Gainsboro)
  278. );
  279. public static readonly DependencyProperty TimeIntervalProperty =
  280. DependencyProperty.Register(
  281. "TimeInterval",
  282. typeof(AssignmentViewTimeInterval),
  283. typeof(AssignmentView2),
  284. new PropertyMetadata(AssignmentViewTimeInterval.FifteenMinutes)
  285. );
  286. public static readonly DependencyProperty CanShowHideSideBarProperty =
  287. DependencyProperty.Register(
  288. "CanShowHideSideBar",
  289. typeof(bool),
  290. typeof(AssignmentView2),
  291. new PropertyMetadata(true)
  292. );
  293. public static readonly DependencyProperty DateVisibleProperty =
  294. DependencyProperty.Register(
  295. "DateVisible",
  296. typeof(bool),
  297. typeof(AssignmentView2),
  298. new PropertyMetadata(true)
  299. );
  300. #endregion
  301. #region UI Sync Stuff
  302. // These functions should "push" property values to the UI
  303. // They should _not_ update the properties themselves
  304. // to avoid circular updates
  305. private bool _updatingUI = false;
  306. private void UpdateUI(Action action)
  307. {
  308. _updatingUI = true;
  309. try
  310. {
  311. action?.Invoke();
  312. }
  313. finally
  314. {
  315. _updatingUI = false;
  316. }
  317. }
  318. private void UpdateStartHour()
  319. {
  320. StartTime.Value = new TimeSpan(StartHour, 0, 0);
  321. StartAMPM.Content = StartHour < 12 ? " AM " : StartHour > 12 ? " PM " : " NN ";
  322. UpdateWorkingHourColors();
  323. Bookings.SelectedDate = _selecteddate.Date;
  324. var margin = IntervalToTimeSpan(TimeInterval);
  325. var start = new TimeSpan(StartHour, 0, 0);
  326. if (start >= margin)
  327. start -= margin;
  328. Bookings.DisplayDate = _selecteddate.Add(start);
  329. }
  330. private void UpdateEndHour()
  331. {
  332. EndTime.Value = new TimeSpan(EndHour, 0, 0);
  333. EndAMPM.Content = EndHour < 12 ? " AM " : EndHour > 12 ? " PM " : " NN ";
  334. UpdateWorkingHourColors();
  335. }
  336. private void UpdateWorkingHourColors()
  337. {
  338. if (Bookings.ResourceCollection == null)
  339. return;
  340. var resources = Bookings.ResourceCollection.OfType<SchedulerResource>();
  341. if (!resources.Any())
  342. return;
  343. var regions = new ObservableCollection<SpecialTimeRegion>();
  344. foreach (var resource in resources)
  345. {
  346. if (StartHour > 0)
  347. {
  348. var before = new SpecialTimeRegion
  349. {
  350. StartTime = SelectedDate.Date,
  351. EndTime = SelectedDate.Date.AddHours(StartHour),
  352. ResourceIdCollection = new ObservableCollection<object> { resource.Id },
  353. Background = new SolidColorBrush(NonWorkingHourColor),
  354. Foreground = new SolidColorBrush(Colors.Black),
  355. CanMergeAdjacentRegions = true
  356. };
  357. regions.Add(before);
  358. }
  359. if (EndHour < 24)
  360. {
  361. var after = new SpecialTimeRegion
  362. {
  363. StartTime = SelectedDate.Date.AddHours(EndHour),
  364. EndTime = SelectedDate.Date.AddDays(1).AddMilliseconds(-1),
  365. ResourceIdCollection = new ObservableCollection<object> { resource.Id },
  366. Background = new SolidColorBrush(NonWorkingHourColor),
  367. Foreground = new SolidColorBrush(Colors.Black),
  368. CanMergeAdjacentRegions = true
  369. };
  370. regions.Add(after);
  371. }
  372. if (StartHour < EndHour)
  373. {
  374. var working = new SpecialTimeRegion
  375. {
  376. StartTime = SelectedDate.Date.AddHours(StartHour),
  377. EndTime = SelectedDate.Date.AddHours(EndHour),
  378. ResourceIdCollection = new ObservableCollection<object> { resource.Id },
  379. Background = new SolidColorBrush(WorkingHourColor),
  380. Foreground = new SolidColorBrush(Colors.Black),
  381. CanMergeAdjacentRegions = true
  382. };
  383. regions.Add(working);
  384. }
  385. }
  386. Bookings.DaysViewSettings.SpecialTimeRegions = regions;
  387. }
  388. private void UpdateSelectedTeam()
  389. {
  390. Teams.SelectedValue = SelectedTeam;
  391. LoadEmployees();
  392. }
  393. private void UpdateTimeInterval()
  394. {
  395. try
  396. {
  397. if (Bookings.IsVisible)
  398. Bookings.DaysViewSettings.TimeInterval = IntervalToTimeSpan(TimeInterval);
  399. }
  400. catch (Exception e)
  401. {
  402. // If the view is invisible, setting the time interval throws an exeception (internal scroll viewer is still set to null)
  403. // So we only want to log an error if the view is actually visible
  404. if (Bookings.IsVisible)
  405. Logger.Send(LogType.Error, "", String.Format("Unable to update TimeInterval!\n{0}\n\n{1}", e.Message, e.StackTrace));
  406. }
  407. }
  408. private void UpdateCanShowHideSideBar()
  409. {
  410. ShowSideBar.Visibility = CanShowHideSideBar && !SideBarOpen
  411. ? Visibility.Visible
  412. : Visibility.Collapsed;
  413. HideSideBar.Visibility = CanShowHideSideBar && SideBarOpen
  414. ? Visibility.Visible
  415. : Visibility.Collapsed;
  416. }
  417. private void UpdateDateVisible()
  418. {
  419. DateRow.Height = DateVisible
  420. ? new GridLength(35, GridUnitType.Pixel)
  421. : new GridLength(0, GridUnitType.Pixel);
  422. }
  423. private void UpdateSideBarOpen()
  424. {
  425. SideBar.Width = SideBarOpen
  426. ? new GridLength(200, GridUnitType.Pixel)
  427. : new GridLength(0, GridUnitType.Pixel);
  428. DateBorder.BorderThickness = SideBarOpen
  429. ? new Thickness(0.75, 0.75, 0, 0.75)
  430. : new Thickness(0.75, 0.75, 0.75, 0.75);
  431. UpdateCanShowHideSideBar();
  432. }
  433. private void UpdateZoom()
  434. {
  435. ResizeIntervals(Bookings.ActualHeight);
  436. }
  437. private void UpdateSelectedDate()
  438. {
  439. CurrentDate.Text = string.Format("{0:ddd, dd MMMM yyyy}", SelectedDate);
  440. Bookings.SelectedDate = _selecteddate.Date;
  441. var margin = IntervalToTimeSpan(TimeInterval);
  442. var start = new TimeSpan(StartHour, 0, 0);
  443. if (start >= margin)
  444. start -= margin;
  445. Bookings.DisplayDate = _selecteddate.Add(start);
  446. }
  447. public void SetDisplayWindow(int start, int end)
  448. {
  449. if (!double.IsNaN(ActualHeight))
  450. {
  451. ResizeIntervals(ActualHeight);
  452. SelectedDate = SelectedDate; // to trigger a reset?
  453. }
  454. }
  455. private void LoadEmployees()
  456. {
  457. var emps = new Dictionary<Guid, string>();
  458. foreach (var row in _employees.Rows.Where(r =>
  459. r.Get<EmployeeTeam, Guid>(c => c.TeamLink.ID).Equals(SelectedTeam) || SelectedTeam.Equals(CoreUtils.FullGuid)))
  460. emps[row.Get<EmployeeTeam, Guid>(c => c.EmployeeLink.ID)] = row.Get<EmployeeTeam, string>(c => c.EmployeeLink.Name);
  461. Employees.ItemsSource = emps;
  462. }
  463. private void UpdateSelectedEmployees()
  464. {
  465. List<SchedulerResource> resources = new List<SchedulerResource>();
  466. Employees.SelectedItems.Clear();
  467. foreach (var item in Employees.Items)
  468. {
  469. var emp = (KeyValuePair<Guid, string>)item;
  470. if (SelectedEmployees.Contains(emp.Key))
  471. {
  472. Employees.SelectedItems.Add(item);
  473. resources.Add(
  474. new SchedulerResource
  475. {
  476. Name = emp.Value,
  477. Id = emp.Key.ToString()
  478. }
  479. );
  480. }
  481. }
  482. Bookings.ResourceCollection = new ObservableCollection<object>(resources);
  483. Bookings.DaysViewSettings.ResourceHeaderSize = resources.Count <= 1 ? 0 : 50;
  484. }
  485. #endregion
  486. public Assignment FindAssignment(Guid id)
  487. {
  488. return _assignments.Rows.FirstOrDefault(r => r.Get<Assignment, Guid>(c => c.ID).Equals(id))?.ToObject<Assignment>();
  489. }
  490. private IAssignmentViewModel FindModel(Guid id)
  491. {
  492. var appointments = Bookings.ItemsSource as ScheduleAppointmentCollection;
  493. return appointments.FirstOrDefault(x => (x as IAssignmentViewModel).AssignmentID.Equals(id)) as IAssignmentViewModel;
  494. }
  495. public void AddAssignment(Assignment assignment)
  496. {
  497. var row = _assignments.NewRow();
  498. _assignments.LoadRow(row, assignment);
  499. _assignments.Rows.Add(row);
  500. LoadModels(assignment.ID);
  501. }
  502. public void GetWindow(TimeSpan time, ref TimeSpan start, ref TimeSpan finish)
  503. {
  504. foreach (var row in _assignments.Rows)
  505. {
  506. var curstart = row.Get<Assignment, TimeSpan>(x => x.Start);
  507. var curfinish = row.Get<Assignment, TimeSpan>(x => x.Finish);
  508. if ((curfinish <= time) && (curfinish >= start))
  509. start = curfinish;
  510. if ((curstart >= time) && (curstart <= finish))
  511. finish = curstart;
  512. }
  513. }
  514. public CoreTable Data() => _assignments;
  515. public void Setup()
  516. {
  517. _employees = new Client<EmployeeTeam>().Query(
  518. null,
  519. new Columns<EmployeeTeam>(
  520. x => x.TeamLink.ID,
  521. x => x.TeamLink.Code,
  522. x => x.TeamLink.Name,
  523. x => x.EmployeeLink.ID,
  524. x => x.EmployeeLink.Name
  525. ),
  526. new SortOrder<EmployeeTeam>(x => x.TeamLink.Code).ThenBy(x => x.EmployeeLink.Name)
  527. );
  528. _employees.IntoDictionary<EmployeeTeam, Guid, String>(
  529. _teams,
  530. x => x.TeamLink.ID,
  531. r => r.Get<EmployeeTeam,String>(c=>c.TeamLink.Name)
  532. );
  533. Teams.ItemsSource = _teams;
  534. bReady = true;
  535. }
  536. private void ResizeIntervals(double height)
  537. {
  538. if (double.IsNaN(height) || height == 0.0F)
  539. return;
  540. var zoomedheight = height * (Zoom / 100.0F);
  541. Bookings.DaysViewSettings.TimeIntervalSize = zoomedheight / 24;
  542. }
  543. private void Bookings_SizeChanged(object sender, SizeChangedEventArgs e)
  544. {
  545. ResizeIntervals(e.NewSize.Height);
  546. }
  547. public void Refresh()
  548. {
  549. var filter = new Filter<Assignment>(x => x.Date).IsGreaterThanOrEqualTo(SelectedDate.Date)
  550. .And(x => x.Date).IsLessThan(SelectedDate.Date.AddDays(1))
  551. .And(x =>x.EmployeeLink.ID).InList(SelectedEmployees);
  552. _assignments = new Client<Assignment>().Query(
  553. filter,
  554. new Columns<Assignment>(
  555. x => x.ID,
  556. x => x.Title,
  557. x => x.ActivityLink.ID,
  558. x => x.ActivityLink.Color,
  559. x => x.ActivityLink.Description,
  560. x => x.ActivityLink.Deleted,
  561. x => x.JobLink.ID,
  562. x => x.JobLink.Name,
  563. x => x.JobLink.JobNumber,
  564. x => x.JobLink.Deleted,
  565. x => x.ITP.ID,
  566. x => x.ITP.Code,
  567. x => x.ITP.Description,
  568. x => x.ITP.Deleted,
  569. x => x.Number,
  570. x => x.Description,
  571. x => x.Date,
  572. x => x.Start,
  573. x => x.Duration,
  574. x => x.Finish,
  575. x => x.LeaveRequestLink.ID,
  576. x => x.Completed,
  577. x => x.Delivery.ID,
  578. x => x.Delivery.Notes,
  579. x => x.Delivery.Deleted,
  580. x => x.TimeSheetLink.ID,
  581. x => x.TimeSheetLink.Deleted,
  582. x => x.EmployeeLink.ID,
  583. x => x.Task.ID,
  584. x => x.Task.Number
  585. )
  586. );
  587. CustomiseAssignments?.Invoke(this, _assignments);
  588. LoadModels(Guid.Empty);
  589. }
  590. private void LoadModels(Guid id)
  591. {
  592. IAssignmentViewModel selected = null;
  593. var appointments = new ScheduleAppointmentCollection();
  594. foreach (var row in _assignments.Rows)
  595. {
  596. var assignment = row.ToObject<Assignment>();
  597. var sColor = assignment.ActivityLink.Color;
  598. var bgColor = string.IsNullOrWhiteSpace(sColor) ? Colors.White : (Color)ColorConverter.ConvertFromString(sColor);
  599. var jobdesc = new List<string>();
  600. var itask = assignment.Task.Number;
  601. if (itask > 0)
  602. jobdesc.Add(string.Format("Task #{0}", itask));
  603. if (assignment.JobLink.IsValid())
  604. {
  605. var job = assignment.JobLink.JobNumber;
  606. if (assignment.ITP.IsValid())
  607. job = string.Format("{0} {1}", job, assignment.ITP.Code);
  608. job = string.Format("({0})", job);
  609. jobdesc.Add(job);
  610. }
  611. var date = assignment.Date;
  612. var sNote = assignment.Description + (assignment.Delivery.IsValid()
  613. ? "\n" + assignment.Delivery.Notes
  614. : "");
  615. var model = new AssignmentViewModel
  616. {
  617. Subject = string.Format("{0}", assignment.Title?.Trim()),
  618. JobNumber = string.Format(" {0} ", string.Join(" ", jobdesc)),
  619. Number = assignment.Number,
  620. Notes = sNote.Trim(),
  621. StartTime = date.Add(assignment.Start),
  622. EndTime = date.Add(assignment.Finish),
  623. AssignmentID = assignment.ID,
  624. EmployeeID = assignment.EmployeeLink.ID,
  625. //AllDay = false,
  626. AppointmentForeground = new SolidColorBrush(Colors.Black),
  627. AppointmentBackground = new SolidColorBrush(bgColor),
  628. Locked = assignment.LeaveRequestLink.IsValid() ? locked : null,
  629. Completed = !assignment.LeaveRequestLink.IsValid() && !assignment.Completed.IsEmpty() ? tick : null,
  630. HasDelivery = !assignment.LeaveRequestLink.IsValid() && assignment.Delivery.IsValid() ? box : null,
  631. TimeSheet = assignment.TimeSheetLink.IsValid() ? timesheet : null,
  632. ResourceIdCollection = new ObservableCollection<object>() { assignment.EmployeeLink.ID.ToString() }
  633. };
  634. appointments.Add(model);
  635. if (model.AssignmentID == id)
  636. selected = model;
  637. }
  638. Bookings.ItemsSource = appointments;
  639. ResizeIntervals(Bookings.ActualHeight);
  640. UpdateWorkingHourColors();
  641. }
  642. public void UpdateAssignment(Assignment assignment)
  643. {
  644. var row = _assignments.Rows.FirstOrDefault(r => r.Get<Assignment, Guid>(x => x.ID).Equals(assignment.ID));
  645. _assignments.LoadRow(row, assignment);
  646. var model = FindModel(assignment.ID);
  647. var sColor = assignment.ActivityLink.Color;
  648. var bgColor = string.IsNullOrWhiteSpace(sColor) ? Colors.White : (Color)ColorConverter.ConvertFromString(sColor);
  649. var date = assignment.Date;
  650. var leaveid = assignment.LeaveRequestLink.ID;
  651. var job = "";
  652. if (assignment.JobLink.IsValid())
  653. {
  654. job = assignment.JobLink.JobNumber;
  655. if (assignment.ITP.IsValid())
  656. job = string.Format("{0} {1}", job, assignment.ITP.Code);
  657. job = string.Format(" ({0}) ", job);
  658. }
  659. model.Subject = assignment.Title;
  660. model.Number = assignment.Number;
  661. model.JobNumber = job;
  662. model.Notes = assignment.Description;
  663. model.StartTime = date.Add(assignment.Start);
  664. model.EndTime = date.Add(assignment.Finish);
  665. model.AppointmentBackground = new SolidColorBrush(bgColor);
  666. model.Locked = assignment.LeaveRequestLink.IsValid() ? locked : null;
  667. model.Completed = !assignment.LeaveRequestLink.IsValid() && !assignment.Completed.IsEmpty() ? tick : null;
  668. model.HasDelivery = !assignment.LeaveRequestLink.IsValid() && assignment.Delivery.IsValid() ? box : null;
  669. model.TimeSheet = assignment.TimeSheetLink.IsValid() ? timesheet : null;
  670. //Bookings.UpdateLayout();
  671. }
  672. #region Responding to UI Events
  673. private void PrevMonth_Click(object sender, RoutedEventArgs e)
  674. {
  675. SelectedDate = SelectedDate.AddDays(-7);
  676. AssignmentSelectionChanged?.Invoke(this, null);
  677. Refresh();
  678. }
  679. private void PrevDay_Click(object sender, RoutedEventArgs e)
  680. {
  681. SelectedDate = SelectedDate.AddDays(-1);
  682. AssignmentSelectionChanged?.Invoke(this, null);
  683. Refresh();
  684. }
  685. private void CurrentDate_MouseDoubleClick(object sender, MouseButtonEventArgs e)
  686. {
  687. SelectedDate = DateTime.Today;
  688. AssignmentSelectionChanged?.Invoke(this, null);
  689. Refresh();
  690. }
  691. private void NextDay_Click(object sender, RoutedEventArgs e)
  692. {
  693. SelectedDate = SelectedDate.AddDays(1);
  694. AssignmentSelectionChanged?.Invoke(this, null);
  695. Refresh();
  696. }
  697. private void NextMonth_Click(object sender, RoutedEventArgs e)
  698. {
  699. SelectedDate = SelectedDate.AddDays(7);
  700. AssignmentSelectionChanged?.Invoke(this, null);
  701. Refresh();
  702. }
  703. private void Teams_SelectionChanged(object sender, SelectionChangedEventArgs e)
  704. {
  705. if (_updatingUI)
  706. return;
  707. SelectedTeam = (Guid)Teams.SelectedValue;
  708. SelectedEmployees = _employees.Rows
  709. .Where(r => (SelectedTeam == CoreUtils.FullGuid) || (r.Get<EmployeeTeam, Guid>(c => c.TeamLink.ID) == SelectedTeam))
  710. .Select(r => r.Get<EmployeeTeam, Guid>(c => c.EmployeeLink.ID))
  711. .Distinct()
  712. .ToArray();
  713. Refresh();
  714. }
  715. private void Employees_SelectionChanged(object sender, SelectionChangedEventArgs e)
  716. {
  717. if (_updatingUI)
  718. return;
  719. SelectedEmployees = Employees.SelectedItems.Select(x => ((KeyValuePair<Guid, String>)x).Key).ToArray();
  720. Refresh();
  721. }
  722. private void StartTime_OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  723. {
  724. if (_updatingUI)
  725. return;
  726. StartHour = (int)StartTime.Value.Value.TotalHours;
  727. }
  728. private void EndTime_OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  729. {
  730. if (_updatingUI)
  731. return;
  732. EndHour = (int)EndTime.Value.Value.TotalHours;
  733. }
  734. private void OpenSideBar_Click(object sender, RoutedEventArgs e)
  735. {
  736. SideBarOpen = true;
  737. }
  738. private void CloseSideBar_Click(object sender, RoutedEventArgs e)
  739. {
  740. SideBarOpen = false;
  741. }
  742. #endregion
  743. private void Schedule_AppointmentEditorOpening(object sender, AppointmentEditorOpeningEventArgs e)
  744. {
  745. if (e.Appointment != null)
  746. {
  747. var model = (AssignmentViewModel)e.Appointment;
  748. Assignment ass = null;
  749. using (new WaitCursor())
  750. {
  751. ass = new Client<Assignment>().Load(new Filter<Assignment>(x => x.ID).IsEqualTo(model.AssignmentID))
  752. .FirstOrDefault();
  753. }
  754. if (ass != null)
  755. EditAssignment(ass);
  756. else
  757. MessageBox.Show("Cannot Load Assignment!");
  758. }
  759. else
  760. {
  761. var res = e.Resource;
  762. if (res != null)
  763. {
  764. var ass = new Assignment();
  765. ass.EmployeeLink.ID = Guid.Parse(res.Id.ToString());
  766. ass.Date = e.DateTime;
  767. ass.Duration = new TimeSpan(1, 0, 0);
  768. var ag = new DynamicDataGrid<Assignment>();
  769. if (ag.EditItems(new[] { ass }))
  770. Refresh();
  771. }
  772. else
  773. {
  774. MessageBox.Show("No Employee Selected!");
  775. }
  776. }
  777. e.Cancel = true;
  778. }
  779. // private void Schedule_AppointmentStartDragging(object sender, AppointmentStartDraggingEventArgs e)
  780. // {
  781. // var model = e.Appointment as AssignmentViewModel;
  782. // if (model == null || model.Locked != null || model.TimeSheet != null)
  783. // e.Cancel = true;
  784. // }
  785. //
  786. // private void Schedule_AppointmentEndDragging(object sender, AppointmentEndDraggingEventArgs e)
  787. // {
  788. // var model = (AssignmentViewModel)e.Appointment;
  789. //
  790. // var row = model != null ? Assignments.Rows.FirstOrDefault(r => r.Get<Assignment, Guid>(x => x.ID).Equals(model.AssignmentID)) : null;
  791. // if (row != null)
  792. // {
  793. // Assignment ass = null;
  794. // using (new WaitCursor())
  795. // {
  796. // ass = new Client<Assignment>().Load(new Filter<Assignment>(x => x.ID).IsEqualTo(model.AssignmentID)).FirstOrDefault();
  797. // }
  798. //
  799. // if (ass != null)
  800. // {
  801. // var resource = e.Resources.FirstOrDefault() as Resource;
  802. // var employeeid = Guid.Parse(resource.ResourceName);
  803. // ass.EmployeeLink.ID = employeeid;
  804. //
  805. // var newtime = e.To.TimeOfDay;
  806. // if (e.To.Minute >= 45)
  807. // newtime = new TimeSpan(e.To.Hour, 45, 0);
  808. // else if (e.To.Minute >= 30)
  809. // newtime = new TimeSpan(e.To.Hour, 30, 0);
  810. // else if (e.To.Minute >= 15)
  811. // newtime = new TimeSpan(e.To.Hour, 15, 0);
  812. // else
  813. // newtime = new TimeSpan(e.To.Hour, 0, 0);
  814. // ass.Date = e.To.Date;
  815. // ass.Start = newtime;
  816. //
  817. // using (new WaitCursor())
  818. // {
  819. // new Client<Assignment>().Save(ass, "Dragged by User", (obj, args) => { });
  820. // }
  821. //
  822. // AssignmentChanged?.Invoke(this, ass);
  823. //
  824. // Refresh();
  825. //
  826. // e.Cancel = true;
  827. // }
  828. // else
  829. // {
  830. // MessageBox.Show("Unable to load Assigmment!");
  831. // }
  832. // }
  833. // else
  834. // {
  835. // MessageBox.Show("Unable to locate Assignment!");
  836. // }
  837. // }
  838. //
  839. // private void Schedule_AppointmentEndResizing(object sender, AppointmentEndResizingEventArgs e)
  840. // {
  841. // var model = (AssignmentViewModel)e.Appointment;
  842. // var row = model != null ? Assignments.Rows.FirstOrDefault(r => r.Get<Assignment, Guid>(x => x.ID).Equals(model.AssignmentID)) : null;
  843. // if (row != null)
  844. // {
  845. // Assignment ass = null;
  846. // using (new WaitCursor())
  847. // {
  848. // ass = new Client<Assignment>().Load(new Filter<Assignment>(x => x.ID).IsEqualTo(model.AssignmentID)).FirstOrDefault();
  849. // }
  850. //
  851. // if (ass != null)
  852. // {
  853. // var newtime = e.To;
  854. // if (e.To.Minute >= 45)
  855. // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 45, 0);
  856. // else if (e.To.Minute >= 30)
  857. // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 30, 0);
  858. // else if (e.To.Minute >= 15)
  859. // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 15, 0);
  860. // else
  861. // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 0, 0);
  862. // ass.Date = newtime;
  863. // using (new WaitCursor())
  864. // {
  865. // new Client<Assignment>().Save(ass, "Dragged by User", (obj, args) => { });
  866. // }
  867. //
  868. // AssignmentChanged?.Invoke(this, ass);
  869. //
  870. // Refresh();
  871. // e.Cancel = true;
  872. // }
  873. // else
  874. // {
  875. // MessageBox.Show("Unable to load Assigmment!");
  876. // }
  877. // }
  878. // else
  879. // {
  880. // MessageBox.Show("Unable to locate Assignment!");
  881. // }
  882. // }
  883. //
  884. // private AssignmentViewTimeInterval TimeSpanToInterval(TimeSpan time)
  885. // {
  886. // if (time <= new TimeSpan(0, 5, 0))
  887. // return AssignmentViewTimeInterval.FiveMinutes;
  888. // if (time <= new TimeSpan(0, 6, 0))
  889. // return AssignmentViewTimeInterval.SixMinutes;
  890. // if (time <= new TimeSpan(0, 10, 0))
  891. // return AssignmentViewTimeInterval.TenMinutes;
  892. // if (time <= new TimeSpan(0, 15, 0))
  893. // return AssignmentViewTimeInterval.FifteenMinutes;
  894. // if (time <= new TimeSpan(0, 20, 0))
  895. // return AssignmentViewTimeInterval.TwentyMinutes;
  896. // if (time <= new TimeSpan(0, 30, 0))
  897. // return AssignmentViewTimeInterval.ThirtyMinutes;
  898. // return AssignmentViewTimeInterval.SixyMinutes;
  899. // }
  900. private TimeSpan IntervalToTimeSpan(AssignmentViewTimeInterval interval)
  901. {
  902. switch (interval)
  903. {
  904. case AssignmentViewTimeInterval.FiveMinutes:
  905. return new TimeSpan(0, 5, 0);
  906. case AssignmentViewTimeInterval.SixMinutes:
  907. return new TimeSpan(0, 6, 0);
  908. case AssignmentViewTimeInterval.TenMinutes:
  909. return new TimeSpan(0, 10, 0);
  910. case AssignmentViewTimeInterval.FifteenMinutes:
  911. return new TimeSpan(0, 15, 0);
  912. case AssignmentViewTimeInterval.TwentyMinutes:
  913. return new TimeSpan(0, 20, 0);
  914. case AssignmentViewTimeInterval.ThirtyMinutes:
  915. return new TimeSpan(0, 30, 0);
  916. default:
  917. return new TimeSpan(1, 0, 0);
  918. }
  919. }
  920. // private int GetDivider(AssignmentViewTimeInterval interval)
  921. // {
  922. // switch (interval)
  923. // {
  924. // case AssignmentViewTimeInterval.FiveMinutes:
  925. // return 12;
  926. // case AssignmentViewTimeInterval.SixMinutes:
  927. // return 10;
  928. // case AssignmentViewTimeInterval.TenMinutes:
  929. // return 6;
  930. // case AssignmentViewTimeInterval.FifteenMinutes:
  931. // return 4;
  932. // case AssignmentViewTimeInterval.TwentyMinutes:
  933. // return 3;
  934. // case AssignmentViewTimeInterval.ThirtyMinutes:
  935. // return 2;
  936. // default:
  937. // return 1;
  938. // }
  939. // }
  940. //
  941. // private TimeSpan GetTime(int row)
  942. // {
  943. // int divider = GetDivider(TimeInterval);
  944. // var hours = row / divider;
  945. // var mins = row % divider * (60 / divider);
  946. // return new TimeSpan(hours, mins, 0);
  947. // }
  948. // private TimeSpan GetTime(Point point)
  949. // {
  950. // var view = Bookings.FindVisualChildren<ScrollViewer>().LastOrDefault(x => x.Name.Equals("PART_ScrollViewer"));
  951. // var intervalheight = (Bookings.ActualHeight - 30.0F) / (24 * 4);
  952. // var row = (int)Math.Truncate((view.VerticalOffset + point.Y - 30.0F) / Bookings.DaysViewSettings.TimeIntervalSize);
  953. // var result = GetTime(row);
  954. // return result;
  955. // }
  956. // private void Bookings_Drop(object sender, DragEventArgs e)
  957. // {
  958. // if (e.Data.GetDataPresent("Comal.Classes.Delivery"))
  959. // {
  960. // var delivery = (e.Data.GetData("Comal.Classes.Delivery") as CoreRow[]).FirstOrDefault();
  961. // if (delivery == null)
  962. // return;
  963. //
  964. // var assignment = new Assignment();
  965. //
  966. // var resource = Bookings.ResourceCollection.OfType<SchedulerResource>().ToArray();
  967. // var colwidth = Bookings.ActualWidth / resource.Length;
  968. // var column = (int)Math.Truncate(e.GetPosition(Bookings).X / colwidth);
  969. // var employee = resource[column];
  970. //
  971. // assignment.EmployeeLink.ID = Guid.Parse(employee.Id.ToString());
  972. //
  973. // assignment.Date = SelectedDate.Date;
  974. //
  975. // //double intervalheight = (Bookings.ActualHeight - 30.0F) / (double)((Bookings.WorkEndHour - Bookings.WorkStartHour) * 4);
  976. // //int row = (int)Math.Truncate((e.GetPosition(Bookings).Y - 30.0F) / intervalheight);
  977. // //int hour = Bookings.WorkStartHour + (row / 4);
  978. // //int min = (row % 4) * 15;
  979. // //assignment.Start = new TimeSpan(hour, min, 0);
  980. // assignment.Start = GetTime(e.GetPosition(Bookings));
  981. //
  982. // assignment.Duration = new TimeSpan(2, 0, 0);
  983. //
  984. // assignment.JobLink.ID = delivery.Get<Delivery, Guid>(x => x.Job.ID);
  985. //
  986. // assignment.Description = string.Format("Delivery Docket #{0}", delivery.Get<Delivery, int>(x => x.Number));
  987. //
  988. // using (new WaitCursor())
  989. // {
  990. // new Client<Assignment>().Save(assignment, "Created for Delivery");
  991. // var del = new Client<Delivery>().Load(new Filter<Delivery>(x => x.ID).IsEqualTo(delivery.Get<Delivery, Guid>(x => x.ID)))
  992. // .FirstOrDefault();
  993. // del.Assignment.ID = assignment.ID;
  994. // new Client<Delivery>().Save(del, "Booked via Scheduler");
  995. // }
  996. //
  997. // AssignmentChanged?.Invoke(this, assignment);
  998. //
  999. // Refresh();
  1000. //
  1001. // AssignmentSelectionChanged?.Invoke(this, assignment);
  1002. // }
  1003. // else if (e.Data.GetDataPresent("Comal.Classes.Kanban"))
  1004. // {
  1005. // var kanban = e.Data.GetData("Comal.Classes.Kanban") as Kanban;
  1006. // if (kanban == null)
  1007. // return;
  1008. //
  1009. // var assignment = new Assignment();
  1010. //
  1011. // var resources = Bookings.ResourceCollection.OfType<SchedulerResource>().ToArray();
  1012. // var colwidth = Bookings.ActualWidth / resources.Length;
  1013. // var column = (int)Math.Truncate(e.GetPosition(Bookings).X / colwidth);
  1014. // var employee = resources[column];
  1015. //
  1016. // assignment.EmployeeLink.ID = Guid.Parse(employee.Id.ToString());
  1017. //
  1018. // assignment.Date = SelectedDate.Date;
  1019. //
  1020. // var view = Bookings.FindVisualChildren<ScrollViewer>().FirstOrDefault(x => x.Name.Equals("Scrollviewer1"));
  1021. // var intervalheight = (Bookings.ActualHeight - 30.0F) / (24 * 4);
  1022. // var row = (int)Math.Truncate((view.VerticalOffset + e.GetPosition(Bookings).Y - 30.0F) / Bookings.DaysViewSettings.TimeIntervalSize);
  1023. // assignment.Start = GetTime(row);
  1024. //
  1025. // assignment.Duration = new TimeSpan(0, 30, 0);
  1026. //
  1027. // assignment.JobLink.ID = kanban.JobLink.ID;
  1028. // assignment.Task.ID = kanban.ID;
  1029. //
  1030. // assignment.Title = kanban.Title;
  1031. //
  1032. // AssignmentChanged?.Invoke(this, assignment);
  1033. //
  1034. // Refresh();
  1035. //
  1036. // AssignmentSelectionChanged?.Invoke(this, assignment);
  1037. // }
  1038. // }
  1039. private void Bookings_OnAppointmentTapped(object? sender, AppointmentTappedArgs e)
  1040. {
  1041. var model = e.Appointment as IAssignmentViewModel;
  1042. if (model != null)
  1043. {
  1044. var ass = FindAssignment(model.AssignmentID);
  1045. if (
  1046. ((ass == null) && (_selectedassignment != null))
  1047. || ((ass != null) && (ass.ID != _selectedassignment))
  1048. )
  1049. {
  1050. _selectedassignment = ass != null ? ass.ID : Guid.Empty;
  1051. AssignmentSelectionChanged?.Invoke(this, ass);
  1052. }
  1053. }
  1054. else
  1055. {
  1056. if (_selectedassignment != Guid.Empty)
  1057. {
  1058. _selectedassignment = Guid.Empty;
  1059. AssignmentSelectionChanged?.Invoke(this, null);
  1060. }
  1061. }
  1062. }
  1063. #region Context Menu Handling
  1064. private void Bookings_OnSchedulerContextMenuOpening(object? sender, SchedulerContextMenuOpeningEventArgs e)
  1065. {
  1066. IAssignmentData args = null;
  1067. e.ContextMenu.Items.Clear();
  1068. if (e.MenuType == SchedulerContextMenuType.Appointment)
  1069. {
  1070. var model = e.MenuInfo.Appointment as IAssignmentViewModel;
  1071. args = new AssignmentData(model, Guid.Empty, DateTime.MinValue);
  1072. CreateEditMenu(e.ContextMenu, args);
  1073. e.ContextMenu.Items.Add(new Separator());
  1074. CreateDeleteMenu(e.ContextMenu, args);
  1075. e.ContextMenu.Items.Add(new Separator());
  1076. }
  1077. else if (e.MenuType == SchedulerContextMenuType.TimeSlotCell)
  1078. {
  1079. if (Guid.TryParse(e.MenuInfo.Resource.Id?.ToString(), out Guid employeeid))
  1080. {
  1081. args = new AssignmentData(null, employeeid, e.MenuInfo.DateTime.Value);
  1082. CreateAddMenu(e.ContextMenu, args);
  1083. e.ContextMenu.Items.Add(new Separator());
  1084. }
  1085. }
  1086. CreateZoomMenus(e.ContextMenu, args);
  1087. CustomiseContextMenu?.Invoke(e.ContextMenu, args);
  1088. }
  1089. private void CreateMenu(ContextMenu menu, string name, string header, IAssignmentData args, RoutedEventHandler action,
  1090. Visibility visibility)
  1091. {
  1092. var item = new MenuItem();
  1093. item.Name = name;
  1094. item.Header = header;
  1095. item.Click += action;
  1096. item.Visibility = visibility;
  1097. item.Tag = args;
  1098. menu.Items.Add(item);
  1099. }
  1100. public bool CreateAddMenu(ContextMenu menu, IAssignmentData args)
  1101. {
  1102. if (args.Model == null)
  1103. {
  1104. CreateMenu(menu, "CreateAssignment", "Create Assignment", args, CreateAssignment_Click,
  1105. Visibility.Visible);
  1106. return true;
  1107. }
  1108. return false;
  1109. }
  1110. public bool CreateEditMenu(ContextMenu menu, IAssignmentData args)
  1111. {
  1112. if (args.Model != null)
  1113. {
  1114. CreateMenu(menu, "EditAssignment", "Edit Assignment", args, EditAssignment_Click,
  1115. Visibility.Visible);
  1116. return true;
  1117. }
  1118. return false;
  1119. }
  1120. public bool CreateDeleteMenu(ContextMenu menu, IAssignmentData args)
  1121. {
  1122. if (args.Model != null)
  1123. {
  1124. CreateMenu(menu, "DeleteAssignment", "Delete Assignment", args, DeleteAssignment_Click,
  1125. Visibility.Visible);
  1126. return true;
  1127. }
  1128. return false;
  1129. }
  1130. public bool CreateZoomMenus(ContextMenu menu, IAssignmentData args)
  1131. {
  1132. CreateMenu(menu, "ZoomIn", "Zoom In", args, ZoomIn_Click, Visibility.Visible);
  1133. CreateMenu(menu, "ZoomOut", "Zoom Out", args, ZoomOut_Click, Visibility.Visible);
  1134. CreateMenu(menu, "ZoomReset", "Reset Zoom", args, ZoomReset_Click, Visibility.Visible);
  1135. return true;
  1136. }
  1137. private void EditAssignment(Assignment ass)
  1138. {
  1139. if (_assignmentgrid == null)
  1140. _assignmentgrid = new AssignmentGrid();
  1141. if (_assignmentgrid.EditItems(new[] { ass }))
  1142. {
  1143. AssignmentChanged?.Invoke(this, ass);
  1144. Refresh();
  1145. }
  1146. }
  1147. private void CreateAssignment_Click(object sender, RoutedEventArgs e)
  1148. {
  1149. var data = (sender as MenuItem).Tag as IAssignmentData;
  1150. if (data != null)
  1151. {
  1152. var ass = new Assignment();
  1153. ass.Date = data.Time.Date;
  1154. ass.Start = data.Time.TimeOfDay;
  1155. ass.Duration = new TimeSpan(1, 0, 0);
  1156. ass.EmployeeLink.ID = data.EmployeeID;
  1157. EditAssignment(ass);
  1158. }
  1159. else
  1160. {
  1161. MessageBox.Show("Please select an employee first!");
  1162. }
  1163. }
  1164. private void EditAssignment_Click(object sender, RoutedEventArgs e)
  1165. {
  1166. var data = (sender as MenuItem).Tag as IAssignmentData;
  1167. Assignment ass = null;
  1168. using (new WaitCursor())
  1169. {
  1170. ass = new Client<Assignment>().Load(new Filter<Assignment>(x => x.ID).IsEqualTo(data.Model.AssignmentID))
  1171. .FirstOrDefault();
  1172. }
  1173. if (ass != null)
  1174. EditAssignment(ass);
  1175. else
  1176. MessageBox.Show("Cannot Load Assignment!");
  1177. }
  1178. private void DeleteAssignment_Click(object sender, RoutedEventArgs e)
  1179. {
  1180. var data = (sender as MenuItem).Tag as IAssignmentData;
  1181. if ((data == null) || (data.Model == null))
  1182. {
  1183. MessageBox.Show("No Assignment to Delete");
  1184. return;
  1185. }
  1186. if (MessageBox.Show("Are you sure you wish to delete this assignment?", "Confirm Delete", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
  1187. {
  1188. Assignment ass = new Assignment() { ID = data.Model.AssignmentID};
  1189. using (new WaitCursor())
  1190. new Client<Assignment>().Delete(ass, "Assignment Deleted from Scheduler");
  1191. AssignmentChanged?.Invoke(this, ass);
  1192. Refresh();
  1193. }
  1194. }
  1195. private void ZoomIn_Click(object sender, RoutedEventArgs e)
  1196. {
  1197. Zoom *= 1.25F;
  1198. }
  1199. private void ZoomOut_Click(object sender, RoutedEventArgs e)
  1200. {
  1201. Zoom /= 1.25F;
  1202. }
  1203. private void ZoomReset_Click(object sender, RoutedEventArgs e)
  1204. {
  1205. Zoom = 100.0F;
  1206. }
  1207. #endregion
  1208. private void Bookings_PreviewKeyDown(object sender, KeyEventArgs e)
  1209. {
  1210. e.Handled = e.Key == Key.Delete;
  1211. }
  1212. }
  1213. }