TasksList.xaml.cs 20 KB

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