TasksList.xaml.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.ComponentModel;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. using comal.timesheets.Tasks;
  8. using Comal.Classes;
  9. using InABox.Clients;
  10. using InABox.Configuration;
  11. using InABox.Core;
  12. using Xamarin.Forms;
  13. using Xamarin.Forms.Xaml;
  14. using XF.Material.Forms.UI;
  15. using XF.Material.Forms.UI.Dialogs;
  16. using System.Threading;
  17. namespace comal.timesheets
  18. {
  19. [XamlCompilation(XamlCompilationOptions.Compile)]
  20. public partial class TasksList : ContentPage
  21. {
  22. Color color = Color.FromHex("#15C7C1");
  23. List<KanbanSubscriberShell> kanbanSubscriberShells = new List<KanbanSubscriberShell>();
  24. List<KanbanSubscriberShell> searchList = new List<KanbanSubscriberShell>();
  25. int currentCategory = 0;
  26. bool searching = false;
  27. bool firstLoad = true;
  28. bool tapping = false;
  29. bool doubleTap = false;
  30. public TasksList()
  31. {
  32. InitializeComponent();
  33. LoadPreferences();
  34. }
  35. private void LoadPreferences()
  36. {
  37. try
  38. {
  39. if (!App.Current.Properties.ContainsKey("ObserverPreference"))
  40. {
  41. App.Current.Properties.Add("ObserverPreference", "True");
  42. observerSwitch.IsToggled = true;
  43. }
  44. else
  45. {
  46. observerSwitch.IsToggled = Convert.ToBoolean(App.Current.Properties["ObserverPreference"]);
  47. }
  48. if (!App.Current.Properties.ContainsKey("PromptedOnUsage"))
  49. {
  50. App.Current.Properties.Add("PromptedOnUsage", "True");
  51. DisplayAlert("One-time Prompt:", "Single Tap to Open Task," + System.Environment.NewLine + "Double Tap to Complete Task", "OK");
  52. }
  53. }
  54. catch { }
  55. }
  56. protected override void OnAppearing()
  57. {
  58. LoadData();
  59. base.OnAppearing();
  60. }
  61. private async void LoadData()
  62. {
  63. try
  64. {
  65. searchEnt.IsEnabled = false;
  66. await Task.Run(() =>
  67. {
  68. kanbanSubscriberShells.Clear();
  69. CoreTable table = new Client<KanbanSubscriber>().Query(
  70. new Filter<KanbanSubscriber>(x => x.Employee.ID).IsEqualTo(GlobalVariables.EmpID)
  71. .And(x => x.Kanban.Closed).IsEqualTo(DateTime.MinValue).And(x => x.Kanban.Category).IsNotEqualTo("Complete"),
  72. new Columns<KanbanSubscriber>
  73. (
  74. x => x.Kanban.ID, //0
  75. x => x.Kanban.Number, //1
  76. x => x.Kanban.DueDate, //2
  77. x => x.Kanban.Title, //3
  78. x => x.Kanban.Summary, //4
  79. x => x.Kanban.Category, //5
  80. x => x.Kanban.ManagerLink.Name, //6
  81. x => x.Kanban.Attachments, //7
  82. x => x.Manager, //8
  83. x => x.Assignee, //9
  84. x => x.Kanban.Locked //10
  85. ),
  86. new SortOrder<KanbanSubscriber>(x => x.Kanban.DueDate));
  87. string emptyString = "";
  88. foreach (CoreRow row in table.Rows)
  89. {
  90. List<object> list = row.Values;
  91. if (list[0] == null) { list[0] = Guid.Empty; } //0
  92. if (list[1] == null) { list[1] = emptyString; } //1
  93. if (list[2] == null) { list[2] = DateTime.MinValue; } //2
  94. if (list[3] == null) { list[3] = emptyString; } //3
  95. if (list[4] == null) { list[4] = emptyString; } //4
  96. if (list[5] == null) { list[5] = emptyString; } //5
  97. if (list[6] == null) { list[6] = emptyString; } //6
  98. if (list[7] == null) { list[7] = 0; } //7
  99. if (list[8] == null) { list[8] = false; } //8
  100. if (list[9] == null) { list[9] = false; } //9
  101. if (list[10] == null) { list[10] = false; } //10
  102. KanbanSubscriberShell kanbanSubscriberShell = new KanbanSubscriberShell();
  103. kanbanSubscriberShell.ID = Guid.Parse(list[0].ToString());
  104. kanbanSubscriberShell.Number = list[1].ToString();
  105. kanbanSubscriberShell.DueDate = DateTime.Parse(list[2].ToString());
  106. kanbanSubscriberShell.Title = list[3].ToString();
  107. kanbanSubscriberShell.Summary = list[4].ToString();
  108. kanbanSubscriberShell.Category = ChooseCategory(list[5].ToString());
  109. kanbanSubscriberShell.ManagerName = list[6].ToString();
  110. kanbanSubscriberShell.Attachments = int.Parse(list[7].ToString());
  111. bool manager = Convert.ToBoolean(list[8].ToString());
  112. bool assignee = Convert.ToBoolean(list[9].ToString());
  113. kanbanSubscriberShell.Locked = Convert.ToBoolean(list[10].ToString());
  114. kanbanSubscriberShell.Color = ChooseColour(manager, assignee, kanbanSubscriberShell.DueDate);
  115. if (kanbanSubscriberShell.Attachments != 0)
  116. {
  117. kanbanSubscriberShell.ImagePath = "paperclip.png";
  118. if (Device.RuntimePlatform.Equals(Device.iOS)) kanbanSubscriberShell.ImagePath = "attachments.png";
  119. }
  120. if (kanbanSubscriberShell.Color == Color.FromHex("#cb99c9"))
  121. {
  122. kanbanSubscriberShell.IsObserver = true;
  123. }
  124. kanbanSubscriberShells.Add(kanbanSubscriberShell);
  125. }
  126. if (searching) RunSearch();
  127. else
  128. {
  129. RefreshButtons(kanbanSubscriberShells);
  130. DisplayList(kanbanSubscriberShells);
  131. }
  132. firstLoad = false;
  133. });
  134. }
  135. catch (Exception ex)
  136. {
  137. var log = new MobileLogging(LogType.Query, "LoadData()", ex.Message + ex.StackTrace, this.GetType().Name);
  138. }
  139. }
  140. private List<KanbanSubscriberShell> removeObservers(List<KanbanSubscriberShell> list)
  141. {
  142. try
  143. {
  144. if (App.Current.Properties["ObserverPreference"].Equals("True"))
  145. {
  146. return list;
  147. }
  148. else
  149. {
  150. var sublist = list.Where(x => x.IsObserver == false);
  151. List<KanbanSubscriberShell> newList = new List<KanbanSubscriberShell>();
  152. foreach (KanbanSubscriberShell shell in sublist)
  153. {
  154. newList.Add(shell);
  155. }
  156. return newList;
  157. }
  158. }
  159. catch { return new List<KanbanSubscriberShell>(); }
  160. }
  161. private void DisplayList(List<KanbanSubscriberShell> list)
  162. {
  163. try
  164. {
  165. list = removeObservers(list);
  166. Device.BeginInvokeOnMainThread(() =>
  167. {
  168. switch (currentCategory)
  169. {
  170. case 0:
  171. taskListView.ItemsSource = list.Where(x => x.Category == "To Do");
  172. break;
  173. case 1:
  174. taskListView.ItemsSource = list.Where(x => x.Category == "Current");
  175. break;
  176. case 2:
  177. taskListView.ItemsSource = list.Where(x => x.Category == "Waiting");
  178. break;
  179. }
  180. searchEnt.IsEnabled = true;
  181. observerSwitch.IsEnabled = true;
  182. });
  183. }
  184. catch { }
  185. }
  186. private void RefreshButtons(List<KanbanSubscriberShell> list)
  187. {
  188. try
  189. {
  190. list = removeObservers(list);
  191. Device.BeginInvokeOnMainThread(() =>
  192. {
  193. if (String.Equals(Device.RuntimePlatform, Device.iOS))
  194. {
  195. buttonToDo.Text = String.Format("{0} ({1})", "To Do", list.Count(x => x.Category == "To Do"));
  196. buttonCurrent.Text = String.Format("{0} ({1})", "Current", list.Count(x => x.Category == "Current"));
  197. buttonWaiting.Text = String.Format("{0} ({1})", "Waiting", list.Count(x => x.Category == "Waiting"));
  198. }
  199. else
  200. {
  201. buttonToDo.Text = "To Do (" + list.Count(x => x.Category == "To Do") + ")";
  202. buttonCurrent.Text = "Current (" + list.Count(x => x.Category == "Current") + ")";
  203. buttonWaiting.Text = "Waiting (" + list.Count(x => x.Category == "Waiting") + ")";
  204. }
  205. });
  206. }
  207. catch { }
  208. }
  209. private string ChooseCategory(string _category)
  210. {
  211. switch (_category)
  212. {
  213. case "Open":
  214. _category = "To Do";
  215. break;
  216. case "In Progress":
  217. _category = "Current";
  218. break;
  219. default:
  220. break;
  221. }
  222. return _category;
  223. }
  224. private void AddTask_Clicked(object sender, EventArgs e)
  225. {
  226. try
  227. {
  228. AddEditTask addEditTask = new AddEditTask();
  229. Navigation.PushAsync(addEditTask);
  230. }
  231. catch { }
  232. }
  233. async void KanbanList_Tapped(object sender, EventArgs e)
  234. {
  235. try
  236. {
  237. if (tapping)
  238. {
  239. doubleTap = true;
  240. var selectedTask = taskListView.SelectedItem as KanbanSubscriberShell;
  241. if (selectedTask.Locked)
  242. {
  243. doubleTap = false;
  244. DisplayAlert("Alert", "Unable to complete locked task", "Cancel");
  245. return;
  246. }
  247. string chosenOption = await DisplayActionSheet("Complete Task?", "Cancel", null, "Yes", "No");
  248. switch (chosenOption)
  249. {
  250. case "Cancel":
  251. break;
  252. case "No":
  253. break;
  254. case "Yes":
  255. CompleteTask(selectedTask);
  256. break;
  257. default:
  258. break;
  259. }
  260. doubleTap = false;
  261. }
  262. else
  263. {
  264. tapping = true;
  265. Timer t = new Timer(TimerCallBack, null, 750, Timeout.Infinite);
  266. }
  267. }
  268. catch { }
  269. }
  270. private async void CompleteTask(KanbanSubscriberShell shell)
  271. {
  272. try
  273. {
  274. kanbanSubscriberShells.Remove(shell);
  275. RefreshButtons(kanbanSubscriberShells);
  276. DisplayList(kanbanSubscriberShells);
  277. await Task.Run(() =>
  278. {
  279. CoreTable table = new Client<Kanban>().Query
  280. (
  281. new Filter<Kanban>(x => x.ID).IsEqualTo(shell.ID),
  282. new Columns<Kanban>(x => x.ID, x => x.Category)
  283. );
  284. Kanban kanban = table.Rows.First().ToObject<Kanban>();
  285. kanban.Category = "Complete";
  286. new Client<Kanban>().Save(kanban, "Completed from mobile device");
  287. });
  288. }
  289. catch { }
  290. }
  291. private async void TimerCallBack(object o) //for single tap
  292. {
  293. try
  294. {
  295. tapping = false;
  296. if (!doubleTap)
  297. {
  298. var selectedTask = taskListView.SelectedItem as KanbanSubscriberShell;
  299. string loadingMessage = "Loading Task " + selectedTask.Number;
  300. if (selectedTask.Attachments != 0)
  301. {
  302. loadingMessage = loadingMessage + " with " + selectedTask.Attachments + " attached document(s). Please wait for photos to appear.";
  303. }
  304. Device.BeginInvokeOnMainThread(async () =>
  305. {
  306. using (await MaterialDialog.Instance.LoadingDialogAsync(message: loadingMessage))
  307. {
  308. Guid ID = selectedTask.ID;
  309. var form = new AddEditTask(ID);
  310. await Navigation.PushAsync(form);
  311. }
  312. });
  313. }
  314. }
  315. catch { }
  316. }
  317. private async void SearchEnt_Changed(object sender, EventArgs e)
  318. {
  319. if (!string.IsNullOrWhiteSpace(searchEnt.Text))
  320. {
  321. searching = true;
  322. RunSearch();
  323. }
  324. else
  325. {
  326. searching = false;
  327. RefreshButtons(kanbanSubscriberShells);
  328. DisplayList(kanbanSubscriberShells);
  329. }
  330. }
  331. private async void RunSearch()
  332. {
  333. try
  334. {
  335. await Task.Run(() =>
  336. {
  337. searchList.Clear();
  338. var list = kanbanSubscriberShells.Where(x =>
  339. x.Number.Contains(searchEnt.Text) ||
  340. x.ManagerName.Contains(searchEnt.Text) || x.ManagerName.Contains(UpperCaseFirst(searchEnt.Text)) ||
  341. x.Title.Contains(searchEnt.Text) || x.Title.Contains(searchEnt.Text.ToUpper()) || x.Title.Contains(searchEnt.Text.ToLower()) || x.Title.Contains(UpperCaseFirst(searchEnt.Text)) ||
  342. x.Summary.Contains(searchEnt.Text) || x.Summary.Contains(searchEnt.Text.ToUpper()) || x.Summary.Contains(searchEnt.Text.ToLower()) || x.Summary.Contains(UpperCaseFirst(searchEnt.Text)) ||
  343. x.DueDate.ToString().Contains(searchEnt.Text) || x.DueDate.ToString().Contains(searchEnt.Text.ToUpper()) || x.DueDate.ToString().Contains(searchEnt.Text.ToLower()) || x.DueDate.ToString().Contains(UpperCaseFirst(searchEnt.Text))
  344. );
  345. foreach (KanbanSubscriberShell shell in list)
  346. {
  347. searchList.Add(shell);
  348. }
  349. RefreshButtons(searchList);
  350. DisplayList(searchList);
  351. });
  352. }
  353. catch { }
  354. }
  355. static String UpperCaseFirst(string s)
  356. {
  357. char[] a = s.ToCharArray();
  358. a[0] = char.ToUpper(a[0]);
  359. return new string(a);
  360. }
  361. private Color ChooseColour(bool manager, bool employee, DateTime due)
  362. {
  363. Color color = Color.FromHex("#cb99c9"); //purple / pastel violet
  364. if (manager)
  365. {
  366. if (employee)
  367. {
  368. color = ColorOnDate(due);
  369. }
  370. else
  371. {
  372. color = Color.LightGray;
  373. }
  374. }
  375. else if (employee)
  376. {
  377. color = ColorOnDate(due);
  378. }
  379. return color;
  380. }
  381. private Color ColorOnDate(DateTime due)
  382. {
  383. Color color = Color.FromHex("#77dd77"); //green / pastel green
  384. int result = DateTime.Compare(DateTime.Now, due);
  385. if (result < 0) //relationship = "is earlier than";
  386. {
  387. int result2 = DateTime.Compare(DateTime.Today.AddDays(+7), due);
  388. if (result2 == 0 || result2 > 0)
  389. {
  390. color = Color.FromHex("#fff8dc"); //cornsilk / light yellow
  391. }
  392. }
  393. if (result > 0)//relationship = "is later than";
  394. {
  395. color = Color.FromHex("#f08080"); //light coral / red
  396. }
  397. if (due == DateTime.Today) //relationship = "is the same time as";
  398. {
  399. color = Color.FromHex("#fff8dc"); //cornsilk / light yellow
  400. }
  401. return color;
  402. }
  403. private void ButtonToDo_Clicked(object sender, EventArgs e)
  404. {
  405. currentCategory = 0;
  406. if (!searching)
  407. DisplayList(kanbanSubscriberShells);
  408. else
  409. {
  410. DisplayList(searchList);
  411. }
  412. ChangeButtonColour();
  413. }
  414. private void ButtonCurrent_Clicked(object sender, EventArgs e)
  415. {
  416. currentCategory = 1;
  417. if (!searching)
  418. DisplayList(kanbanSubscriberShells);
  419. else
  420. {
  421. DisplayList(searchList);
  422. }
  423. ChangeButtonColour();
  424. }
  425. private void ButtonWaiting_Clicked(object sender, EventArgs e)
  426. {
  427. currentCategory = 2;
  428. if (!searching)
  429. DisplayList(kanbanSubscriberShells);
  430. else
  431. {
  432. DisplayList(searchList);
  433. }
  434. ChangeButtonColour();
  435. }
  436. private void ChangeButtonColour()
  437. {
  438. switch (currentCategory)
  439. {
  440. case 0:
  441. buttonToDo.BackgroundColor = color;
  442. buttonCurrent.BackgroundColor = Color.Default;
  443. buttonWaiting.BackgroundColor = Color.Default;
  444. break;
  445. case 1:
  446. buttonToDo.BackgroundColor = Color.Default;
  447. buttonCurrent.BackgroundColor = color;
  448. buttonWaiting.BackgroundColor = Color.Default;
  449. break;
  450. case 2:
  451. buttonToDo.BackgroundColor = Color.Default;
  452. buttonCurrent.BackgroundColor = Color.Default;
  453. buttonWaiting.BackgroundColor = color;
  454. break;
  455. }
  456. }
  457. private void ObserverSwitch_Toggled(object sender, EventArgs e)
  458. {
  459. if (firstLoad)
  460. return;
  461. if (observerSwitch.IsToggled)
  462. {
  463. if (App.Current.Properties.ContainsKey("ObserverPreference"))
  464. {
  465. App.Current.Properties["ObserverPreference"] = "True";
  466. }
  467. else
  468. {
  469. App.Current.Properties.Add("ObserverPreference", "True");
  470. }
  471. }
  472. else
  473. {
  474. if (App.Current.Properties.ContainsKey("ObserverPreference"))
  475. {
  476. App.Current.Properties["ObserverPreference"] = "False";
  477. }
  478. else
  479. {
  480. App.Current.Properties.Add("ObserverPreference", "False");
  481. }
  482. }
  483. if (searching) RunSearch();
  484. else
  485. {
  486. RefreshButtons(kanbanSubscriberShells);
  487. DisplayList(kanbanSubscriberShells);
  488. }
  489. }
  490. }
  491. }