QAFormViewer.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using System.Linq;
  5. using Xamarin.Forms;
  6. using InABox.Core;
  7. using InABox.Clients;
  8. using System.IO;
  9. using InABox.Mobile;
  10. using Comal.Classes;
  11. using PRSClasses;
  12. namespace PRS.Mobile
  13. {
  14. public class QAFormViewer : Grid, IDFRenderer
  15. {
  16. #region Fields
  17. // This connects the DFLayout elements to the respective UI elements
  18. public readonly Dictionary<DFLayoutField, IDigitalFormField> Bindings = new();
  19. // These get saved into FormData
  20. public DFLoadStorage Storage { get; private set; }
  21. // These are used to pre-populate the next instance of this form
  22. public DFLoadStorage RetainedData { get; private set; }
  23. //public readonly Dictionary<DFLayoutLookupField, Dictionary<Guid, string>> dfLayoutLookupFieldLookupOptions = new();
  24. private DFLayout _layout = new();
  25. private IDigitalFormDataModel? _model;
  26. const string nullOrInvalidType = "Null or Invalid Type";
  27. private readonly List<string> useSavedSignatures = new();
  28. public readonly List<string> errors = new();
  29. public bool isRequiredEmpty { get; set; }
  30. public string isRequiredMessage { get; set; } = "";
  31. private readonly Location location = new();
  32. private readonly Color isRequiredColor = Color.DarkOrange;
  33. private readonly Color isRequiredFrame = Color.Firebrick;
  34. private DateTime timeStarted = DateTime.MinValue;
  35. readonly List<DigitalFormHeader> headersToCollapse = new();
  36. #endregion
  37. #region Constructor
  38. public QAFormViewer()
  39. {
  40. Storage = new DFLoadStorage();
  41. RetainedData = new DFLoadStorage();
  42. }
  43. public QAFormViewer(IDigitalFormDataModel model, DFLayout layout,
  44. Guid job = default) : this()
  45. {
  46. Load(model, layout, job);
  47. }
  48. public void Load(IDigitalFormDataModel model, DFLayout layout, Guid job = default)
  49. {
  50. GetLocation();
  51. timeStarted = DateTime.Now;
  52. _model = model;
  53. _layout = layout;
  54. _layout.Renderer = this;
  55. isRequiredEmpty = false;
  56. isRequiredMessage = "";
  57. LoadFormLayout();
  58. Storage = DigitalForm.DeserializeFormData(_model.Instance) ?? new DFLoadStorage();
  59. LoadData();
  60. }
  61. #endregion
  62. #region Location
  63. private async void GetLocation()
  64. {
  65. await Task.Run(() =>
  66. {
  67. LocationServices locationServices = new LocationServices();
  68. locationServices.OnLocationFound += LocationFound;
  69. locationServices.OnLocationError += LocationError;
  70. locationServices.GetLocation();
  71. });
  72. }
  73. private void LocationFound(LocationServices sender)
  74. {
  75. location.Latitude = sender.Latitude;
  76. location.Longitude = sender.Longitude;
  77. }
  78. private void LocationError(LocationServices sender, Exception error)
  79. {
  80. errors.Add("Location error: " + error.Message);
  81. }
  82. #endregion Location
  83. #region Load and Save Data
  84. public void LoadData()
  85. {
  86. foreach (DFLayoutField field in Bindings.Keys)
  87. {
  88. try
  89. {
  90. if (RetainedData.HasValue(field.Name))
  91. Bindings[field].Deserialize(RetainedData.GetEntry(field.Name));
  92. else if (Storage.HasValue(field.Name))
  93. Bindings[field].Deserialize(Storage.GetEntry(field.Name));
  94. _layout.ChangeField(field.Name);
  95. }
  96. catch (Exception ex)
  97. {
  98. InABox.Mobile.MobileLogging.Log(ex,$"LoadData({field.Name})");
  99. }
  100. }
  101. }
  102. public void SaveData(bool saveForLater)
  103. {
  104. try
  105. {
  106. var save = new DFSaveStorage();
  107. var retained = new DFSaveStorage();
  108. foreach (DFLayoutField field in Bindings.Keys)
  109. {
  110. var entry = save.GetEntry(field.Name);
  111. Bindings[field].Serialize(entry);
  112. if (field.GetProperties().Retain)
  113. {
  114. var retentry = retained.GetEntry(field.Name);
  115. Bindings[field].Serialize(retentry);
  116. }
  117. }
  118. UpdateModel(save, saveForLater);
  119. Storage.Clear();
  120. RetainedData.Load(retained.FormData, retained.BlobData);
  121. }
  122. catch (Exception ex)
  123. {
  124. InABox.Mobile.MobileLogging.Log(ex,"SaveData");
  125. }
  126. }
  127. #endregion
  128. #region Load Form Layout
  129. private void LoadFormLayout()
  130. {
  131. RowDefinitions.Clear();
  132. foreach (var row in _layout.RowHeights)
  133. {
  134. RowDefinition def = new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) };
  135. SetRowHeight(row, def);
  136. RowDefinitions.Add(def);
  137. }
  138. ColumnDefinitions.Clear();
  139. foreach (var col in _layout.ColumnWidths)
  140. {
  141. ColumnDefinition def = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) };
  142. def = SetColumnWidth(col, def);
  143. ColumnDefinitions.Add(def);
  144. }
  145. Children.Clear();
  146. foreach (DFLayoutControl element in _layout.Elements)
  147. LoadViewAccordingToElement(element);
  148. foreach (var header in headersToCollapse)
  149. AdjustHeaderSection(header, false);
  150. }
  151. private static void SetRowHeight(string row, RowDefinition def)
  152. {
  153. if (int.TryParse(row, out int rowHeight))
  154. def.Height = new GridLength(Math.Max(60, rowHeight), GridUnitType.Absolute);
  155. else if (row.Contains("*"))
  156. {
  157. def.Height = int.TryParse(row.Substring(0, row.IndexOf("*")), out int result)
  158. ? new GridLength(result, GridUnitType.Star)
  159. : new GridLength(1, GridUnitType.Star);
  160. }
  161. else
  162. def.Height = new GridLength(1, GridUnitType.Auto);
  163. }
  164. private static ColumnDefinition SetColumnWidth(string col, ColumnDefinition def)
  165. {
  166. if (int.TryParse(col, out int colWidth))
  167. def = new ColumnDefinition { Width = new GridLength(colWidth, GridUnitType.Absolute) };
  168. else if (col.Contains("*"))
  169. {
  170. def = int.TryParse(col.Substring(0, col.IndexOf("*")), out int result)
  171. ? new ColumnDefinition { Width = new GridLength(result, GridUnitType.Star) }
  172. : new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };
  173. }
  174. return def;
  175. }
  176. private void LoadViewAccordingToElement(DFLayoutControl element)
  177. {
  178. // Not sure why this is here - perhaps to ry and handle malformed element definitions?
  179. if (string.IsNullOrEmpty(element.Description))
  180. return;
  181. if (element is DFLayoutLabel l)
  182. {
  183. var result = new DigitalFormLabel() { Definition = l };
  184. AddViewToGrid(result, element);
  185. }
  186. else if (element is DFLayoutImage img )
  187. {
  188. var result = new DigitalFormImage() { Definition = img };
  189. AddViewToGrid(result, element);
  190. }
  191. else if (element is DFLayoutHeader hdr)
  192. {
  193. var result = new DigitalFormHeader() { Definition = hdr };
  194. result.CollapsedChanged += (sender, args) => AdjustHeaderSection(result, result.Collapsed);
  195. if (hdr.Collapsed)
  196. headersToCollapse.Add(result);
  197. AddViewToGrid(result, element);
  198. }
  199. else if (element is DFLayoutBooleanField b)
  200. CreateView<DigitalFormBoolean, DFLayoutBooleanField, DFLayoutBooleanFieldProperties, bool, bool?>(b);
  201. else if (element is DFLayoutStringField s)
  202. {
  203. if (s.Properties.PopupEditor)
  204. CreateView<DigitalFormStringPopup, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  205. else if (s.Properties.TextWrapping)
  206. CreateView<DigitalFormStringEditor, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  207. else
  208. CreateView<DigitalFormStringEntry, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  209. }
  210. else if (element is DFLayoutIntegerField i)
  211. CreateView<DigitalFormIntegerEntry, DFLayoutIntegerField, DFLayoutIntegerFieldProperties, int, int?>(i);
  212. else if (element is DFLayoutDoubleField d)
  213. CreateView<DigitalFormDoubleEntry, DFLayoutDoubleField, DFLayoutDoubleFieldProperties, double, double?>(d);
  214. else if (element is DFLayoutDateField df)
  215. CreateView<DigitalFormDateEntry, DFLayoutDateField, DFLayoutDateFieldProperties, DateTime, DateTime?>(df);
  216. else if (element is DFLayoutTimeField tf)
  217. CreateView<DigitalFormTimeEntry, DFLayoutTimeField, DFLayoutTimeFieldProperties, TimeSpan,TimeSpan?>(tf);
  218. else if (element is DFLayoutOptionField of)
  219. {
  220. if (of.Properties.OptionType == DFLayoutOptionType.Radio)
  221. CreateView<DigitalFormOptionRadioList, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  222. else if (of.Properties.OptionType == DFLayoutOptionType.Buttons)
  223. CreateView<DigitalFormOptionButtonList, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  224. else
  225. CreateView<DigitalFormOptionComboBox, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  226. }
  227. else if (element is DFLayoutLookupField lf)
  228. {
  229. if (lf.Properties.DisplayType == DFLayoutLookupDisplayType.Combo)
  230. CreateView<DigitalFormLookupComboBox, DFLayoutLookupField, DFLayoutLookupFieldProperties, Guid, DFLayoutLookupValue>(lf);
  231. else
  232. CreateView<DigitalFormLookupButton, DFLayoutLookupField, DFLayoutLookupFieldProperties, Guid, DFLayoutLookupValue>(lf);
  233. }
  234. else if (element is DFLayoutSignaturePad sp)
  235. CreateView<DigitalFormSignature, DFLayoutSignaturePad, DFLayoutSignaturePadProperties, byte[], byte[]?>(sp);
  236. else if (element is DFLayoutEmbeddedImage ei)
  237. CreateView<DigitalFormEmbeddedImage, DFLayoutEmbeddedImage, DFLayoutEmbeddedImageProperties, Guid, DFLayoutEmbeddedMediaValue>(ei);
  238. else if (element is DFLayoutVideoField ev)
  239. CreateView<DigitalFormEmbeddedVideo, DFLayoutVideoField, DFLayoutVideoFieldProperties, byte[], DFLayoutEmbeddedMediaValue>(ev);
  240. else if (element is DFLayoutMultiImage mi)
  241. CreateView<DigitalFormMultiImage, DFLayoutMultiImage, DFLayoutMultiImageProperties, List<Guid>, DFLayoutEmbeddedMediaValues>(mi);
  242. else if (element is DFLayoutMultiSignaturePad ms)
  243. {
  244. CreateView<DigitalFormMultiSignature, DFLayoutMultiSignaturePad, DFLayoutMultiSignaturePadProperties,
  245. Dictionary<string, byte[]>, Dictionary<string, byte[]>?>(ms);
  246. //var tuple = LoadMultiSignaturePad(element);
  247. //AddViewToGrid(tuple.Item1, element);
  248. }
  249. else if (element is DFLayoutAddTaskField at)
  250. {
  251. CreateView<DigitalFormAddTask, DFLayoutAddTaskField, DFLayoutAddTaskFieldProperties,
  252. string?, string?>(at);
  253. //var tuple = LoadAddTaskField(element);
  254. //AddViewToGrid(tuple.Item1, element);
  255. }
  256. }
  257. private TField CreateView<TField, TDefinition, TProperties, TValue, TSerialized>(TDefinition definition)
  258. where TField : View, IDigitalFormField<TDefinition, TProperties, TValue, TSerialized>, new()
  259. where TDefinition : DFLayoutField<TProperties>
  260. where TProperties : DFLayoutFieldProperties<TValue, TSerialized>, new()
  261. {
  262. TField item = new TField()
  263. {
  264. Definition = definition,
  265. IsEnabled = !definition.GetProperties().Secure
  266. && _model.Instance.FormCompleted.IsEmpty()
  267. && string.IsNullOrWhiteSpace(definition.GetPropertyValue<string>("Expression")),
  268. };
  269. item.ValueChanged += (sender, args) =>
  270. {
  271. // Update Object?
  272. var property = args.Definition.GetProperties().Property;
  273. if (!String.IsNullOrWhiteSpace(property))
  274. CoreUtils.SetPropertyValue(_model.Entity,property,args.Value);
  275. foreach (var other in Bindings.Keys.Where(x=>x.Name != args.Definition.Name))
  276. {
  277. var linked = other.GetProperties().Property;
  278. if (!String.IsNullOrWhiteSpace(linked))
  279. {
  280. var linkedvalue = CoreUtils.GetPropertyValue(_model.Entity, linked);
  281. // Problem - linkedvalue might not be the same as the
  282. //CoreUtils.SetPropertyValue(pairs[other],"Value",linkedvalue);
  283. }
  284. }
  285. // Update ChangedLinkedProperties?
  286. // Run Expressions and Scripts?
  287. // Update Dictionary?
  288. };
  289. Bindings[definition] = item;
  290. AddViewToGrid(item, definition);
  291. return item;
  292. }
  293. private void AddViewToGrid(View view, DFLayoutControl element)
  294. {
  295. //rows and columns coming in from the desktop designer start from 1, not 0 (most of the time??)
  296. SetRow(view, Math.Max(0,element.Row - 1));
  297. SetRowSpan(view, Math.Max(1,element.RowSpan));
  298. SetColumn(view, Math.Max(0,element.Column - 1));
  299. SetColumnSpan(view, Math.Max(1,element.ColumnSpan));
  300. Children.Add(view);
  301. }
  302. private void AdjustHeaderSection(DigitalFormHeader header, bool collapsed)
  303. {
  304. try
  305. {
  306. var thisHeaderRow = GetRow(header);
  307. var headerRows = Children.OfType<DigitalFormHeader>().Select(x => GetRow(x)).OrderBy(x=>x).ToArray();
  308. if (headerRows.Any())
  309. AdjustHeightsToNextHeader(headerRows, thisHeaderRow, collapsed);
  310. else
  311. AdjustHeightsBelowHeader(headerRows, thisHeaderRow, collapsed);
  312. }
  313. catch (Exception ex)
  314. {
  315. MobileLogging.Log(ex, "AdjustHeaderSection()");
  316. }
  317. }
  318. private void AdjustHeightsToNextHeader(int[] headerRows, int thisHeaderRow, bool collapsed)
  319. {
  320. int nextHeaderRow = headerRows[0];
  321. for (int i = thisHeaderRow + 1; i < nextHeaderRow; i++)
  322. AdjustHeight(i, collapsed);
  323. }
  324. private void AdjustHeightsBelowHeader(int[] headerRows, int thisHeaderRow, bool collapsed)
  325. {
  326. for (int i = thisHeaderRow + 1; i < RowDefinitions.Count; i++)
  327. AdjustHeight(i, collapsed);
  328. }
  329. private void AdjustHeight(int i, bool collapsed)
  330. {
  331. var rowdef = RowDefinitions[i];
  332. if (collapsed)
  333. SetRowHeight(_layout.RowHeights[i], rowdef);
  334. else
  335. rowdef.Height = 0;
  336. }
  337. // private Tuple<View, bool> LoadMultiSignaturePad(DFLayoutControl element)
  338. // {
  339. // string value = "";
  340. // DFLayoutMultiSignaturePad dfLayoutMultiSignaturePad = element as DFLayoutMultiSignaturePad;
  341. // DataButtonControl button = new DataButtonControl
  342. // {
  343. // Text = "Add Signatures",
  344. // };
  345. // if (Storage.TryGetValue(dfLayoutMultiSignaturePad.Name, out value))
  346. // {
  347. // button.Data = value;
  348. // }
  349. // MultiSignaturePad multiSignaturePad = new MultiSignaturePad(button.Data);
  350. // multiSignaturePad.OnMultiSignatureSaved += (result) =>
  351. // {
  352. // button.Data = result;
  353. // };
  354. // button.Clicked += (object sender, MobileButtonClickEventArgs e) =>
  355. // {
  356. // Navigation.PushAsync(multiSignaturePad);
  357. // };
  358. //
  359. // if (dfLayoutMultiSignaturePad.Properties.Required)
  360. // {
  361. // button.BackgroundColor = isRequiredColor;
  362. // button.BorderColor = isRequiredFrame;
  363. // }
  364. // else if (!_model.Instance.FormCompleted.IsEmpty())
  365. // {
  366. // button.BackgroundColor = Color.Silver;
  367. // button.BorderColor = Color.Gray;
  368. // }
  369. //
  370. // return new Tuple<View, bool>(button, dfLayoutMultiSignaturePad.Properties.Required);
  371. // }
  372. // private Tuple<View, bool> LoadAddTaskField(DFLayoutControl element)
  373. // {
  374. // string value = "";
  375. // DFLayoutAddTaskField field = element as DFLayoutAddTaskField;
  376. // DFCreateTaskView taskView = new DFCreateTaskView();
  377. // taskView.OnAddTaskButtonClicked += () =>
  378. // {
  379. // AddEditTask addEditTask = new AddEditTask(Guid.Empty, "New task from Digital Form");
  380. // if (field.Properties.TaskType != null)
  381. // {
  382. // addEditTask.kanban.Type.ID = field.Properties.TaskType.ID;
  383. // try
  384. // {
  385. // addEditTask.kanban.Type.Description = new Client<KanbanType>().Query(
  386. // new Filter<KanbanType>(x => x.ID).IsEqualTo(field.Properties.TaskType.ID),
  387. // new Columns<KanbanType>(x => x.Description)
  388. // ).Rows.FirstOrDefault()?.Get<KanbanType,String>(c=>c.Description) ?? "";
  389. // }
  390. // catch (Exception ex)
  391. // {
  392. // MobileLogging.Log(ex,"LoadAddTaskField");
  393. // }
  394. // addEditTask.UpdateScreen(true);
  395. // }
  396. // addEditTask.OnTaskSaved += (taskNumber) =>
  397. // {
  398. // taskView.DisableButton();
  399. // taskView.TaskNumber = taskNumber.ToString();
  400. // };
  401. // Navigation.PushAsync(addEditTask);
  402. // };
  403. // if (Storage.TryGetValue(field.Name, out value))
  404. // {
  405. // taskView.TaskNumber = value;
  406. // taskView.DisableButton();
  407. // }
  408. //
  409. // return new Tuple<View, bool>(taskView, field.Properties.Required);
  410. // }
  411. #endregion
  412. #region Checks / Custom methods
  413. private void CheckRequired(DFLayoutField field)
  414. {
  415. if (field is DFLayoutStringField)
  416. {
  417. if ((field as DFLayoutStringField).Properties.Required)
  418. {
  419. isRequiredEmpty = true;
  420. isRequiredMessage = (field as DFLayoutStringField).Description;
  421. }
  422. }
  423. else if (field is DFLayoutIntegerField)
  424. {
  425. if ((field as DFLayoutIntegerField).Properties.Required)
  426. {
  427. isRequiredEmpty = true;
  428. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  429. }
  430. }
  431. else if (field is DFLayoutDoubleField)
  432. {
  433. if ((field as DFLayoutDoubleField).Properties.Required)
  434. {
  435. {
  436. isRequiredEmpty = true;
  437. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  438. }
  439. }
  440. }
  441. else if (field is DFLayoutBooleanField)
  442. {
  443. if ((field as DFLayoutBooleanField).Properties.Required)
  444. {
  445. {
  446. isRequiredEmpty = true;
  447. isRequiredMessage = (field as DFLayoutBooleanField).Description;
  448. }
  449. }
  450. }
  451. else if (field is DFLayoutDateField)
  452. {
  453. if ((field as DFLayoutDateField).Properties.Required)
  454. {
  455. {
  456. isRequiredEmpty = true;
  457. isRequiredMessage = (field as DFLayoutDateField).Description;
  458. }
  459. }
  460. }
  461. else if (field is DFLayoutTimeField)
  462. {
  463. if ((field as DFLayoutTimeField).Properties.Required)
  464. {
  465. {
  466. isRequiredEmpty = true;
  467. isRequiredMessage = (field as DFLayoutTimeField).Description;
  468. }
  469. }
  470. }
  471. else if (field is DFLayoutOptionField)
  472. {
  473. if ((field as DFLayoutOptionField).Properties.Required)
  474. {
  475. {
  476. isRequiredEmpty = true;
  477. isRequiredMessage = (field as DFLayoutOptionField).Description;
  478. }
  479. }
  480. }
  481. else if (field is DFLayoutLookupField)
  482. {
  483. if ((field as DFLayoutLookupField).Properties.Required)
  484. {
  485. {
  486. isRequiredEmpty = true;
  487. isRequiredMessage = (field as DFLayoutLookupField).Description;
  488. }
  489. }
  490. }
  491. else if (field is DFLayoutSignaturePad)
  492. {
  493. if ((field as DFLayoutSignaturePad).Properties.Required)
  494. {
  495. {
  496. isRequiredEmpty = true;
  497. isRequiredMessage = (field as DFLayoutSignaturePad).Description;
  498. }
  499. }
  500. }
  501. else if (field is DFLayoutEmbeddedImage)
  502. {
  503. if ((field as DFLayoutEmbeddedImage).Properties.Required)
  504. {
  505. {
  506. isRequiredEmpty = true;
  507. isRequiredMessage = (field as DFLayoutEmbeddedImage).Description;
  508. }
  509. }
  510. }
  511. else if (field is DFLayoutMultiImage)
  512. {
  513. if ((field as DFLayoutMultiImage).Properties.Required)
  514. {
  515. {
  516. isRequiredEmpty = true;
  517. isRequiredMessage = (field as DFLayoutMultiImage).Description;
  518. }
  519. }
  520. }
  521. else if (field is DFLayoutMultiSignaturePad)
  522. {
  523. if ((field as DFLayoutMultiSignaturePad).Properties.Required)
  524. {
  525. {
  526. isRequiredEmpty = true;
  527. isRequiredMessage = (field as DFLayoutMultiSignaturePad).Description;
  528. }
  529. }
  530. }
  531. }
  532. //
  533. // {
  534. // StreamImageSource streamImageSource = (StreamImageSource)source;
  535. // System.Threading.CancellationToken cancellationToken = System.Threading.CancellationToken.None;
  536. // Task<Stream> task = streamImageSource.Stream(cancellationToken);
  537. // Stream stream = task.Result;
  538. // byte[] bytes = new byte[stream.Length];
  539. // stream.Read(bytes, 0, bytes.Length);
  540. // string s = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
  541. // return s;
  542. // }
  543. //
  544. // private string FindIDForDesignLookupField(DataButtonControl button)
  545. // {
  546. // try
  547. // {
  548. // string userInputValue = button.Data;
  549. // string guidString = "";
  550. // if (userInputValue != nullOrInvalidType)
  551. // {
  552. // foreach (KeyValuePair<DFLayoutLookupField, Dictionary<Guid, string>> pair in dfLayoutLookupFieldLookupOptions)
  553. // {
  554. // foreach (KeyValuePair<Guid, string> innerPair in pair.Value)
  555. // {
  556. // if (innerPair.Value == userInputValue)
  557. // {
  558. // guidString = innerPair.Key.ToString();
  559. // }
  560. // }
  561. // }
  562. // }
  563. //
  564. // return guidString;
  565. // }
  566. // catch (Exception e)
  567. // {
  568. // MobileLogging.Log(e,"FindIDForDesignLookupField");
  569. // return "";
  570. // }
  571. // }
  572. #endregion
  573. #region Save Completion
  574. public void DeleteForm()
  575. {
  576. _model.Instance.FormCancelled = DateTime.Now;
  577. _model.Update(null);
  578. }
  579. //point of determination for whether or not QA form gets completed or saved for later
  580. private void UpdateModel(DFSaveStorage save, bool saveForLater)
  581. {
  582. if (save.Count() > 0 && _model != null)
  583. {
  584. // Blobs are uploaded in the background by DigitalFormDocumentHandler class,
  585. // so the blob breakup doesn't have to happen anymore :-)
  586. DigitalForm.SerializeFormData(_model.Instance, _model.Variables, save);
  587. if (_model.Instance.FormStarted == DateTime.MinValue)
  588. _model.Instance.FormStarted = timeStarted;
  589. _model.Instance.FormOpen += (DateTime.Now - timeStarted);
  590. if (!saveForLater)
  591. {
  592. _model.Instance.FormCompleted = DateTime.Now;
  593. _model.Instance.FormCompletedBy.ID = App.Data.Me.UserID;
  594. _model.Instance.Location.Longitude = location.Longitude;
  595. _model.Instance.Location.Latitude = location.Latitude;
  596. _model.Instance.Location.Timestamp = _model.Instance.FormCompleted;
  597. }
  598. _model.Update(null);
  599. }
  600. }
  601. #endregion
  602. #region Expressions
  603. public object GetFieldValue(string name)
  604. {
  605. try
  606. {
  607. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, name));
  608. if (definition != null)
  609. return CoreUtils.GetPropertyValue(Bindings[definition],"Value");
  610. }
  611. catch (Exception e)
  612. {
  613. MobileLogging.Log(e,"SetFieldValue");
  614. }
  615. return null;
  616. }
  617. public void SetFieldValue(string name, object value)
  618. {
  619. try
  620. {
  621. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, name));
  622. if (definition != null)
  623. CoreUtils.SetPropertyValue(Bindings[definition],"Value",value);
  624. }
  625. catch (Exception e)
  626. {
  627. MobileLogging.Log(e,"SetFieldValue");
  628. }
  629. }
  630. public object GetFieldData(string fieldName, string dataField)
  631. {
  632. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, fieldName));
  633. if ((definition != null) && (Bindings[definition] is DigitalFormLookupView lookup))
  634. return lookup.OtherValue(dataField);
  635. return null;
  636. }
  637. public void SetFieldColour(string field, System.Drawing.Color? colour = null)
  638. {
  639. if (colour != null)
  640. {
  641. try
  642. {
  643. System.Drawing.Color color = (System.Drawing.Color)colour;
  644. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, field));
  645. if (definition != null)
  646. {
  647. Bindings[definition].BackgroundColor = Color.FromRgba(
  648. Convert.ToDouble(color.R),
  649. Convert.ToDouble(color.G),
  650. Convert.ToDouble(color.B),
  651. Convert.ToDouble(color.A)
  652. );
  653. }
  654. }
  655. catch (Exception e)
  656. {
  657. MobileLogging.Log(e,"SetFieldColor");
  658. }
  659. }
  660. }
  661. #endregion
  662. }
  663. }