LiveMapsTwo.xaml.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.ComponentModel;
  5. using System.Linq;
  6. using System.Linq.Expressions;
  7. using System.Threading.Tasks;
  8. using Comal.Classes;
  9. using InABox.Clients;
  10. using InABox.Core;
  11. using Xamarin.Forms;
  12. using Xamarin.Forms.Xaml;
  13. using Syncfusion.SfMaps.XForms;
  14. using System.Threading;
  15. using System.IO;
  16. using Xamarin.Essentials;
  17. using Xamarin.CommunityToolkit.UI.Views;
  18. namespace comal.timesheets
  19. {
  20. [XamlCompilation(XamlCompilationOptions.Compile)]
  21. public partial class LiveMapsTwo : ContentPage
  22. {
  23. Frame currentHeader = new Frame();
  24. int currentPosition = 0;
  25. Equipment equipment = new Equipment();
  26. Job job = new Job();
  27. List<String> types = new List<String>();
  28. string[] array;
  29. string country = "Australia";
  30. bool bFirstLoad = true;
  31. double deviceHeight = 0.0F;
  32. Color On = Color.LightGreen;
  33. Color Off = Color.White;
  34. string saved = "SavedMapEquipment";
  35. List<Frame> frames = new List<Frame>();
  36. InABox.Core.Location CurrentJobLocation = new InABox.Core.Location();
  37. InABox.Core.Location Perth = new InABox.Core.Location() { Latitude = -32.0410801, Longitude = 115.9957434 };
  38. bool bButtonsTouched = false;
  39. Dictionary<string, List<EquipmentShell>> EquipmentMappedToTypes = new Dictionary<string, List<EquipmentShell>>();
  40. List<EquipmentShell> equipmentShellsToDisplay = new List<EquipmentShell>();
  41. List<Expander> expanders = new List<Expander>();
  42. List<EquipmentShell> equipmentShells = new List<EquipmentShell>();
  43. Dictionary<string, Image> images = new Dictionary<string, Image>();
  44. Dictionary<string, Image> images1 = new Dictionary<string, Image>();
  45. double DeviceWidth = 0.0F;
  46. public LiveMapsTwo()
  47. {
  48. InitializeComponent();
  49. job = new Job();
  50. equipment = new Equipment();
  51. var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
  52. deviceHeight = mainDisplayInfo.Height;
  53. DeviceWidth = mainDisplayInfo.Width;
  54. sfMapLayer.GeoCoordinates = new Point(-32.0410801, 115.9957434);
  55. sfMap.ZoomLevel = 10;
  56. if (Device.RuntimePlatform.Equals(Device.iOS))
  57. {
  58. //ImageSource imageSource = "mapmarker.png";
  59. //sfMapLayer.MarkerSettings.MarkerIcon = MapMarkerIcon.Image;
  60. //sfMapLayer.MarkerSettings.ImageSource = "location-pin.pdf";
  61. //sfMapLayer.MarkerSettings.IconSize = 35;
  62. sfMapLayer.MarkerSettings.MarkerIcon = MapMarkerIcon.Circle;
  63. sfMapLayer.MarkerSettings.IconColor = Color.DarkBlue;
  64. sfMapLayer.MarkerSettings.IconSize = 15;
  65. }
  66. else
  67. {
  68. sfMapLayer.MarkerSettings.MarkerIcon = MapMarkerIcon.Image;
  69. sfMapLayer.MarkerSettings.ImageSource = "mapmarker.png";
  70. sfMapLayer.MarkerSettings.IconSize = 35;
  71. }
  72. sfMapLayer.MarkerSettings.FontAttributes = FontAttributes.Bold;
  73. sfMapLayer.MarkerSettings.LabelSize = 20;
  74. sfMapLayer.MarkerSettings.LabelColor = Color.DarkBlue;
  75. Timer t = new Timer(JobsBtnBounceCallBack, null, 0, 5000);
  76. LoadData();
  77. }
  78. protected override void OnAppearing()
  79. {
  80. base.OnAppearing();
  81. }
  82. private void Reset_Clicked(object sender, EventArgs e)
  83. {
  84. if (jobsBtn.BackgroundColor == On)
  85. {
  86. jobsBtn.BackgroundColor = Off;
  87. equipmentShellsToDisplay.Clear();
  88. sfMapLayer.Markers.Clear();
  89. flexLayout.Children.Clear();
  90. Title = "Select Equipment";
  91. foreach (Expander expander in expanders)
  92. {
  93. flexLayout.Children.Add(expander);
  94. }
  95. }
  96. sfMapLayer.Markers.Clear();
  97. sfMapLayer.GeoCoordinates = new Point(-32.0410801, 115.9957434);
  98. sfMap.ZoomLevel = 10;
  99. equipmentShellsToDisplay.Clear();
  100. }
  101. private async void JobsBtnBounceCallBack(object o)
  102. {
  103. if (jobsBtn.BackgroundColor == On)
  104. {
  105. await jobsBtn.TranslateTo(0, -15, 150);
  106. await jobsBtn.TranslateTo(0, 0, 150);
  107. await jobsBtn.TranslateTo(0, -7.5, 150);
  108. await jobsBtn.TranslateTo(0, 0, 150);
  109. }
  110. }
  111. private async void LoadData()
  112. {
  113. Title = "Live Maps - Loading";
  114. await Task.Run(() =>
  115. {
  116. if (Application.Current.Properties.ContainsKey(saved))
  117. {
  118. equipmentShellsToDisplay = Application.Current.Properties[saved] as List<EquipmentShell>;
  119. DisplayMarkersFromList();
  120. }
  121. LoadGroups();
  122. LoadEquipment();
  123. LoadExpanders();
  124. double width = (DeviceWidth / 10) * 4;
  125. Thread.Sleep(300);
  126. Device.BeginInvokeOnMainThread(async () =>
  127. {
  128. if (Device.RuntimePlatform.Equals(Device.Android))
  129. {
  130. Swipe.IsVisible = true;
  131. await Swipe.TranslateTo(width, 0, 1000);
  132. await Swipe.TranslateTo(0, 0, 1000);
  133. Swipe.IsVisible = false;
  134. }
  135. jobsBtn.RotateTo(360, 1000);
  136. });
  137. });
  138. }
  139. private void LoadGroups()
  140. {
  141. var client = new Client<EquipmentGroup>();
  142. var table = client.Query(
  143. new Filter<EquipmentGroup>(x => x.Code).IsNotEqualTo(string.Empty),
  144. new Columns<EquipmentGroup>(x => x.Code, x => x.Thumbnail.ID),
  145. new SortOrder<EquipmentGroup>(x => x.Description)
  146. );
  147. foreach (CoreRow row in table.Rows)
  148. {
  149. List<object> list = row.Values;
  150. if (list[0] == null) { list[0] = ""; } //0
  151. if (list[1] == null) { list[1] = Guid.Empty; } //1
  152. EquipmentGroupShell group = new EquipmentGroupShell()
  153. {
  154. Code = list[0].ToString(),
  155. ThumbnailID = Guid.Parse(list[1].ToString())
  156. };
  157. //TODO remove Comal-specific group filtering
  158. if (group.Code != "ZZINACTIVE" && group.Code != "CALIBRATED" && group.Code != "DEVICE" && group.Code != "FACTORY")
  159. {
  160. types.Add(group.Code);
  161. CoreTable table2 = new Client<Document>().Query
  162. (
  163. new Filter<Document>(x => x.ID).IsEqualTo(group.ThumbnailID),
  164. new Columns<Document>(x => x.Data)
  165. );
  166. if (table2.Rows.Any())
  167. {
  168. CoreRow docrow = table2.Rows.FirstOrDefault();
  169. if (docrow != null)
  170. {
  171. byte[] data = docrow.Get<Document, byte[]>(x => x.Data);
  172. ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  173. Image img = new Image();
  174. img.HeightRequest = 30;
  175. img.WidthRequest = 30;
  176. img.Aspect = Aspect.AspectFit;
  177. img.Source = src;
  178. images.Add(group.Code, img);
  179. Image img1 = new Image();
  180. img1.HeightRequest = 30;
  181. img1.WidthRequest = 30;
  182. img1.Aspect = Aspect.AspectFit;
  183. img1.Source = src;
  184. images1.Add(group.Code, img1);
  185. }
  186. }
  187. }
  188. }
  189. }
  190. private void LoadEquipment()
  191. {
  192. Filter<Equipment> filter = new Filter<Equipment>(x => x.GroupLink.Code).IsEqualTo(types.First());
  193. foreach (string s in types)
  194. {
  195. if (s != types.First())
  196. filter = filter.Or(x => x.GroupLink.Code).IsEqualTo(s);
  197. }
  198. CoreTable table = new Client<Equipment>().Query(
  199. filter,
  200. new Columns<Equipment>(
  201. x => x.GroupLink.Code, //0
  202. x => x.Description, //1
  203. x => x.TrackerLink.Location.Latitude, //2
  204. x => x.TrackerLink.Location.Longitude, //3
  205. x => x.LastUpdate //4
  206. )
  207. );
  208. foreach (CoreRow row in table.Rows)
  209. {
  210. List<object> list = row.Values;
  211. if (list[0] == null) { list[0] = ""; } //0
  212. if (list[1] == null) { list[1] = ""; } //1
  213. if (list[2] == null) { list[2] = 0.0F; } //2
  214. if (list[3] == null) { list[3] = 0.0F; } //3
  215. if (list[4] == null) { list[4] = DateTime.MinValue; }//4
  216. EquipmentShell equipmentShell = new EquipmentShell()
  217. {
  218. Code = list[0].ToString(),
  219. Description = list[1].ToString(),
  220. Latitude = double.Parse(list[2].ToString()),
  221. Longitude = double.Parse(list[3].ToString()),
  222. LastUpdate = DateTime.Parse(list[4].ToString()),
  223. };
  224. equipmentShell.Location = new InABox.Core.Location() { Latitude = equipmentShell.Latitude, Longitude = equipmentShell.Longitude };
  225. if (equipmentShell.Longitude == 0.0F && equipmentShell.Latitude == 0.0F)
  226. {
  227. //do nothing
  228. }
  229. else
  230. equipmentShells.Add(equipmentShell);
  231. }
  232. }
  233. private void LoadExpanders()
  234. {
  235. List<string> equipmentShellsToDisplayNames = new List<string>();
  236. if (equipmentShellsToDisplay.Count > 0)
  237. {
  238. foreach (EquipmentShell shell in equipmentShellsToDisplay)
  239. {
  240. equipmentShellsToDisplayNames.Add(shell.Description);
  241. }
  242. }
  243. Dictionary<string, List<OptionString>> ListsDictionary = new Dictionary<string, List<OptionString>>();
  244. foreach (string s in types)
  245. {
  246. List<EquipmentShell> shells = new List<EquipmentShell>();
  247. List<OptionString> optionStrings = new List<OptionString>();
  248. foreach (EquipmentShell equipmentShell in equipmentShells)
  249. {
  250. if (equipmentShell.Code == s)
  251. {
  252. OptionString optionString = new OptionString() { Value = equipmentShell.Description };
  253. if (equipmentShellsToDisplayNames.Contains(equipmentShell.Description))
  254. {
  255. optionString.Color = On;
  256. }
  257. optionStrings.Add(optionString);
  258. shells.Add(equipmentShell);
  259. }
  260. }
  261. if (optionStrings.Count > 16)
  262. {
  263. optionStrings.Add(new OptionString { Value = "" });
  264. optionStrings.Add(new OptionString { Value = "" });
  265. optionStrings.Add(new OptionString { Value = "" });
  266. }
  267. EquipmentMappedToTypes.Add(s, shells);
  268. ListsDictionary.Add(s, optionStrings);
  269. Label label = new Label
  270. {
  271. Text = s,
  272. FontAttributes = FontAttributes.Bold,
  273. HorizontalOptions = LayoutOptions.Center,
  274. VerticalOptions = LayoutOptions.Center,
  275. VerticalTextAlignment = TextAlignment.Center
  276. };
  277. label.FontSize = 18;
  278. Grid grid = new Grid();
  279. grid.Margin = 0;
  280. grid.Padding = 0;
  281. grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  282. grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  283. Frame frame = new Frame();
  284. frame.BackgroundColor = Color.White;
  285. frame.HasShadow = false;
  286. frame.CornerRadius = 15;
  287. frame.BorderColor = Color.Transparent;
  288. frame.Padding = new Thickness(12, 2, 12, 2);
  289. frame.Margin = new Thickness(0, 0, 0, 5);
  290. frame.HorizontalOptions = LayoutOptions.Center;
  291. Image image = new Image();
  292. try
  293. {
  294. image = images[s];
  295. }
  296. catch { }
  297. if (image != null)
  298. {
  299. Grid.SetColumn(image, 0);
  300. Grid.SetColumn(label, 1);
  301. image.Margin = 0;
  302. grid.Children.Add(image);
  303. grid.Children.Add(label);
  304. frame.Content = grid;
  305. }
  306. else
  307. {
  308. frame.Content = label;
  309. }
  310. Expander expander = new Expander
  311. {
  312. Header = frame
  313. };
  314. DataTemplate template = new DataTemplate(() =>
  315. {
  316. Button valueBtn = new Button();
  317. valueBtn.SetBinding(Button.TextProperty, "Value");
  318. valueBtn.SetBinding(BackgroundColorProperty, "Color");
  319. valueBtn.Clicked += ValueBtn_Clicked;
  320. valueBtn.TextColor = Color.DarkGray;
  321. valueBtn.CornerRadius = 15;
  322. valueBtn.BorderColor = Color.Transparent;
  323. valueBtn.Margin = new Thickness(10, 1, 10, 1);
  324. return new ViewCell { View = valueBtn };
  325. });
  326. ListView listView = new ListView();
  327. listView.ItemTemplate = template;
  328. listView.ItemsSource = ListsDictionary[s];
  329. expander.Content = listView;
  330. expander.ExpandAnimationLength = 100;
  331. expander.ExpandAnimationEasing = Easing.CubicOut;
  332. expander.CollapseAnimationLength = 0;
  333. expander.Margin = new Thickness(2, 2, 2, 5);
  334. expander.BackgroundColor = Color.Transparent;
  335. expander.Tapped += Expander_Tapped;
  336. expanders.Add(expander);
  337. Device.BeginInvokeOnMainThread(() =>
  338. {
  339. flexLayout.Children.Add(expander);
  340. });
  341. GenerateFrame(s);
  342. }
  343. bFirstLoad = false;
  344. Device.BeginInvokeOnMainThread(() =>
  345. {
  346. Title = "Select Equipment";
  347. jobsBtn.IsEnabled = true;
  348. });
  349. }
  350. private void GenerateFrame(string s)
  351. {
  352. Label label1 = new Label
  353. {
  354. Text = s,
  355. FontAttributes = FontAttributes.Bold,
  356. HorizontalOptions = LayoutOptions.Center,
  357. VerticalOptions = LayoutOptions.Center,
  358. VerticalTextAlignment = TextAlignment.Center
  359. };
  360. label1.FontSize = 18;
  361. Grid grid1 = new Grid();
  362. grid1.Margin = 0;
  363. grid1.Padding = 0;
  364. grid1.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  365. grid1.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  366. Image image1 = new Image();
  367. try
  368. {
  369. image1 = images1[s];
  370. }
  371. catch { }
  372. Frame frame1 = new Frame();
  373. frame1.BackgroundColor = Off;
  374. frame1.HasShadow = false;
  375. frame1.CornerRadius = 15;
  376. frame1.BorderColor = Color.Transparent;
  377. frame1.Padding = new Thickness(15, 2, 15, 2);
  378. frame1.Margin = new Thickness(5, 0, 5, 5);
  379. frame1.HorizontalOptions = LayoutOptions.Center;
  380. if (image1 != null)
  381. {
  382. Grid.SetColumn(image1, 0);
  383. Grid.SetColumn(label1, 1);
  384. image1.Margin = 0;
  385. grid1.Children.Add(image1);
  386. grid1.Children.Add(label1);
  387. frame1.Content = grid1;
  388. }
  389. else
  390. {
  391. frame1.Content = label1;
  392. }
  393. TapGestureRecognizer tapGestureRecognizer = new TapGestureRecognizer() { NumberOfTapsRequired = 1 };
  394. tapGestureRecognizer.Tapped += ((object sender, EventArgs e) =>
  395. {
  396. bButtonsTouched = true;
  397. Frame thisFrame = sender as Frame;
  398. if (thisFrame.BackgroundColor == Off)
  399. {
  400. sfMapLayer.Markers.Clear();
  401. thisFrame.BackgroundColor = On;
  402. image1.BackgroundColor = On;
  403. foreach (EquipmentShell equipment in EquipmentMappedToTypes[s])
  404. {
  405. if (CurrentJobLocation.DistanceTo(equipment.Location, UnitOfLength.Kilometers) < 1.5)
  406. {
  407. equipmentShellsToDisplay.Add(equipment);
  408. }
  409. }
  410. DisplayMarkersFromList();
  411. }
  412. else if (thisFrame.BackgroundColor == On)
  413. {
  414. sfMapLayer.Markers.Clear();
  415. thisFrame.BackgroundColor = Off;
  416. foreach (EquipmentShell equipment in EquipmentMappedToTypes[s])
  417. {
  418. if (CurrentJobLocation.DistanceTo(equipment.Location, UnitOfLength.Kilometers) < 1.5)
  419. {
  420. equipmentShellsToDisplay.Remove(equipment);
  421. }
  422. }
  423. DisplayMarkersFromList();
  424. }
  425. });
  426. frame1.GestureRecognizers.Add(tapGestureRecognizer);
  427. frames.Add(frame1);
  428. }
  429. private void ValueBtn_Clicked(object sender, EventArgs e)
  430. {
  431. Button valueBtn = sender as Button;
  432. if (valueBtn.BackgroundColor == Off)
  433. {
  434. valueBtn.BackgroundColor = On;
  435. equipmentShellsToDisplay.Add(equipmentShells.Find(x => x.Description.Equals(valueBtn.Text)));
  436. }
  437. else
  438. {
  439. valueBtn.BackgroundColor = Off;
  440. equipmentShellsToDisplay.Remove(equipmentShellsToDisplay.Find(x => x.Description.Equals(valueBtn.Text)));
  441. }
  442. }
  443. protected override void OnDisappearing()
  444. {
  445. if (equipmentShellsToDisplay.Count > 0)
  446. {
  447. if (!Application.Current.Properties.ContainsKey(saved))
  448. {
  449. Application.Current.Properties.Add(saved, equipmentShellsToDisplay);
  450. }
  451. else
  452. {
  453. Application.Current.Properties.Remove(saved);
  454. Application.Current.Properties.Add(saved, equipmentShellsToDisplay);
  455. }
  456. }
  457. else
  458. {
  459. Application.Current.Properties.Remove(saved);
  460. }
  461. base.OnDisappearing();
  462. }
  463. private void Expander_Tapped(object sender, EventArgs e)
  464. {
  465. Expander exp = sender as Expander;
  466. if (exp.State.Equals(ExpandState.Expanding) || exp.State.Equals(ExpandState.Expanded))
  467. {
  468. currentHeader = exp.Header as Frame;
  469. foreach (Expander expander in expanders)
  470. {
  471. if (!expander.Equals(sender))
  472. {
  473. flexLayout.Children.Remove(expander);
  474. }
  475. else
  476. {
  477. currentPosition = expanders.IndexOf(expander);
  478. exp.Header = CreateFrame();
  479. }
  480. }
  481. scrollView.HeightRequest = deviceHeight;
  482. scrollView.ScrollToAsync(exp, ScrollToPosition.MakeVisible, false);
  483. }
  484. else if (exp.State.Equals(ExpandState.Collapsing) || exp.State.Equals(ExpandState.Collapsed))
  485. {
  486. scrollView.HeightRequest = 45;
  487. scrollView.ScrollToAsync(exp, ScrollToPosition.MakeVisible, false);
  488. flexLayout.Children.Clear();
  489. exp.Header = currentHeader;
  490. foreach (Expander expander in expanders)
  491. {
  492. flexLayout.Children.Add(expander);
  493. }
  494. sfMapLayer.Markers.Clear();
  495. DisplayMarkersFromList();
  496. }
  497. }
  498. private Frame CreateFrame()
  499. {
  500. Label label = new Label
  501. {
  502. Text = "Tap Here to View or Cancel",
  503. FontAttributes = FontAttributes.Bold,
  504. HorizontalOptions = LayoutOptions.Center,
  505. VerticalOptions = LayoutOptions.Center,
  506. VerticalTextAlignment = TextAlignment.Center,
  507. LineBreakMode = LineBreakMode.WordWrap
  508. };
  509. label.FontSize = Device.GetNamedSize(NamedSize.Large, label);
  510. Grid grid = new Grid();
  511. grid.Margin = 0;
  512. grid.Padding = 0;
  513. grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  514. grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  515. Frame frame = new Frame();
  516. frame.BackgroundColor = Color.Orange;
  517. frame.HasShadow = false;
  518. frame.CornerRadius = 15;
  519. frame.BorderColor = Color.Transparent;
  520. frame.Padding = new Thickness(10);
  521. frame.Margin = new Thickness(5);
  522. frame.HorizontalOptions = LayoutOptions.Center;
  523. frame.HeightRequest = 40;
  524. Image image = new Image();
  525. image.Source = "mapicon.png";
  526. Grid.SetColumn(image, 0);
  527. Grid.SetColumn(label, 1);
  528. image.Margin = 0;
  529. grid.Children.Add(image);
  530. grid.Children.Add(label);
  531. frame.Content = grid;
  532. return frame;
  533. }
  534. private async void DisplayMarkersFromList()
  535. {
  536. await Task.Run(() =>
  537. {
  538. CalculateCenter();
  539. foreach (EquipmentShell equipment in equipmentShellsToDisplay)
  540. {
  541. MapMarker marker = new MapMarker();
  542. marker.Label = equipment.Description;
  543. marker.Latitude = equipment.Latitude.ToString();
  544. marker.Longitude = equipment.Longitude.ToString();
  545. Device.BeginInvokeOnMainThread(() =>
  546. {
  547. sfMapLayer.Markers.Add(marker);
  548. });
  549. }
  550. });
  551. }
  552. private async void CalculateCenter()
  553. {
  554. if (equipmentShellsToDisplay.Count == 1)
  555. {
  556. EquipmentShell equipment = equipmentShellsToDisplay.First();
  557. Device.BeginInvokeOnMainThread(() =>
  558. {
  559. sfMapLayer.GeoCoordinates = new Point(equipment.Latitude, equipment.Longitude);
  560. sfMap.ZoomLevel = 15;
  561. });
  562. }
  563. else if (equipmentShellsToDisplay.Count > 1)
  564. {
  565. List<double> latitudes = new List<double>();
  566. List<double> longitudes = new List<double>();
  567. foreach (EquipmentShell equipment in equipmentShellsToDisplay)
  568. {
  569. latitudes.Add(equipment.Latitude);
  570. longitudes.Add(equipment.Longitude);
  571. }
  572. latitudes.Sort();
  573. longitudes.Sort();
  574. double firstLat = latitudes.First();
  575. double lastLat = latitudes.Last();
  576. double firstLong = longitudes.First();
  577. double lastLong = longitudes.Last();
  578. double resultLat = (firstLat + lastLat) / 2;
  579. double resultLong = (firstLong + lastLong) / 2;
  580. InABox.Core.Location firstLocation = new InABox.Core.Location() { Latitude = firstLat, Longitude = firstLong };
  581. InABox.Core.Location lastLocation = new InABox.Core.Location() { Latitude = lastLat, Longitude = lastLong };
  582. double distance = firstLocation.DistanceTo(lastLocation, UnitOfLength.Kilometers);
  583. CalculateZoom(distance);
  584. Device.BeginInvokeOnMainThread(() =>
  585. {
  586. sfMapLayer.GeoCoordinates = new Point(resultLat, resultLong);
  587. });
  588. }
  589. }
  590. private void CalculateZoom(double distance)
  591. {
  592. Device.BeginInvokeOnMainThread(() =>
  593. {
  594. if (distance < 1)
  595. {
  596. sfMap.ZoomLevel = 17;
  597. }
  598. else if (distance >= 1 && distance <= 5)
  599. {
  600. sfMap.ZoomLevel = 16;
  601. }
  602. else if (distance >= 5 && distance <= 10)
  603. {
  604. sfMap.ZoomLevel = 15;
  605. }
  606. else if (distance >= 10 && distance <= 20)
  607. {
  608. sfMap.ZoomLevel = 11;
  609. }
  610. else if (distance >= 20 && distance <= 50)
  611. {
  612. sfMap.ZoomLevel = 10;
  613. }
  614. else if (distance >= 50 && distance <= 100)
  615. {
  616. sfMap.ZoomLevel = 9;
  617. }
  618. else if (distance >= 100 && distance <= 200)
  619. {
  620. sfMap.ZoomLevel = 8;
  621. }
  622. else if (distance >= 200 && distance <= 400)
  623. {
  624. sfMap.ZoomLevel = 7;
  625. }
  626. else if (distance >= 400)
  627. {
  628. sfMap.ZoomLevel = 6;
  629. }
  630. });
  631. }
  632. private async void JobsBtn_Clicked(object sender, EventArgs e)
  633. {
  634. if (jobsBtn.BackgroundColor == On)
  635. {
  636. jobsBtn.BackgroundColor = Off;
  637. equipmentShellsToDisplay.Clear();
  638. sfMapLayer.Markers.Clear();
  639. flexLayout.Children.Clear();
  640. Title = "Select Equipment";
  641. foreach (Expander expander in expanders)
  642. {
  643. flexLayout.Children.Add(expander);
  644. }
  645. }
  646. else
  647. {
  648. var jobs = GlobalVariables.JobShells.Where(x => x.JobStatusDescription.Equals("Active"));
  649. List<string> names = new List<string>();
  650. foreach (var jobshell in jobs)
  651. {
  652. string s = jobshell.Name;
  653. if (!string.IsNullOrWhiteSpace(s) && s != "Empty Job")
  654. names.Add(s);
  655. }
  656. string[] actions = names.ToArray();
  657. string result = await DisplayActionSheet("Select Job", "Cancel", null, actions);
  658. if (string.IsNullOrEmpty(result) || result.Equals("Cancel"))
  659. return;
  660. Device.BeginInvokeOnMainThread(() =>
  661. {
  662. Title = "Loading Job";
  663. });
  664. try
  665. {
  666. await Task.Run(async () =>
  667. {
  668. CustomControls.JobShell _jobShell = GlobalVariables.JobShells.Find(x => x.Name.Equals(result));
  669. Job job = new Client<Job>().Query(new Filter<Job>(x => x.ID).IsEqualTo(_jobShell.ID)).Rows.First().ToObject<Job>();
  670. var xamlocation = (await Geocoding.GetLocationsAsync($"{job.SiteAddress.Street}, {job.SiteAddress.City}, {"Australia"}")).FirstOrDefault();
  671. if (xamlocation == null) return;
  672. CurrentJobLocation = new InABox.Core.Location() { Latitude = xamlocation.Latitude, Longitude = xamlocation.Longitude };
  673. equipmentShellsToDisplay.Clear();
  674. if (CurrentJobLocation.DistanceTo(Perth, UnitOfLength.Kilometers) > 500)
  675. {
  676. DisplayAlert("Error with Address", "Address on file: " + job.SiteAddress + " " + job.SiteAddress.City, "OK");
  677. }
  678. else
  679. {
  680. Device.BeginInvokeOnMainThread(() =>
  681. {
  682. Title = "Equipment by Job";
  683. sfMapLayer.Markers.Clear();
  684. sfMap.ZoomLevel = 18;
  685. sfMapLayer.GeoCoordinates = new Point(xamlocation.Latitude, xamlocation.Longitude);
  686. Title = result;
  687. flexLayout.Children.Clear();
  688. flexLayout.HeightRequest = 55;
  689. jobsBtn.BackgroundColor = On;
  690. foreach (Frame frame in frames)
  691. {
  692. flexLayout.Children.Add(frame);
  693. }
  694. });
  695. if (Device.RuntimePlatform.Equals(Device.Android))
  696. {
  697. bButtonsTouched = false;
  698. Thread.Sleep(2000);
  699. HighlightFrames();
  700. Timer t = new Timer(ButtonsNotTouched, null, 0, 6000);
  701. }
  702. }
  703. });
  704. }
  705. catch
  706. {
  707. DisplayAlert("Error with Address", "Address on file: " + job.SiteAddress + " " + job.SiteAddress.City, "OK");
  708. Device.BeginInvokeOnMainThread(() =>
  709. {
  710. Title = "Select Equipment";
  711. });
  712. }
  713. }
  714. }
  715. private async void HighlightFrames()
  716. {
  717. foreach (Frame frame in frames)
  718. {
  719. frame.BackgroundColor = Color.Yellow;
  720. Thread.Sleep(750);
  721. frame.BackgroundColor = Off;
  722. }
  723. }
  724. private void ButtonsNotTouched(object o)
  725. {
  726. if (!bButtonsTouched)
  727. {
  728. HighlightFrames();
  729. }
  730. }
  731. private async void ShowJobLocation(string street, string city, string name)
  732. {
  733. try
  734. {
  735. var location = (await Geocoding.GetLocationsAsync($"{street}, {city}, {country}")).FirstOrDefault();
  736. if (location == null) return;
  737. sfMap.ZoomLevel = 15;
  738. sfMapLayer.GeoCoordinates = new Point(location.Latitude, location.Longitude);
  739. MapMarker marker1 = new MapMarker();
  740. marker1.Label = name;
  741. marker1.Latitude = location.Latitude.ToString();
  742. marker1.Longitude = location.Longitude.ToString();
  743. sfMapLayer.Markers.Add(marker1);
  744. sfMapLayer.MarkerSettings.IconSize = 15;
  745. sfMapLayer.MarkerSettings.FontAttributes = FontAttributes.Bold;
  746. sfMapLayer.MarkerSettings.LabelSize = 20;
  747. sfMapLayer.MarkerSettings.LabelColor = Color.DarkRed;
  748. sfMapLayer.MarkerSettings.IconColor = Color.Red;
  749. if (!string.IsNullOrWhiteSpace(name))
  750. {
  751. Title = name;
  752. }
  753. equipment = null;
  754. }
  755. catch (Exception e)
  756. {
  757. await DisplayAlert("Error Loading Address.",
  758. street + " " + city + " Not found.", "OK");
  759. return;
  760. }
  761. }
  762. }
  763. public class OptionString
  764. {
  765. public string Value { get; set; }
  766. public Color Color { get; set; }
  767. public OptionString()
  768. {
  769. Value = "";
  770. Color = Color.White;
  771. }
  772. }
  773. public class EquipmentShell
  774. {
  775. public string Code { get; set; }
  776. public string Description { get; set; }
  777. public double Latitude { get; set; }
  778. public double Longitude { get; set; }
  779. public DateTime LastUpdate { get; set; }
  780. public InABox.Core.Location Location { get; set; }
  781. public EquipmentShell()
  782. {
  783. Code = "";
  784. Description = "";
  785. Latitude = 0.0F;
  786. Longitude = 0.0F;
  787. LastUpdate = DateTime.MinValue;
  788. Location = new InABox.Core.Location();
  789. }
  790. }
  791. public class EquipmentGroupShell
  792. {
  793. public String Code { get; set; }
  794. public Guid ThumbnailID { get; set; }
  795. public EquipmentGroupShell()
  796. {
  797. Code = "";
  798. ThumbnailID = Guid.Empty;
  799. }
  800. }
  801. }