AssignmentView2.xaml.cs 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371
  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. Bookings.DaysViewSettings.TimeInterval = IntervalToTimeSpan(TimeInterval);
  398. }
  399. catch (Exception e)
  400. {
  401. // If the view is invisible, setting the time interval throws an exeception (internal scroll viewer is still set to null)
  402. // So we only want to log an error if the view is actually visible
  403. if (Bookings.IsVisible)
  404. Logger.Send(LogType.Error, "", String.Format("Unable to update TimeInterval!\n{0}\n\n{1}", e.Message, e.StackTrace));
  405. }
  406. }
  407. private void UpdateCanShowHideSideBar()
  408. {
  409. ShowSideBar.Visibility = CanShowHideSideBar && !SideBarOpen
  410. ? Visibility.Visible
  411. : Visibility.Collapsed;
  412. HideSideBar.Visibility = CanShowHideSideBar && SideBarOpen
  413. ? Visibility.Visible
  414. : Visibility.Collapsed;
  415. }
  416. private void UpdateDateVisible()
  417. {
  418. DateRow.Height = DateVisible
  419. ? new GridLength(35, GridUnitType.Pixel)
  420. : new GridLength(0, GridUnitType.Pixel);
  421. }
  422. private void UpdateSideBarOpen()
  423. {
  424. SideBar.Width = SideBarOpen
  425. ? new GridLength(200, GridUnitType.Pixel)
  426. : new GridLength(0, GridUnitType.Pixel);
  427. DateBorder.BorderThickness = SideBarOpen
  428. ? new Thickness(0.75, 0.75, 0, 0.75)
  429. : new Thickness(0.75, 0.75, 0.75, 0.75);
  430. UpdateCanShowHideSideBar();
  431. }
  432. private void UpdateZoom()
  433. {
  434. ResizeIntervals(Bookings.ActualHeight);
  435. }
  436. private void UpdateSelectedDate()
  437. {
  438. CurrentDate.Text = string.Format("{0:ddd, dd MMMM yyyy}", SelectedDate);
  439. Bookings.SelectedDate = _selecteddate.Date;
  440. var margin = IntervalToTimeSpan(TimeInterval);
  441. var start = new TimeSpan(StartHour, 0, 0);
  442. if (start >= margin)
  443. start -= margin;
  444. Bookings.DisplayDate = _selecteddate.Add(start);
  445. }
  446. public void SetDisplayWindow(int start, int end)
  447. {
  448. if (!double.IsNaN(ActualHeight))
  449. {
  450. ResizeIntervals(ActualHeight);
  451. SelectedDate = SelectedDate; // to trigger a reset?
  452. }
  453. }
  454. private void LoadEmployees()
  455. {
  456. var emps = new Dictionary<Guid, string>();
  457. foreach (var row in _employees.Rows.Where(r =>
  458. r.Get<EmployeeTeam, Guid>(c => c.TeamLink.ID).Equals(SelectedTeam) || SelectedTeam.Equals(CoreUtils.FullGuid)))
  459. emps[row.Get<EmployeeTeam, Guid>(c => c.EmployeeLink.ID)] = row.Get<EmployeeTeam, string>(c => c.EmployeeLink.Name);
  460. Employees.ItemsSource = emps;
  461. }
  462. private void UpdateSelectedEmployees()
  463. {
  464. List<SchedulerResource> resources = new List<SchedulerResource>();
  465. Employees.SelectedItems.Clear();
  466. foreach (var item in Employees.Items)
  467. {
  468. var emp = (KeyValuePair<Guid, string>)item;
  469. if (SelectedEmployees.Contains(emp.Key))
  470. {
  471. Employees.SelectedItems.Add(item);
  472. resources.Add(
  473. new SchedulerResource
  474. {
  475. Name = emp.Value,
  476. Id = emp.Key.ToString()
  477. }
  478. );
  479. }
  480. }
  481. Bookings.ResourceCollection = new ObservableCollection<object>(resources);
  482. Bookings.DaysViewSettings.ResourceHeaderSize = resources.Count <= 1 ? 0 : 50;
  483. }
  484. #endregion
  485. public Assignment FindAssignment(Guid id)
  486. {
  487. return _assignments.Rows.FirstOrDefault(r => r.Get<Assignment, Guid>(c => c.ID).Equals(id))?.ToObject<Assignment>();
  488. }
  489. private IAssignmentViewModel FindModel(Guid id)
  490. {
  491. var appointments = Bookings.ItemsSource as ScheduleAppointmentCollection;
  492. return appointments.FirstOrDefault(x => (x as IAssignmentViewModel).AssignmentID.Equals(id)) as IAssignmentViewModel;
  493. }
  494. public void AddAssignment(Assignment assignment)
  495. {
  496. var row = _assignments.NewRow();
  497. _assignments.LoadRow(row, assignment);
  498. _assignments.Rows.Add(row);
  499. LoadModels(assignment.ID);
  500. }
  501. public void GetWindow(TimeSpan time, ref TimeSpan start, ref TimeSpan finish)
  502. {
  503. foreach (var row in _assignments.Rows)
  504. {
  505. var curstart = row.Get<Assignment, TimeSpan>(x => x.Start);
  506. var curfinish = row.Get<Assignment, TimeSpan>(x => x.Finish);
  507. if ((curfinish <= time) && (curfinish >= start))
  508. start = curfinish;
  509. if ((curstart >= time) && (curstart <= finish))
  510. finish = curstart;
  511. }
  512. }
  513. public CoreTable Data() => _assignments;
  514. public void Setup()
  515. {
  516. _employees = new Client<EmployeeTeam>().Query(
  517. null,
  518. new Columns<EmployeeTeam>(
  519. x => x.TeamLink.ID,
  520. x => x.TeamLink.Code,
  521. x => x.TeamLink.Name,
  522. x => x.EmployeeLink.ID,
  523. x => x.EmployeeLink.Name
  524. ),
  525. new SortOrder<EmployeeTeam>(x => x.TeamLink.Code).ThenBy(x => x.EmployeeLink.Name)
  526. );
  527. _employees.IntoDictionary<EmployeeTeam, Guid, String>(
  528. _teams,
  529. x => x.TeamLink.ID,
  530. r => r.Get<EmployeeTeam,String>(c=>c.TeamLink.Name)
  531. );
  532. Teams.ItemsSource = _teams;
  533. bReady = true;
  534. }
  535. private void ResizeIntervals(double height)
  536. {
  537. if (double.IsNaN(height) || height == 0.0F)
  538. return;
  539. var zoomedheight = height * (Zoom / 100.0F);
  540. Bookings.DaysViewSettings.TimeIntervalSize = zoomedheight / 24;
  541. }
  542. private void Bookings_SizeChanged(object sender, SizeChangedEventArgs e)
  543. {
  544. ResizeIntervals(e.NewSize.Height);
  545. }
  546. public void Refresh()
  547. {
  548. var filter = new Filter<Assignment>(x => x.Date).IsGreaterThanOrEqualTo(SelectedDate.Date)
  549. .And(x => x.Date).IsLessThanOrEqualTo(SelectedDate.Date.AddDays(1))
  550. .And(x =>x.EmployeeLink.ID).InList(SelectedEmployees);
  551. _assignments = new Client<Assignment>().Query(
  552. filter,
  553. new Columns<Assignment>(
  554. x => x.ID,
  555. x => x.Title,
  556. x => x.ActivityLink.ID,
  557. x => x.ActivityLink.Color,
  558. x => x.ActivityLink.Description,
  559. x => x.ActivityLink.Deleted,
  560. x => x.JobLink.ID,
  561. x => x.JobLink.Name,
  562. x => x.JobLink.JobNumber,
  563. x => x.JobLink.Deleted,
  564. x => x.ITP.ID,
  565. x => x.ITP.Code,
  566. x => x.ITP.Description,
  567. x => x.ITP.Deleted,
  568. x => x.Number,
  569. x => x.Description,
  570. x => x.Date,
  571. x => x.Start,
  572. x => x.Duration,
  573. x => x.Finish,
  574. x => x.LeaveRequestLink.ID,
  575. x => x.Completed,
  576. x => x.Delivery.ID,
  577. x => x.Delivery.Notes,
  578. x => x.Delivery.Deleted,
  579. x => x.TimeSheetLink.ID,
  580. x => x.TimeSheetLink.Deleted,
  581. x => x.EmployeeLink.ID,
  582. x => x.Task.ID,
  583. x => x.Task.Number
  584. )
  585. );
  586. CustomiseAssignments?.Invoke(this, _assignments);
  587. LoadModels(Guid.Empty);
  588. }
  589. private void LoadModels(Guid id)
  590. {
  591. IAssignmentViewModel selected = null;
  592. var appointments = new ScheduleAppointmentCollection();
  593. foreach (var row in _assignments.Rows)
  594. {
  595. var assignment = row.ToObject<Assignment>();
  596. var sColor = assignment.ActivityLink.Color;
  597. var bgColor = string.IsNullOrWhiteSpace(sColor) ? Colors.White : (Color)ColorConverter.ConvertFromString(sColor);
  598. var jobdesc = new List<string>();
  599. var itask = assignment.Task.Number;
  600. if (itask > 0)
  601. jobdesc.Add(string.Format("Task #{0}", itask));
  602. if (assignment.JobLink.IsValid())
  603. {
  604. var job = assignment.JobLink.JobNumber;
  605. if (assignment.ITP.IsValid())
  606. job = string.Format("{0} {1}", job, assignment.ITP.Code);
  607. job = string.Format("({0})", job);
  608. jobdesc.Add(job);
  609. }
  610. var date = assignment.Date;
  611. var sNote = assignment.Description + (assignment.Delivery.IsValid()
  612. ? "\n" + assignment.Delivery.Notes
  613. : "");
  614. var model = new AssignmentViewModel
  615. {
  616. Subject = string.Format("{0}", assignment.Title?.Trim()),
  617. JobNumber = string.Format(" {0} ", string.Join(" ", jobdesc)),
  618. Number = assignment.Number,
  619. Notes = sNote.Trim(),
  620. StartTime = date.Add(assignment.Start),
  621. EndTime = date.Add(assignment.Finish),
  622. AssignmentID = assignment.ID,
  623. EmployeeID = assignment.EmployeeLink.ID,
  624. //AllDay = false,
  625. AppointmentForeground = new SolidColorBrush(Colors.Black),
  626. AppointmentBackground = new SolidColorBrush(bgColor),
  627. Locked = assignment.LeaveRequestLink.IsValid() ? locked : null,
  628. Completed = !assignment.LeaveRequestLink.IsValid() && !assignment.Completed.IsEmpty() ? tick : null,
  629. HasDelivery = !assignment.LeaveRequestLink.IsValid() && assignment.Delivery.IsValid() ? box : null,
  630. TimeSheet = assignment.TimeSheetLink.IsValid() ? timesheet : null,
  631. ResourceIdCollection = new ObservableCollection<object>() { assignment.EmployeeLink.ID.ToString() }
  632. };
  633. appointments.Add(model);
  634. if (model.AssignmentID == id)
  635. selected = model;
  636. }
  637. Bookings.ItemsSource = appointments;
  638. ResizeIntervals(Bookings.ActualHeight);
  639. UpdateWorkingHourColors();
  640. }
  641. public void UpdateAssignment(Assignment assignment)
  642. {
  643. var row = _assignments.Rows.FirstOrDefault(r => r.Get<Assignment, Guid>(x => x.ID).Equals(assignment.ID));
  644. _assignments.LoadRow(row, assignment);
  645. var model = FindModel(assignment.ID);
  646. var sColor = assignment.ActivityLink.Color;
  647. var bgColor = string.IsNullOrWhiteSpace(sColor) ? Colors.White : (Color)ColorConverter.ConvertFromString(sColor);
  648. var date = assignment.Date;
  649. var leaveid = assignment.LeaveRequestLink.ID;
  650. var job = "";
  651. if (assignment.JobLink.IsValid())
  652. {
  653. job = assignment.JobLink.JobNumber;
  654. if (assignment.ITP.IsValid())
  655. job = string.Format("{0} {1}", job, assignment.ITP.Code);
  656. job = string.Format(" ({0}) ", job);
  657. }
  658. model.Subject = assignment.Title;
  659. model.Number = assignment.Number;
  660. model.JobNumber = job;
  661. model.Notes = assignment.Description;
  662. model.StartTime = date.Add(assignment.Start);
  663. model.EndTime = date.Add(assignment.Finish);
  664. model.AppointmentBackground = new SolidColorBrush(bgColor);
  665. model.Locked = assignment.LeaveRequestLink.IsValid() ? locked : null;
  666. model.Completed = !assignment.LeaveRequestLink.IsValid() && !assignment.Completed.IsEmpty() ? tick : null;
  667. model.HasDelivery = !assignment.LeaveRequestLink.IsValid() && assignment.Delivery.IsValid() ? box : null;
  668. model.TimeSheet = assignment.TimeSheetLink.IsValid() ? timesheet : null;
  669. //Bookings.UpdateLayout();
  670. }
  671. #region Responding to UI Events
  672. private void PrevMonth_Click(object sender, RoutedEventArgs e)
  673. {
  674. SelectedDate = SelectedDate.AddDays(-7);
  675. AssignmentSelectionChanged?.Invoke(this, null);
  676. Refresh();
  677. }
  678. private void PrevDay_Click(object sender, RoutedEventArgs e)
  679. {
  680. SelectedDate = SelectedDate.AddDays(-1);
  681. AssignmentSelectionChanged?.Invoke(this, null);
  682. Refresh();
  683. }
  684. private void CurrentDate_MouseDoubleClick(object sender, MouseButtonEventArgs e)
  685. {
  686. SelectedDate = DateTime.Today;
  687. AssignmentSelectionChanged?.Invoke(this, null);
  688. Refresh();
  689. }
  690. private void NextDay_Click(object sender, RoutedEventArgs e)
  691. {
  692. SelectedDate = SelectedDate.AddDays(1);
  693. AssignmentSelectionChanged?.Invoke(this, null);
  694. Refresh();
  695. }
  696. private void NextMonth_Click(object sender, RoutedEventArgs e)
  697. {
  698. SelectedDate = SelectedDate.AddDays(7);
  699. AssignmentSelectionChanged?.Invoke(this, null);
  700. Refresh();
  701. }
  702. private void Teams_SelectionChanged(object sender, SelectionChangedEventArgs e)
  703. {
  704. if (_updatingUI)
  705. return;
  706. SelectedTeam = (Guid)Teams.SelectedValue;
  707. SelectedEmployees = _employees.Rows
  708. .Where(r => (SelectedTeam == CoreUtils.FullGuid) || (r.Get<EmployeeTeam, Guid>(c => c.TeamLink.ID) == SelectedTeam))
  709. .Select(r => r.Get<EmployeeTeam, Guid>(c => c.EmployeeLink.ID))
  710. .Distinct()
  711. .ToArray();
  712. Refresh();
  713. }
  714. private void Employees_SelectionChanged(object sender, SelectionChangedEventArgs e)
  715. {
  716. if (_updatingUI)
  717. return;
  718. SelectedEmployees = Employees.SelectedItems.Select(x => ((KeyValuePair<Guid, String>)x).Key).ToArray();
  719. Refresh();
  720. }
  721. private void StartTime_OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  722. {
  723. if (_updatingUI)
  724. return;
  725. StartHour = (int)StartTime.Value.Value.TotalHours;
  726. }
  727. private void EndTime_OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  728. {
  729. if (_updatingUI)
  730. return;
  731. EndHour = (int)EndTime.Value.Value.TotalHours;
  732. }
  733. private void OpenSideBar_Click(object sender, RoutedEventArgs e)
  734. {
  735. SideBarOpen = true;
  736. }
  737. private void CloseSideBar_Click(object sender, RoutedEventArgs e)
  738. {
  739. SideBarOpen = false;
  740. }
  741. #endregion
  742. private void Schedule_AppointmentEditorOpening(object sender, AppointmentEditorOpeningEventArgs e)
  743. {
  744. if (e.Appointment != null)
  745. {
  746. var model = (AssignmentViewModel)e.Appointment;
  747. Assignment ass = null;
  748. using (new WaitCursor())
  749. {
  750. ass = new Client<Assignment>().Load(new Filter<Assignment>(x => x.ID).IsEqualTo(model.AssignmentID))
  751. .FirstOrDefault();
  752. }
  753. if (ass != null)
  754. EditAssignment(ass);
  755. else
  756. MessageBox.Show("Cannot Load Assignment!");
  757. }
  758. else
  759. {
  760. var res = e.Resource;
  761. if (res != null)
  762. {
  763. var ass = new Assignment();
  764. ass.EmployeeLink.ID = Guid.Parse(res.Id.ToString());
  765. ass.Date = e.DateTime;
  766. ass.Duration = new TimeSpan(1, 0, 0);
  767. var ag = new DynamicDataGrid<Assignment>();
  768. if (ag.EditItems(new[] { ass }))
  769. Refresh();
  770. }
  771. else
  772. {
  773. MessageBox.Show("No Employee Selected!");
  774. }
  775. }
  776. e.Cancel = true;
  777. }
  778. // private void Schedule_AppointmentStartDragging(object sender, AppointmentStartDraggingEventArgs e)
  779. // {
  780. // var model = e.Appointment as AssignmentViewModel;
  781. // if (model == null || model.Locked != null || model.TimeSheet != null)
  782. // e.Cancel = true;
  783. // }
  784. //
  785. // private void Schedule_AppointmentEndDragging(object sender, AppointmentEndDraggingEventArgs e)
  786. // {
  787. // var model = (AssignmentViewModel)e.Appointment;
  788. //
  789. // var row = model != null ? Assignments.Rows.FirstOrDefault(r => r.Get<Assignment, Guid>(x => x.ID).Equals(model.AssignmentID)) : null;
  790. // if (row != null)
  791. // {
  792. // Assignment ass = null;
  793. // using (new WaitCursor())
  794. // {
  795. // ass = new Client<Assignment>().Load(new Filter<Assignment>(x => x.ID).IsEqualTo(model.AssignmentID)).FirstOrDefault();
  796. // }
  797. //
  798. // if (ass != null)
  799. // {
  800. // var resource = e.Resources.FirstOrDefault() as Resource;
  801. // var employeeid = Guid.Parse(resource.ResourceName);
  802. // ass.EmployeeLink.ID = employeeid;
  803. //
  804. // var newtime = e.To.TimeOfDay;
  805. // if (e.To.Minute >= 45)
  806. // newtime = new TimeSpan(e.To.Hour, 45, 0);
  807. // else if (e.To.Minute >= 30)
  808. // newtime = new TimeSpan(e.To.Hour, 30, 0);
  809. // else if (e.To.Minute >= 15)
  810. // newtime = new TimeSpan(e.To.Hour, 15, 0);
  811. // else
  812. // newtime = new TimeSpan(e.To.Hour, 0, 0);
  813. // ass.Date = e.To.Date;
  814. // ass.Start = newtime;
  815. //
  816. // using (new WaitCursor())
  817. // {
  818. // new Client<Assignment>().Save(ass, "Dragged by User", (obj, args) => { });
  819. // }
  820. //
  821. // AssignmentChanged?.Invoke(this, ass);
  822. //
  823. // Refresh();
  824. //
  825. // e.Cancel = true;
  826. // }
  827. // else
  828. // {
  829. // MessageBox.Show("Unable to load Assigmment!");
  830. // }
  831. // }
  832. // else
  833. // {
  834. // MessageBox.Show("Unable to locate Assignment!");
  835. // }
  836. // }
  837. //
  838. // private void Schedule_AppointmentEndResizing(object sender, AppointmentEndResizingEventArgs e)
  839. // {
  840. // var model = (AssignmentViewModel)e.Appointment;
  841. // var row = model != null ? Assignments.Rows.FirstOrDefault(r => r.Get<Assignment, Guid>(x => x.ID).Equals(model.AssignmentID)) : null;
  842. // if (row != null)
  843. // {
  844. // Assignment ass = null;
  845. // using (new WaitCursor())
  846. // {
  847. // ass = new Client<Assignment>().Load(new Filter<Assignment>(x => x.ID).IsEqualTo(model.AssignmentID)).FirstOrDefault();
  848. // }
  849. //
  850. // if (ass != null)
  851. // {
  852. // var newtime = e.To;
  853. // if (e.To.Minute >= 45)
  854. // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 45, 0);
  855. // else if (e.To.Minute >= 30)
  856. // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 30, 0);
  857. // else if (e.To.Minute >= 15)
  858. // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 15, 0);
  859. // else
  860. // newtime = new DateTime(e.To.Year, e.To.Month, e.To.Day, e.To.Hour, 0, 0);
  861. // ass.Date = newtime;
  862. // using (new WaitCursor())
  863. // {
  864. // new Client<Assignment>().Save(ass, "Dragged by User", (obj, args) => { });
  865. // }
  866. //
  867. // AssignmentChanged?.Invoke(this, ass);
  868. //
  869. // Refresh();
  870. // e.Cancel = true;
  871. // }
  872. // else
  873. // {
  874. // MessageBox.Show("Unable to load Assigmment!");
  875. // }
  876. // }
  877. // else
  878. // {
  879. // MessageBox.Show("Unable to locate Assignment!");
  880. // }
  881. // }
  882. //
  883. // private AssignmentViewTimeInterval TimeSpanToInterval(TimeSpan time)
  884. // {
  885. // if (time <= new TimeSpan(0, 5, 0))
  886. // return AssignmentViewTimeInterval.FiveMinutes;
  887. // if (time <= new TimeSpan(0, 6, 0))
  888. // return AssignmentViewTimeInterval.SixMinutes;
  889. // if (time <= new TimeSpan(0, 10, 0))
  890. // return AssignmentViewTimeInterval.TenMinutes;
  891. // if (time <= new TimeSpan(0, 15, 0))
  892. // return AssignmentViewTimeInterval.FifteenMinutes;
  893. // if (time <= new TimeSpan(0, 20, 0))
  894. // return AssignmentViewTimeInterval.TwentyMinutes;
  895. // if (time <= new TimeSpan(0, 30, 0))
  896. // return AssignmentViewTimeInterval.ThirtyMinutes;
  897. // return AssignmentViewTimeInterval.SixyMinutes;
  898. // }
  899. private TimeSpan IntervalToTimeSpan(AssignmentViewTimeInterval interval)
  900. {
  901. switch (interval)
  902. {
  903. case AssignmentViewTimeInterval.FiveMinutes:
  904. return new TimeSpan(0, 5, 0);
  905. case AssignmentViewTimeInterval.SixMinutes:
  906. return new TimeSpan(0, 6, 0);
  907. case AssignmentViewTimeInterval.TenMinutes:
  908. return new TimeSpan(0, 10, 0);
  909. case AssignmentViewTimeInterval.FifteenMinutes:
  910. return new TimeSpan(0, 15, 0);
  911. case AssignmentViewTimeInterval.TwentyMinutes:
  912. return new TimeSpan(0, 20, 0);
  913. case AssignmentViewTimeInterval.ThirtyMinutes:
  914. return new TimeSpan(0, 30, 0);
  915. default:
  916. return new TimeSpan(1, 0, 0);
  917. }
  918. }
  919. // private int GetDivider(AssignmentViewTimeInterval interval)
  920. // {
  921. // switch (interval)
  922. // {
  923. // case AssignmentViewTimeInterval.FiveMinutes:
  924. // return 12;
  925. // case AssignmentViewTimeInterval.SixMinutes:
  926. // return 10;
  927. // case AssignmentViewTimeInterval.TenMinutes:
  928. // return 6;
  929. // case AssignmentViewTimeInterval.FifteenMinutes:
  930. // return 4;
  931. // case AssignmentViewTimeInterval.TwentyMinutes:
  932. // return 3;
  933. // case AssignmentViewTimeInterval.ThirtyMinutes:
  934. // return 2;
  935. // default:
  936. // return 1;
  937. // }
  938. // }
  939. //
  940. // private TimeSpan GetTime(int row)
  941. // {
  942. // int divider = GetDivider(TimeInterval);
  943. // var hours = row / divider;
  944. // var mins = row % divider * (60 / divider);
  945. // return new TimeSpan(hours, mins, 0);
  946. // }
  947. // private TimeSpan GetTime(Point point)
  948. // {
  949. // var view = Bookings.FindVisualChildren<ScrollViewer>().LastOrDefault(x => x.Name.Equals("PART_ScrollViewer"));
  950. // var intervalheight = (Bookings.ActualHeight - 30.0F) / (24 * 4);
  951. // var row = (int)Math.Truncate((view.VerticalOffset + point.Y - 30.0F) / Bookings.DaysViewSettings.TimeIntervalSize);
  952. // var result = GetTime(row);
  953. // return result;
  954. // }
  955. // private void Bookings_Drop(object sender, DragEventArgs e)
  956. // {
  957. // if (e.Data.GetDataPresent("Comal.Classes.Delivery"))
  958. // {
  959. // var delivery = (e.Data.GetData("Comal.Classes.Delivery") as CoreRow[]).FirstOrDefault();
  960. // if (delivery == null)
  961. // return;
  962. //
  963. // var assignment = new Assignment();
  964. //
  965. // var resource = Bookings.ResourceCollection.OfType<SchedulerResource>().ToArray();
  966. // var colwidth = Bookings.ActualWidth / resource.Length;
  967. // var column = (int)Math.Truncate(e.GetPosition(Bookings).X / colwidth);
  968. // var employee = resource[column];
  969. //
  970. // assignment.EmployeeLink.ID = Guid.Parse(employee.Id.ToString());
  971. //
  972. // assignment.Date = SelectedDate.Date;
  973. //
  974. // //double intervalheight = (Bookings.ActualHeight - 30.0F) / (double)((Bookings.WorkEndHour - Bookings.WorkStartHour) * 4);
  975. // //int row = (int)Math.Truncate((e.GetPosition(Bookings).Y - 30.0F) / intervalheight);
  976. // //int hour = Bookings.WorkStartHour + (row / 4);
  977. // //int min = (row % 4) * 15;
  978. // //assignment.Start = new TimeSpan(hour, min, 0);
  979. // assignment.Start = GetTime(e.GetPosition(Bookings));
  980. //
  981. // assignment.Duration = new TimeSpan(2, 0, 0);
  982. //
  983. // assignment.JobLink.ID = delivery.Get<Delivery, Guid>(x => x.Job.ID);
  984. //
  985. // assignment.Description = string.Format("Delivery Docket #{0}", delivery.Get<Delivery, int>(x => x.Number));
  986. //
  987. // using (new WaitCursor())
  988. // {
  989. // new Client<Assignment>().Save(assignment, "Created for Delivery");
  990. // var del = new Client<Delivery>().Load(new Filter<Delivery>(x => x.ID).IsEqualTo(delivery.Get<Delivery, Guid>(x => x.ID)))
  991. // .FirstOrDefault();
  992. // del.Assignment.ID = assignment.ID;
  993. // new Client<Delivery>().Save(del, "Booked via Scheduler");
  994. // }
  995. //
  996. // AssignmentChanged?.Invoke(this, assignment);
  997. //
  998. // Refresh();
  999. //
  1000. // AssignmentSelectionChanged?.Invoke(this, assignment);
  1001. // }
  1002. // else if (e.Data.GetDataPresent("Comal.Classes.Kanban"))
  1003. // {
  1004. // var kanban = e.Data.GetData("Comal.Classes.Kanban") as Kanban;
  1005. // if (kanban == null)
  1006. // return;
  1007. //
  1008. // var assignment = new Assignment();
  1009. //
  1010. // var resources = Bookings.ResourceCollection.OfType<SchedulerResource>().ToArray();
  1011. // var colwidth = Bookings.ActualWidth / resources.Length;
  1012. // var column = (int)Math.Truncate(e.GetPosition(Bookings).X / colwidth);
  1013. // var employee = resources[column];
  1014. //
  1015. // assignment.EmployeeLink.ID = Guid.Parse(employee.Id.ToString());
  1016. //
  1017. // assignment.Date = SelectedDate.Date;
  1018. //
  1019. // var view = Bookings.FindVisualChildren<ScrollViewer>().FirstOrDefault(x => x.Name.Equals("Scrollviewer1"));
  1020. // var intervalheight = (Bookings.ActualHeight - 30.0F) / (24 * 4);
  1021. // var row = (int)Math.Truncate((view.VerticalOffset + e.GetPosition(Bookings).Y - 30.0F) / Bookings.DaysViewSettings.TimeIntervalSize);
  1022. // assignment.Start = GetTime(row);
  1023. //
  1024. // assignment.Duration = new TimeSpan(0, 30, 0);
  1025. //
  1026. // assignment.JobLink.ID = kanban.JobLink.ID;
  1027. // assignment.Task.ID = kanban.ID;
  1028. //
  1029. // assignment.Title = kanban.Title;
  1030. //
  1031. // AssignmentChanged?.Invoke(this, assignment);
  1032. //
  1033. // Refresh();
  1034. //
  1035. // AssignmentSelectionChanged?.Invoke(this, assignment);
  1036. // }
  1037. // }
  1038. private void Bookings_OnAppointmentTapped(object? sender, AppointmentTappedArgs e)
  1039. {
  1040. var model = e.Appointment as IAssignmentViewModel;
  1041. if (model != null)
  1042. {
  1043. var ass = FindAssignment(model.AssignmentID);
  1044. if (
  1045. ((ass == null) && (_selectedassignment != null))
  1046. || ((ass != null) && (ass.ID != _selectedassignment))
  1047. )
  1048. {
  1049. _selectedassignment = ass != null ? ass.ID : Guid.Empty;
  1050. AssignmentSelectionChanged?.Invoke(this, ass);
  1051. }
  1052. }
  1053. else
  1054. {
  1055. if (_selectedassignment != Guid.Empty)
  1056. {
  1057. _selectedassignment = Guid.Empty;
  1058. AssignmentSelectionChanged?.Invoke(this, null);
  1059. }
  1060. }
  1061. }
  1062. #region Context Menu Handling
  1063. private void Bookings_OnSchedulerContextMenuOpening(object? sender, SchedulerContextMenuOpeningEventArgs e)
  1064. {
  1065. IAssignmentData args = null;
  1066. e.ContextMenu.Items.Clear();
  1067. if (e.MenuType == SchedulerContextMenuType.Appointment)
  1068. {
  1069. var model = e.MenuInfo.Appointment as IAssignmentViewModel;
  1070. args = new AssignmentData(model, Guid.Empty, DateTime.MinValue);
  1071. CreateEditMenu(e.ContextMenu, args);
  1072. e.ContextMenu.Items.Add(new Separator());
  1073. CreateDeleteMenu(e.ContextMenu, args);
  1074. e.ContextMenu.Items.Add(new Separator());
  1075. }
  1076. else if (e.MenuType == SchedulerContextMenuType.TimeSlotCell)
  1077. {
  1078. if (Guid.TryParse(e.MenuInfo.Resource.Id?.ToString(), out Guid employeeid))
  1079. {
  1080. args = new AssignmentData(null, employeeid, e.MenuInfo.DateTime.Value);
  1081. CreateAddMenu(e.ContextMenu, args);
  1082. e.ContextMenu.Items.Add(new Separator());
  1083. }
  1084. }
  1085. CreateZoomMenus(e.ContextMenu, args);
  1086. CustomiseContextMenu?.Invoke(e.ContextMenu, args);
  1087. }
  1088. private void CreateMenu(ContextMenu menu, string name, string header, IAssignmentData args, RoutedEventHandler action,
  1089. Visibility visibility)
  1090. {
  1091. var item = new MenuItem();
  1092. item.Name = name;
  1093. item.Header = header;
  1094. item.Click += action;
  1095. item.Visibility = visibility;
  1096. item.Tag = args;
  1097. menu.Items.Add(item);
  1098. }
  1099. public bool CreateAddMenu(ContextMenu menu, IAssignmentData args)
  1100. {
  1101. if (args.Model == null)
  1102. {
  1103. CreateMenu(menu, "CreateAssignment", "Create Assignment", args, CreateAssignment_Click,
  1104. Visibility.Visible);
  1105. return true;
  1106. }
  1107. return false;
  1108. }
  1109. public bool CreateEditMenu(ContextMenu menu, IAssignmentData args)
  1110. {
  1111. if (args.Model != null)
  1112. {
  1113. CreateMenu(menu, "EditAssignment", "Edit Assignment", args, EditAssignment_Click,
  1114. Visibility.Visible);
  1115. return true;
  1116. }
  1117. return false;
  1118. }
  1119. public bool CreateDeleteMenu(ContextMenu menu, IAssignmentData args)
  1120. {
  1121. if (args.Model != null)
  1122. {
  1123. CreateMenu(menu, "DeleteAssignment", "Delete Assignment", args, DeleteAssignment_Click,
  1124. Visibility.Visible);
  1125. return true;
  1126. }
  1127. return false;
  1128. }
  1129. public bool CreateZoomMenus(ContextMenu menu, IAssignmentData args)
  1130. {
  1131. CreateMenu(menu, "ZoomIn", "Zoom In", args, ZoomIn_Click, Visibility.Visible);
  1132. CreateMenu(menu, "ZoomOut", "Zoom Out", args, ZoomOut_Click, Visibility.Visible);
  1133. CreateMenu(menu, "ZoomReset", "Reset Zoom", args, ZoomReset_Click, Visibility.Visible);
  1134. return true;
  1135. }
  1136. private void EditAssignment(Assignment ass)
  1137. {
  1138. if (_assignmentgrid == null)
  1139. _assignmentgrid = new AssignmentGrid();
  1140. if (_assignmentgrid.EditItems(new[] { ass }))
  1141. {
  1142. AssignmentChanged?.Invoke(this, ass);
  1143. Refresh();
  1144. }
  1145. }
  1146. private void CreateAssignment_Click(object sender, RoutedEventArgs e)
  1147. {
  1148. var data = (sender as MenuItem).Tag as IAssignmentData;
  1149. if (data != null)
  1150. {
  1151. var ass = new Assignment();
  1152. ass.Date = data.Time.Date;
  1153. ass.Start = data.Time.TimeOfDay;
  1154. ass.Duration = new TimeSpan(1, 0, 0);
  1155. ass.EmployeeLink.ID = data.EmployeeID;
  1156. EditAssignment(ass);
  1157. }
  1158. else
  1159. {
  1160. MessageBox.Show("Please select an employee first!");
  1161. }
  1162. }
  1163. private void EditAssignment_Click(object sender, RoutedEventArgs e)
  1164. {
  1165. var data = (sender as MenuItem).Tag as IAssignmentData;
  1166. Assignment ass = null;
  1167. using (new WaitCursor())
  1168. {
  1169. ass = new Client<Assignment>().Load(new Filter<Assignment>(x => x.ID).IsEqualTo(data.Model.AssignmentID))
  1170. .FirstOrDefault();
  1171. }
  1172. if (ass != null)
  1173. EditAssignment(ass);
  1174. else
  1175. MessageBox.Show("Cannot Load Assignment!");
  1176. }
  1177. private void DeleteAssignment_Click(object sender, RoutedEventArgs e)
  1178. {
  1179. var data = (sender as MenuItem).Tag as IAssignmentData;
  1180. if ((data == null) || (data.Model == null))
  1181. {
  1182. MessageBox.Show("No Assignment to Delete");
  1183. return;
  1184. }
  1185. if (MessageBox.Show("Are you sure you wish to delete this assignment?", "Confirm Delete", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
  1186. {
  1187. Assignment ass = new Assignment() { ID = data.Model.AssignmentID};
  1188. using (new WaitCursor())
  1189. new Client<Assignment>().Delete(ass, "Assignment Deleted from Scheduler");
  1190. AssignmentChanged?.Invoke(this, ass);
  1191. Refresh();
  1192. }
  1193. }
  1194. private void ZoomIn_Click(object sender, RoutedEventArgs e)
  1195. {
  1196. Zoom *= 1.25F;
  1197. }
  1198. private void ZoomOut_Click(object sender, RoutedEventArgs e)
  1199. {
  1200. Zoom /= 1.25F;
  1201. }
  1202. private void ZoomReset_Click(object sender, RoutedEventArgs e)
  1203. {
  1204. Zoom = 100.0F;
  1205. }
  1206. #endregion
  1207. private void Bookings_PreviewKeyDown(object sender, KeyEventArgs e)
  1208. {
  1209. e.Handled = e.Key == Key.Delete;
  1210. }
  1211. }
  1212. }