QAFormViewer.cs 31 KB

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