JobDocViewer.xaml.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. using comal.timesheets.CustomControls;
  2. using comal.timesheets.Data_Classes;
  3. using Comal.Classes;
  4. using InABox.Clients;
  5. using InABox.Core;
  6. using Syncfusion.TreeView.Engine;
  7. using Syncfusion.XForms.PopupLayout;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Collections.ObjectModel;
  11. using System.ComponentModel;
  12. using System.IO;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using Xamarin.Essentials;
  18. using Xamarin.Forms;
  19. using Xamarin.Forms.Xaml;
  20. using XF.Material.Forms.UI.Dialogs;
  21. using PRSSecurity = InABox.Core.Security;
  22. namespace comal.timesheets
  23. {
  24. public delegate void OnFolderListChanged();
  25. [XamlCompilation(XamlCompilationOptions.Compile)]
  26. public partial class JobDocViewer : ContentPage
  27. {
  28. #region Fields and Constructor / Navigation
  29. ObservableCollection<FolderViewItem> folderList = new ObservableCollection<FolderViewItem>();
  30. ObservableCollection<FolderViewItem> displayList = new ObservableCollection<FolderViewItem>();
  31. DeviceIdiom idiom;
  32. bool foldersLoaded = false;
  33. bool filesLoaded = false;
  34. bool specificQueryLoading = false;
  35. Dictionary<JobDocFilterType, string> filters = new Dictionary<JobDocFilterType, string>();
  36. Guid jobID = Guid.Empty;
  37. List<Guid> loadedFolders = new List<Guid>();
  38. List<MileStoneShell> mileStoneShells = new List<MileStoneShell>();
  39. List<JobDocSetFileShell> fullListShells = new List<JobDocSetFileShell>();
  40. List<JobDocSetFileShell> filteredShells = new List<JobDocSetFileShell>();
  41. List<JobDocSetFileShell> searchList = new List<JobDocSetFileShell>();
  42. List<MileStoneShell> specificQueryMileStones = new List<MileStoneShell>();
  43. List<JobDocSetFileShell> specificQueryFileShells = new List<JobDocSetFileShell>();
  44. List<JobDocSetFileShell> currentQueryFileShells = new List<JobDocSetFileShell>();
  45. public JobDocViewer(Job job)
  46. {
  47. InitializeComponent();
  48. NavigationPage.SetHasBackButton(this, false);
  49. titleLbl.Text = "Job " + job.JobNumber;
  50. treeView.QueryNodeSize += TreeView_QueryNodeSize;
  51. idiom = DeviceInfo.Idiom;
  52. if (Device.RuntimePlatform.Equals(Device.iOS))
  53. {
  54. expandImg.HeightRequest = 50;
  55. expandImg.WidthRequest = 50;
  56. collapseImg.HeightRequest = 50;
  57. collapseImg.WidthRequest = 50;
  58. }
  59. jobID = job.ID;
  60. LoadFiles(new Filter<JobDocumentSetMileStone>(x => x.DocumentSet.Job.ID).IsEqualTo(jobID));
  61. LoadFolders(jobID);
  62. }
  63. void ExitBtn_Clicked(object sender, EventArgs e)
  64. {
  65. Navigation.PopAsync();
  66. }
  67. private void FilterButton_Tapped(object sender, EventArgs e)
  68. {
  69. var page = new JobDocsFilterPage(jobID, filters);
  70. page.OnJobDocFiltersPicked += Page_OnJobDocFiltersPicked;
  71. Navigation.PushAsync(page);
  72. }
  73. private void Page_OnJobDocFiltersPicked(string discipline, string type, string category, string area)
  74. {
  75. filterLayout.Children.Clear();
  76. filteredShells.Clear();
  77. filters.Clear();
  78. if (!string.IsNullOrWhiteSpace(discipline))
  79. AddFilter(discipline, JobDocFilterType.Discipline);
  80. if (!string.IsNullOrWhiteSpace(type))
  81. AddFilter(type, JobDocFilterType.Type);
  82. if (!string.IsNullOrWhiteSpace(category))
  83. AddFilter(category, JobDocFilterType.Category);
  84. if (!string.IsNullOrWhiteSpace(area))
  85. AddFilter(area, JobDocFilterType.Area);
  86. DisplayFolderContents();
  87. }
  88. private void AddFilter(string text, JobDocFilterType type)
  89. {
  90. if (!filters.ContainsKey(type))
  91. filters.Add(type, text);
  92. JobDocFilterItem item = new JobDocFilterItem();
  93. item.Init(text, type);
  94. item.OnJobDocFilterClosed += ((filter, type) =>
  95. {
  96. filterLayout.Children.Remove(item);
  97. filters.Remove(type);
  98. RemoveShells(filter, type);
  99. DisplayFolderContents();
  100. });
  101. filterLayout.Children.Add(item);
  102. FilterList(text, type);
  103. }
  104. private void FilterList(string text, JobDocFilterType type)
  105. {
  106. if (type == JobDocFilterType.Discipline)
  107. {
  108. var list = fullListShells.Where(x => x.DocSetDiscipline.Equals(text));
  109. foreach (var v in list)
  110. CheckDuplicateAndAdd(v);
  111. }
  112. else if (type == JobDocFilterType.Type)
  113. {
  114. var list = fullListShells.Where(x => x.DocSetType.Equals(text));
  115. foreach (var v in list)
  116. CheckDuplicateAndAdd(v);
  117. }
  118. else if (type == JobDocFilterType.Category)
  119. {
  120. var list = fullListShells.Where(x => x.DocSetCategory.Equals(text));
  121. foreach (var v in list)
  122. CheckDuplicateAndAdd(v);
  123. }
  124. else if (type == JobDocFilterType.Area)
  125. {
  126. var list = fullListShells.Where(x => x.DocSetArea.Equals(text));
  127. foreach (var v in list)
  128. CheckDuplicateAndAdd(v);
  129. }
  130. }
  131. private void CheckDuplicateAndAdd(JobDocSetFileShell v)
  132. {
  133. var duplicate = filteredShells.FirstOrDefault(x => x.ID == v.ID);
  134. if (duplicate == null)
  135. filteredShells.Add(v);
  136. }
  137. private void RemoveShells(string filter, JobDocFilterType type)
  138. {
  139. if (type == JobDocFilterType.Discipline)
  140. {
  141. while (filteredShells.Find(x => x.DocSetDiscipline == filter) != null)
  142. {
  143. var shell = filteredShells.FirstOrDefault(x => x.DocSetDiscipline == filter);
  144. filteredShells.Remove(shell);
  145. }
  146. }
  147. else if (type == JobDocFilterType.Type)
  148. {
  149. while (filteredShells.Find(x => x.DocSetType == filter) != null)
  150. {
  151. var shell = filteredShells.FirstOrDefault(x => x.DocSetType == filter);
  152. filteredShells.Remove(shell);
  153. }
  154. }
  155. else if (type == JobDocFilterType.Category)
  156. {
  157. while (filteredShells.Find(x => x.DocSetCategory == filter) != null)
  158. {
  159. var shell = filteredShells.FirstOrDefault(x => x.DocSetCategory == filter);
  160. filteredShells.Remove(shell);
  161. }
  162. }
  163. else if (type == JobDocFilterType.Area)
  164. {
  165. while (filteredShells.Find(x => x.DocSetArea == filter) != null)
  166. {
  167. var shell = filteredShells.FirstOrDefault(x => x.DocSetArea == filter);
  168. filteredShells.Remove(shell);
  169. }
  170. }
  171. }
  172. #endregion
  173. #region TreeView / Folder Interaction
  174. void Folder_Tapped(object sender, EventArgs e)
  175. {
  176. DisplayFolderContents();
  177. }
  178. private void DisplayFolderContents()
  179. {
  180. if (treeView.SelectedItem == null)
  181. {
  182. DisplayAlert("Info", "Please select a folder or All folders", "OK");
  183. return;
  184. }
  185. var folder = treeView.SelectedItem as FolderViewItem;
  186. if (folder.Documents == 0)
  187. return;
  188. if (specificQueryLoading)
  189. return;
  190. if (filesLoaded)
  191. {
  192. if (folder.ItemName == "All")
  193. {
  194. if (filters.Count != 0)
  195. AddSearchItems(filteredShells);
  196. else
  197. AddSearchItems(fullListShells);
  198. }
  199. else
  200. {
  201. if (filters.Count != 0)
  202. {
  203. var list = filteredShells.Where(x => x.FolderID == folder.ID);
  204. AddSearchItems(list);
  205. }
  206. else
  207. {
  208. var list = fullListShells.Where(x => x.FolderID == folder.ID);
  209. AddSearchItems(list);
  210. }
  211. }
  212. }
  213. else if (loadedFolders.Contains(folder.ID))
  214. {
  215. var list = specificQueryFileShells.Where(x => x.FolderID == folder.ID);
  216. AddSearchItems(list);
  217. }
  218. else
  219. LoadFilesForFolder(folder.ID);
  220. }
  221. private async void LoadFilesForFolder(Guid folderID)
  222. {
  223. currentQueryFileShells.Clear();
  224. specificQueryLoading = true;
  225. ShowLoading();
  226. LoadFiles(new Filter<JobDocumentSetMileStone>(x => x.DocumentSet.Folder.ID).IsEqualTo(folderID), true, folderID);
  227. }
  228. void Expand_Tapped(object sender, EventArgs e)
  229. {
  230. if (!foldersLoaded)
  231. return;
  232. treeViewFrame.HeightRequest = 28 * folderList.Count;
  233. expandImg.IsVisible = false;
  234. collapseImg.IsVisible = true;
  235. }
  236. void Collapse_Tapped(object sender, EventArgs e)
  237. {
  238. treeViewFrame.HeightRequest = 120;
  239. expandImg.IsVisible = true;
  240. collapseImg.IsVisible = false;
  241. }
  242. #endregion
  243. #region Searching
  244. private void SearchEnt_Changed(object sender, EventArgs e)
  245. {
  246. if (specificQueryLoading)
  247. return;
  248. RunSearch();
  249. }
  250. private void AddSearchItems(IEnumerable<JobDocSetFileShell> list)
  251. {
  252. searchList.Clear();
  253. foreach (var v in list)
  254. {
  255. searchList.Add(v);
  256. }
  257. RunSearch();
  258. }
  259. private void RunSearch()
  260. {
  261. Device.BeginInvokeOnMainThread(() =>
  262. {
  263. listView.ItemsSource = null;
  264. if (string.IsNullOrWhiteSpace(searchEnt.Text))
  265. {
  266. listView.ItemsSource = searchList;
  267. fileCountLbl.Text = "Files (" + searchList.Count() + ")";
  268. }
  269. else
  270. {
  271. var list = searchList.Where
  272. (
  273. x =>
  274. x.FileName.Contains(searchEnt.Text) || x.FileName.Contains(searchEnt.Text.ToLower()) ||
  275. x.FileName.Contains(searchEnt.Text.ToUpper()) || x.FileName.Contains(SearchUtils.UpperCaseFirst(searchEnt.Text)) ||
  276. x.DocSetDescription.Contains(searchEnt.Text) || x.DocSetDescription.Contains(searchEnt.Text.ToLower()) ||
  277. x.DocSetDescription.Contains(searchEnt.Text.ToUpper()) || x.DocSetDescription.Contains(SearchUtils.UpperCaseFirst(searchEnt.Text)) ||
  278. x.Issued.Contains(searchEnt.Text) || x.Issued.Contains(searchEnt.Text.ToLower()) ||
  279. x.Issued.Contains(searchEnt.Text.ToUpper()) || x.Issued.Contains(SearchUtils.UpperCaseFirst(searchEnt.Text)) ||
  280. x.TrimmedIssued.Contains(searchEnt.Text) || x.TrimmedIssued.Contains(searchEnt.Text.ToLower()) ||
  281. x.TrimmedIssued.Contains(searchEnt.Text.ToUpper()) || x.TrimmedIssued.Contains(SearchUtils.UpperCaseFirst(searchEnt.Text)) ||
  282. x.TrimmedIssued.Contains(SearchUtils.UpperCaseSecond(searchEnt.Text)) || x.TrimmedIssued.Contains(SearchUtils.UpperCaseThird(searchEnt.Text)) || x.TrimmedIssued.Contains(SearchUtils.UpperCaseFourth(searchEnt.Text))
  283. );
  284. listView.ItemsSource = list;
  285. fileCountLbl.Text = "Files (" + list.Count() + ")";
  286. }
  287. });
  288. }
  289. #endregion
  290. #region Loading
  291. private void TreeView_QueryNodeSize(object sender, Syncfusion.XForms.TreeView.QueryNodeSizeEventArgs e)
  292. {
  293. e.Height = e.GetActualNodeHeight();
  294. e.Handled = true;
  295. }
  296. private void LoadFolders(Guid jobid)
  297. {
  298. CoreTable table = new Client<JobDocumentSetFolder>().Query(new Filter<JobDocumentSetFolder>(x => x.Job.ID).IsEqualTo(jobid),
  299. new Columns<JobDocumentSetFolder>(x => x.ID, x => x.Parent.ID, x => x.Name, x => x.Documents));
  300. foreach (CoreRow row in table.Rows)
  301. {
  302. FolderViewItem folderItem = new FolderViewItem
  303. {
  304. ID = row.Get<Guid>("ID"),
  305. ParentID = row.Get<Guid>("Parent.ID"),
  306. ItemName = row.Get<string>("Name"),
  307. Documents = row.Get<int>("Documents")
  308. };
  309. folderList.Add(folderItem);
  310. }
  311. foreach (var folder in folderList)
  312. {
  313. folder.List = folderList;
  314. if (folder.ParentID == Guid.Empty || folder.ParentID == CoreUtils.FullGuid)
  315. displayList.Add(folder);
  316. }
  317. displayList = new ObservableCollection<FolderViewItem>(displayList.OrderBy(x => x.ItemName));
  318. treeView.ItemsSource = displayList;
  319. foldersLoaded = true;
  320. filterBtn.IsEnabled = true;
  321. }
  322. private async void LoadFiles(Filter<JobDocumentSetMileStone> filter, bool specificQuery = false, Guid loadFolder = new Guid())
  323. {
  324. await Task.Run(() =>
  325. {
  326. try
  327. {
  328. filter = filter.And(x => x.Status).IsEqualTo(JobDocumentSetMileStoneStatus.Approved)
  329. .And(x => x.Type.SiteVisible).IsEqualTo(true);
  330. CoreTable milestones = new Client<JobDocumentSetMileStone>().Query(filter,
  331. new Columns<JobDocumentSetMileStone>(
  332. x => x.ID,
  333. x => x.DocumentSet.Folder.Name,
  334. x => x.DocumentSet.Folder.ID,
  335. x => x.DocumentSet.Type.Description,
  336. x => x.DocumentSet.Category.Description,
  337. x => x.DocumentSet.Discipline.Description,
  338. x => x.DocumentSet.Area.Description,
  339. x => x.Submitted,
  340. x => x.Employee.Name,
  341. x => x.Type.Description,
  342. x => x.DocumentSet.Description
  343. )
  344. );
  345. if (milestones.Rows.Any())
  346. {
  347. var table = QueryFiles(milestones, specificQuery);
  348. if (table.Rows.Any())
  349. {
  350. foreach (CoreRow filerow in table.Rows)
  351. {
  352. AddFileShell(filerow, specificQuery);
  353. }
  354. Device.BeginInvokeOnMainThread(() =>
  355. {
  356. if (specificQuery)
  357. {
  358. ShowFiles();
  359. specificQueryLoading = false;
  360. loadedFolders.Add(loadFolder);
  361. AddSearchItems(currentQueryFileShells);
  362. }
  363. else
  364. {
  365. filesLoaded = true;
  366. displayList.Insert(0, new FolderViewItem { ItemName = "All", Documents = fullListShells.Count });
  367. folderList.Insert(0, new FolderViewItem { ItemName = "All", Documents = fullListShells.Count });
  368. treeView.ItemsSource = null;
  369. treeView.ItemsSource = displayList;
  370. }
  371. });
  372. }
  373. }
  374. else
  375. {
  376. specificQueryLoading = false;
  377. ShowFiles();
  378. }
  379. }
  380. catch
  381. {
  382. specificQueryLoading = false;
  383. ShowFiles();
  384. }
  385. });
  386. }
  387. private CoreTable QueryFiles(CoreTable milestones, bool specificQuery = false)
  388. {
  389. Filter<JobDocumentSetMileStoneFile> filter = new Filter<JobDocumentSetMileStoneFile>(x => x.EntityLink.ID).IsEqualTo(milestones.Rows.FirstOrDefault().Get<Guid>("ID"));
  390. foreach (CoreRow milestonerow in milestones.Rows)
  391. {
  392. Guid id = AddMileStoneShell(milestonerow, specificQuery);
  393. filter = filter.Or(x => x.EntityLink.ID).IsEqualTo(milestonerow.Get<Guid>("ID"));
  394. }
  395. CoreTable table = new Client<JobDocumentSetMileStoneFile>().Query(
  396. filter,
  397. new Columns<JobDocumentSetMileStoneFile>(
  398. x => x.ID,
  399. x => x.DocumentLink.ID,
  400. x => x.Thumbnail,
  401. x => x.DocumentLink.FileName,
  402. x => x.EntityLink.ID
  403. ));
  404. return table;
  405. }
  406. private Guid AddMileStoneShell(CoreRow milestonerow, bool specificQuery = false)
  407. {
  408. Guid id = milestonerow.Get<Guid>("ID");
  409. MileStoneShell shell = new MileStoneShell
  410. {
  411. ID = milestonerow.Get<Guid>("ID"),
  412. FolderName = milestonerow.Get<JobDocumentSetMileStone, string>(x => x.DocumentSet.Folder.Name),
  413. FolderID = milestonerow.Get<JobDocumentSetMileStone, Guid>(x => x.DocumentSet.Folder.ID),
  414. EmployeeName = milestonerow.Get<JobDocumentSetMileStone, string>(x => x.Employee.Name),
  415. Type = milestonerow.Get<JobDocumentSetMileStone, string>(x => x.Type.Description),
  416. DocSetDescription = milestonerow.Get<JobDocumentSetMileStone, string>(x => x.DocumentSet.Description),
  417. Issued = "Submitted: " + milestonerow.Get<JobDocumentSetMileStone, DateTime>(x => x.Submitted).ToString("dd MMM yy"),
  418. DocSetType = milestonerow.Get<JobDocumentSetMileStone, string>(x => x.DocumentSet.Type.Description),
  419. DocSetCategory = milestonerow.Get<JobDocumentSetMileStone, string>(x => x.DocumentSet.Category.Description),
  420. DocSetDiscipline = milestonerow.Get<JobDocumentSetMileStone, string>(x => x.DocumentSet.Discipline.Description),
  421. };
  422. if (specificQuery)
  423. specificQueryMileStones.Add(shell);
  424. else
  425. mileStoneShells.Add(shell);
  426. return id;
  427. }
  428. private void AddFileShell(CoreRow filerow, bool specificQuery = false)
  429. {
  430. JobDocSetFileShell file = new JobDocSetFileShell
  431. {
  432. ID = filerow.Get<JobDocumentSetMileStoneFile, Guid>(x => x.ID),
  433. DocLinkID = filerow.Get<JobDocumentSetMileStoneFile, Guid>(x => x.DocumentLink.ID),
  434. FileName = filerow.Get<JobDocumentSetMileStoneFile, string>(x => x.DocumentLink.FileName),
  435. MileStoneID = filerow.Get<JobDocumentSetMileStoneFile, Guid>(x => x.EntityLink.ID)
  436. };
  437. MileStoneShell mileStone = mileStoneShells.Find(x => x.ID == file.MileStoneID);
  438. file.FolderName = mileStone.FolderName;
  439. file.FolderID = mileStone.FolderID;
  440. file.EmployeeName = mileStone.EmployeeName;
  441. file.Type = mileStone.Type;
  442. file.DocSetDescription = mileStone.DocSetDescription;
  443. file.Issued = mileStone.Issued;
  444. file.DocSetCategory = mileStone.DocSetCategory;
  445. file.DocSetType = mileStone.DocSetType;
  446. file.DocSetDiscipline = mileStone.DocSetDiscipline;
  447. file.TrimmedIssued = TrimWhiteSpace(file.Issued);
  448. byte[] data = filerow.Get<byte[]>("Thumbnail");
  449. if (data != null)
  450. {
  451. file.ImageSource = ImageSource.FromStream(() => new MemoryStream(data));
  452. if (idiom == DeviceIdiom.Tablet)
  453. {
  454. file.HeightRequest = 400;
  455. file.WidthRequest = 500;
  456. }
  457. file.Thumbnail = data;
  458. }
  459. if (specificQuery)
  460. {
  461. specificQueryFileShells.Add(file);
  462. currentQueryFileShells.Add(file);
  463. }
  464. else
  465. fullListShells.Add(file);
  466. }
  467. private void ShowFiles()
  468. {
  469. Device.BeginInvokeOnMainThread(() =>
  470. {
  471. treeView.IsEnabled = true;
  472. loadingLayout.IsVisible = false;
  473. loadingColumn.Width = 0;
  474. filesLayout.IsVisible = true;
  475. filesColumn.Width = new GridLength(1, GridUnitType.Star);
  476. });
  477. }
  478. private void ShowLoading()
  479. {
  480. Device.BeginInvokeOnMainThread(async () =>
  481. {
  482. treeView.IsEnabled = false;
  483. filesLayout.IsVisible = false;
  484. filesColumn.Width = 0;
  485. loadingLayout.IsVisible = true;
  486. loadingColumn.Width = new GridLength(1, GridUnitType.Star);
  487. Random random = new Random();
  488. uint number = (uint)random.Next(500, 3000);
  489. await loadingLbl.TranslateTo(0, 15, 500);
  490. await loadingLbl.TranslateTo(0, 0, 500);
  491. loadingLbl.RotateTo(360, number);
  492. await loadingLbl.TranslateTo(0, 15, 500);
  493. await loadingLbl.TranslateTo(0, 0, 500);
  494. await loadingLbl.TranslateTo(0, 15, 500);
  495. await loadingLbl.TranslateTo(0, 0, 500);
  496. await loadingLbl.TranslateTo(0, 15, 500);
  497. number = (uint)random.Next(500, 3000);
  498. await loadingLbl.TranslateTo(0, 0, 500);
  499. loadingLbl.RotateTo(360, number);
  500. });
  501. }
  502. static string TrimWhiteSpace(string s)
  503. {
  504. s = String.Concat(s.Where(c => !Char.IsWhiteSpace(c)));
  505. return s;
  506. }
  507. #endregion
  508. #region ListView Interaction
  509. void List_Tapped(object sender, EventArgs e)
  510. {
  511. var shell = listView.SelectedItem as JobDocSetFileShell;
  512. if (Device.RuntimePlatform.Equals(Device.Android) && PRSSecurity.IsAllowed<CanOpenMobileNativePDFViewer>())
  513. OpenNativeViewer(shell.DocLinkID);
  514. else
  515. {
  516. PDFViewer viewer = new PDFViewer(shell.DocLinkID);
  517. Navigation.PushAsync(viewer);
  518. }
  519. }
  520. private async void OpenNativeViewer(Guid docID)
  521. {
  522. CoreTable table = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(docID),
  523. new Columns<Document>(x => x.Data, x => x.FileName));
  524. Document doc = table.Rows.First().ToObject<Document>();
  525. var filePath = Path.Combine(FileSystem.AppDataDirectory, doc.FileName);
  526. File.WriteAllBytes(filePath, doc.Data);
  527. await Launcher.OpenAsync(new OpenFileRequest
  528. {
  529. File = new ReadOnlyFile(filePath)
  530. });
  531. }
  532. void Image_Tapped(object sender, EventArgs e)
  533. {
  534. var shell = ((TappedEventArgs)e).Parameter as JobDocSetFileShell;
  535. if (shell == null)
  536. return;
  537. if (shell.Thumbnail != null)
  538. {
  539. Image popupContent = new Image();
  540. popupContent.HeightRequest = 500;
  541. popupContent.WidthRequest = 600;
  542. popupContent.HorizontalOptions = LayoutOptions.FillAndExpand;
  543. popupContent.VerticalOptions = LayoutOptions.FillAndExpand;
  544. popupContent.Aspect = Aspect.AspectFit;
  545. popupContent.Source = ImageSource.FromStream(() => new MemoryStream(shell.Thumbnail));
  546. popupLayout.PopupView.ShowHeader = false;
  547. popupLayout.PopupView.ShowFooter = false;
  548. popupLayout.PopupView.ContentTemplate = new DataTemplate(() =>
  549. {
  550. return popupContent;
  551. });
  552. popupLayout.Show();
  553. }
  554. }
  555. #endregion
  556. }
  557. #region Classes
  558. public class FolderViewItem : INotifyPropertyChanged
  559. {
  560. public event OnFolderListChanged OnFolderListChanged;
  561. public event PropertyChangedEventHandler PropertyChanged;
  562. public Guid ID { get; set; }
  563. public Guid ParentID { get; set; }
  564. public ImageSource ImageIcon { get; set; }
  565. private ObservableCollection<FolderViewItem> list;
  566. public ObservableCollection<FolderViewItem> List
  567. {
  568. get
  569. {
  570. return list;
  571. }
  572. set
  573. {
  574. list = value;
  575. OnFolderListChanged?.Invoke();
  576. }
  577. }
  578. private string itemName;
  579. public string ItemName
  580. {
  581. get { return itemName; }
  582. set
  583. {
  584. itemName = value;
  585. RaisedOnPropertyChanged("ItemName");
  586. }
  587. }
  588. public int Documents { get; set; }
  589. public ObservableCollection<FolderViewItem> SubFiles { get; set; }
  590. public Guid DocID { get; set; }
  591. public FolderViewItem()
  592. {
  593. ID = Guid.Empty;
  594. ItemName = "";
  595. ImageIcon = "folder.png";
  596. DocID = Guid.Empty;
  597. ParentID = Guid.Empty;
  598. OnFolderListChanged += FolderViewItem_OnFolderListChanged;
  599. Documents = 0;
  600. }
  601. private void FolderViewItem_OnFolderListChanged()
  602. {
  603. GetChildren();
  604. }
  605. public void RaisedOnPropertyChanged(string _PropertyName)
  606. {
  607. if (PropertyChanged != null)
  608. {
  609. PropertyChanged(this, new PropertyChangedEventArgs(_PropertyName));
  610. }
  611. }
  612. private void GetChildren()
  613. {
  614. SubFiles = new ObservableCollection<FolderViewItem>(list.Where(x => x.ParentID.Equals(ID)));
  615. }
  616. }
  617. public class MileStoneShell
  618. {
  619. public Guid ID { get; set; }
  620. public string FolderName { get; set; }
  621. public Guid FolderID { get; set; }
  622. public string EmployeeName { get; set; }
  623. public string Type { get; set; }
  624. public string DocSetDescription { get; set; }
  625. public string Issued { get; set; }
  626. public string DocSetType { get; set; }
  627. public string DocSetDiscipline { get; set; }
  628. public string DocSetCategory { get; set; }
  629. public string DocSetArea { get; set; }
  630. public MileStoneShell()
  631. {
  632. ID = Guid.Empty;
  633. FolderID = Guid.Empty;
  634. FolderName = "";
  635. EmployeeName = "";
  636. Type = "";
  637. DocSetDescription = "";
  638. Issued = "";
  639. DocSetCategory = "";
  640. DocSetDiscipline = "";
  641. DocSetType = "";
  642. DocSetArea = "";
  643. }
  644. }
  645. public class JobDocSetFileShell
  646. {
  647. public Guid ID { get; set; }
  648. public Guid DocLinkID { get; set; }
  649. public string FileName { get; set; }
  650. public string FolderName { get; set; }
  651. public Guid FolderID { get; set; }
  652. public string EmployeeName { get; set; }
  653. public string Type { get; set; }
  654. public string DocSetDescription { get; set; }
  655. public string Issued { get; set; }
  656. public string TrimmedIssued { get; set; }
  657. public ImageSource ImageSource { get; set; }
  658. public double HeightRequest { get; set; }
  659. public double WidthRequest { get; set; }
  660. public byte[] Thumbnail { get; set; }
  661. public Guid MileStoneID { get; set; }
  662. public string DocSetType { get; set; }
  663. public string DocSetDiscipline { get; set; }
  664. public string DocSetCategory { get; set; }
  665. public string DocSetArea { get; set; }
  666. public JobDocSetFileShell()
  667. {
  668. ID = Guid.Empty;
  669. DocLinkID = Guid.Empty;
  670. FileName = "";
  671. FolderName = "";
  672. EmployeeName = "";
  673. Type = "";
  674. DocSetDescription = "";
  675. ImageSource = null;
  676. Issued = "";
  677. TrimmedIssued = "";
  678. HeightRequest = 150;
  679. WidthRequest = 200;
  680. Thumbnail = null;
  681. MileStoneID = Guid.Empty;
  682. FolderID = Guid.Empty;
  683. DocSetCategory = "";
  684. DocSetDiscipline = "";
  685. DocSetType = "";
  686. DocSetArea = "";
  687. }
  688. }
  689. public enum JobDocFilterType
  690. {
  691. Discipline,
  692. Type,
  693. Category,
  694. Area
  695. }
  696. #endregion
  697. }