QAFormViewer.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  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. Children.Clear();
  157. foreach (DFLayoutControl element in _layout.Elements)
  158. LoadViewAccordingToElement(element);
  159. foreach (var header in headersToCollapse)
  160. AdjustHeaderSection(header, false);
  161. }
  162. private static void SetRowHeight(string row, RowDefinition def)
  163. {
  164. if (int.TryParse(row, out int rowHeight))
  165. def.Height = new GridLength(Math.Max(60, rowHeight), GridUnitType.Absolute);
  166. else if (row.Contains("*"))
  167. {
  168. def.Height = int.TryParse(row.Substring(0, row.IndexOf("*")), out int result)
  169. ? new GridLength(result, GridUnitType.Star)
  170. : new GridLength(1, GridUnitType.Star);
  171. }
  172. else
  173. def.Height = new GridLength(1, GridUnitType.Auto);
  174. }
  175. private static ColumnDefinition SetColumnWidth(string col, ColumnDefinition def)
  176. {
  177. if (int.TryParse(col, out int colWidth))
  178. def = new ColumnDefinition { Width = new GridLength(colWidth, GridUnitType.Absolute) };
  179. else if (col.Contains("*"))
  180. {
  181. def = int.TryParse(col.Substring(0, col.IndexOf("*")), out int result)
  182. ? new ColumnDefinition { Width = new GridLength(result, GridUnitType.Star) }
  183. : new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };
  184. }
  185. return def;
  186. }
  187. private void LoadViewAccordingToElement(DFLayoutControl element)
  188. {
  189. // Not sure why this is here - perhaps to ry and handle malformed element definitions?
  190. if (string.IsNullOrEmpty(element.Description))
  191. return;
  192. if (element is DFLayoutLabel l)
  193. {
  194. var result = new DigitalFormLabel() { Definition = l };
  195. AddViewToGrid(result, element);
  196. }
  197. else if (element is DFLayoutImage img )
  198. {
  199. var result = new DigitalFormImage() { Definition = img };
  200. AddViewToGrid(result, element);
  201. }
  202. else if (element is DFLayoutHeader hdr)
  203. {
  204. var result = new DigitalFormHeader() { Definition = hdr };
  205. result.CollapsedChanged += (sender, args) => AdjustHeaderSection(result, result.Collapsed);
  206. if (hdr.Collapsed)
  207. headersToCollapse.Add(result);
  208. AddViewToGrid(result, element);
  209. }
  210. else if (element is DFLayoutBooleanField b)
  211. CreateView<DigitalFormBoolean, DFLayoutBooleanField, DFLayoutBooleanFieldProperties, bool, bool?>(b);
  212. else if (element is DFLayoutStringField s)
  213. {
  214. if (s.Properties.PopupEditor)
  215. CreateView<DigitalFormStringPopup, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  216. else if (s.Properties.TextWrapping)
  217. CreateView<DigitalFormStringEditor, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  218. else
  219. CreateView<DigitalFormStringEntry, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  220. }
  221. else if (element is DFLayoutIntegerField i)
  222. CreateView<DigitalFormIntegerEntry, DFLayoutIntegerField, DFLayoutIntegerFieldProperties, int, int?>(i);
  223. else if (element is DFLayoutDoubleField d)
  224. CreateView<DigitalFormDoubleEntry, DFLayoutDoubleField, DFLayoutDoubleFieldProperties, double, double?>(d);
  225. else if (element is DFLayoutDateField df)
  226. CreateView<DigitalFormDateEntry, DFLayoutDateField, DFLayoutDateFieldProperties, DateTime, DateTime?>(df);
  227. else if (element is DFLayoutTimeField tf)
  228. CreateView<DigitalFormTimeEntry, DFLayoutTimeField, DFLayoutTimeFieldProperties, TimeSpan,TimeSpan?>(tf);
  229. else if (element is DFLayoutOptionField of)
  230. {
  231. if (of.Properties.OptionType == DFLayoutOptionType.Radio)
  232. CreateView<DigitalFormOptionRadioList, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  233. else if (of.Properties.OptionType == DFLayoutOptionType.Buttons)
  234. CreateView<DigitalFormOptionButtonList, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  235. else
  236. CreateView<DigitalFormOptionComboBox, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  237. }
  238. else if (element is DFLayoutLookupField lf)
  239. {
  240. if (lf.Properties.DisplayType == DFLayoutLookupDisplayType.Combo)
  241. CreateView<DigitalFormLookupComboBox, DFLayoutLookupField, DFLayoutLookupFieldProperties, Guid, DFLayoutLookupValue>(lf);
  242. else
  243. CreateView<DigitalFormLookupButton, DFLayoutLookupField, DFLayoutLookupFieldProperties, Guid, DFLayoutLookupValue>(lf);
  244. }
  245. else if (element is DFLayoutSignaturePad sp)
  246. CreateView<DigitalFormSignature, DFLayoutSignaturePad, DFLayoutSignaturePadProperties, byte[], byte[]?>(sp);
  247. else if (element is DFLayoutEmbeddedImage ei)
  248. CreateView<DigitalFormEmbeddedImage, DFLayoutEmbeddedImage, DFLayoutEmbeddedImageProperties, Guid, DFLayoutEmbeddedMediaValue>(ei);
  249. else if (element is DFLayoutVideoField ev)
  250. CreateView<DigitalFormEmbeddedVideo, DFLayoutVideoField, DFLayoutVideoFieldProperties, byte[], DFLayoutEmbeddedMediaValue>(ev);
  251. else if (element is DFLayoutMultiImage mi)
  252. CreateView<DigitalFormMultiImage, DFLayoutMultiImage, DFLayoutMultiImageProperties, List<Guid>, DFLayoutEmbeddedMediaValues>(mi);
  253. else if (element is DFLayoutMultiSignaturePad ms)
  254. {
  255. CreateView<DigitalFormMultiSignature, DFLayoutMultiSignaturePad, DFLayoutMultiSignaturePadProperties,
  256. Dictionary<string, byte[]>, Dictionary<string, byte[]>?>(ms);
  257. //var tuple = LoadMultiSignaturePad(element);
  258. //AddViewToGrid(tuple.Item1, element);
  259. }
  260. else if (element is DFLayoutAddTaskField at)
  261. {
  262. CreateView<DigitalFormAddTask, DFLayoutAddTaskField, DFLayoutAddTaskFieldProperties,
  263. string?, string?>(at);
  264. //var tuple = LoadAddTaskField(element);
  265. //AddViewToGrid(tuple.Item1, element);
  266. }
  267. }
  268. private TField CreateView<TField, TDefinition, TProperties, TValue, TSerialized>(TDefinition definition)
  269. where TField : View, IDigitalFormField<TDefinition, TProperties, TValue, TSerialized>, new()
  270. where TDefinition : DFLayoutField<TProperties>
  271. where TProperties : DFLayoutFieldProperties<TValue, TSerialized>, new()
  272. {
  273. TField item = new TField()
  274. {
  275. Definition = definition,
  276. IsEnabled = !definition.GetProperties().Secure
  277. && _model.Instance.FormCompleted.IsEmpty()
  278. && string.IsNullOrWhiteSpace(definition.GetPropertyValue<string>("Expression")),
  279. };
  280. item.ValueChanged += (sender, args) =>
  281. {
  282. // Update Object?
  283. var property = args.Definition.GetProperties().Property;
  284. if (!String.IsNullOrWhiteSpace(property))
  285. CoreUtils.SetPropertyValue(_model.Entity,property,args.Value);
  286. foreach (var other in Bindings.Keys.Where(x=>x.Name != args.Definition.Name))
  287. {
  288. var linked = other.GetProperties().Property;
  289. if (!String.IsNullOrWhiteSpace(linked))
  290. {
  291. try
  292. {
  293. var linkedvalue = CoreUtils.GetPropertyValue(_model.Entity, linked);
  294. // Problem - linkedvalue might not be the same as the
  295. //CoreUtils.SetPropertyValue(pairs[other],"Value",linkedvalue);
  296. }
  297. catch (Exception e)
  298. {
  299. MobileLogging.Log(e,"QAFormViewer:Item.ValueChanged()");
  300. }
  301. }
  302. }
  303. // Update ChangedLinkedProperties?
  304. // Run Expressions and Scripts?
  305. // Update Dictionary?
  306. };
  307. Bindings[definition] = item;
  308. AddViewToGrid(item, definition);
  309. return item;
  310. }
  311. private void AddViewToGrid(View view, DFLayoutControl element)
  312. {
  313. //rows and columns coming in from the desktop designer start from 1, not 0 (most of the time??)
  314. SetRow(view, Math.Max(0,element.Row - 1));
  315. SetRowSpan(view, Math.Max(1,element.RowSpan));
  316. SetColumn(view, Math.Max(0,element.Column - 1));
  317. SetColumnSpan(view, Math.Max(1,element.ColumnSpan));
  318. Children.Add(view);
  319. }
  320. private void AdjustHeaderSection(DigitalFormHeader header, bool collapsed)
  321. {
  322. try
  323. {
  324. var thisHeaderRow = GetRow(header);
  325. var headerRows = Children.OfType<DigitalFormHeader>().Select(x => GetRow(x)).OrderBy(x=>x).ToArray();
  326. if (headerRows.Any())
  327. AdjustHeightsToNextHeader(headerRows, thisHeaderRow, collapsed);
  328. else
  329. AdjustHeightsBelowHeader(headerRows, thisHeaderRow, collapsed);
  330. }
  331. catch (Exception ex)
  332. {
  333. MobileLogging.Log(ex, "AdjustHeaderSection()");
  334. }
  335. }
  336. private void AdjustHeightsToNextHeader(int[] headerRows, int thisHeaderRow, bool collapsed)
  337. {
  338. int nextHeaderRow = headerRows[0];
  339. for (int i = thisHeaderRow + 1; i < nextHeaderRow; i++)
  340. AdjustHeight(i, collapsed);
  341. }
  342. private void AdjustHeightsBelowHeader(int[] headerRows, int thisHeaderRow, bool collapsed)
  343. {
  344. for (int i = thisHeaderRow + 1; i < RowDefinitions.Count; i++)
  345. AdjustHeight(i, collapsed);
  346. }
  347. private void AdjustHeight(int i, bool collapsed)
  348. {
  349. var rowdef = RowDefinitions[i];
  350. if (collapsed)
  351. SetRowHeight(_layout.RowHeights[i], rowdef);
  352. else
  353. rowdef.Height = 0;
  354. }
  355. // private Tuple<View, bool> LoadMultiSignaturePad(DFLayoutControl element)
  356. // {
  357. // string value = "";
  358. // DFLayoutMultiSignaturePad dfLayoutMultiSignaturePad = element as DFLayoutMultiSignaturePad;
  359. // DataButtonControl button = new DataButtonControl
  360. // {
  361. // Text = "Add Signatures",
  362. // };
  363. // if (Storage.TryGetValue(dfLayoutMultiSignaturePad.Name, out value))
  364. // {
  365. // button.Data = value;
  366. // }
  367. // MultiSignaturePad multiSignaturePad = new MultiSignaturePad(button.Data);
  368. // multiSignaturePad.OnMultiSignatureSaved += (result) =>
  369. // {
  370. // button.Data = result;
  371. // };
  372. // button.Clicked += (object sender, MobileButtonClickEventArgs e) =>
  373. // {
  374. // Navigation.PushAsync(multiSignaturePad);
  375. // };
  376. //
  377. // if (dfLayoutMultiSignaturePad.Properties.Required)
  378. // {
  379. // button.BackgroundColor = isRequiredColor;
  380. // button.BorderColor = isRequiredFrame;
  381. // }
  382. // else if (!_model.Instance.FormCompleted.IsEmpty())
  383. // {
  384. // button.BackgroundColor = Color.Silver;
  385. // button.BorderColor = Color.Gray;
  386. // }
  387. //
  388. // return new Tuple<View, bool>(button, dfLayoutMultiSignaturePad.Properties.Required);
  389. // }
  390. // private Tuple<View, bool> LoadAddTaskField(DFLayoutControl element)
  391. // {
  392. // string value = "";
  393. // DFLayoutAddTaskField field = element as DFLayoutAddTaskField;
  394. // DFCreateTaskView taskView = new DFCreateTaskView();
  395. // taskView.OnAddTaskButtonClicked += () =>
  396. // {
  397. // AddEditTask addEditTask = new AddEditTask(Guid.Empty, "New task from Digital Form");
  398. // if (field.Properties.TaskType != null)
  399. // {
  400. // addEditTask.kanban.Type.ID = field.Properties.TaskType.ID;
  401. // try
  402. // {
  403. // addEditTask.kanban.Type.Description = new Client<KanbanType>().Query(
  404. // new Filter<KanbanType>(x => x.ID).IsEqualTo(field.Properties.TaskType.ID),
  405. // new Columns<KanbanType>(x => x.Description)
  406. // ).Rows.FirstOrDefault()?.Get<KanbanType,String>(c=>c.Description) ?? string.Empty;
  407. // }
  408. // catch (Exception ex)
  409. // {
  410. // MobileLogging.Log(ex,"LoadAddTaskField");
  411. // }
  412. // addEditTask.UpdateScreen(true);
  413. // }
  414. // addEditTask.OnTaskSaved += (taskNumber) =>
  415. // {
  416. // taskView.DisableButton();
  417. // taskView.TaskNumber = taskNumber.ToString();
  418. // };
  419. // Navigation.PushAsync(addEditTask);
  420. // };
  421. // if (Storage.TryGetValue(field.Name, out value))
  422. // {
  423. // taskView.TaskNumber = value;
  424. // taskView.DisableButton();
  425. // }
  426. //
  427. // return new Tuple<View, bool>(taskView, field.Properties.Required);
  428. // }
  429. #endregion
  430. #region Checks / Custom methods
  431. private void CheckRequired(DFLayoutField field)
  432. {
  433. if (field is DFLayoutStringField)
  434. {
  435. if ((field as DFLayoutStringField).Properties.Required)
  436. {
  437. isRequiredEmpty = true;
  438. isRequiredMessage = (field as DFLayoutStringField).Description;
  439. }
  440. }
  441. else if (field is DFLayoutIntegerField)
  442. {
  443. if ((field as DFLayoutIntegerField).Properties.Required)
  444. {
  445. isRequiredEmpty = true;
  446. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  447. }
  448. }
  449. else if (field is DFLayoutDoubleField)
  450. {
  451. if ((field as DFLayoutDoubleField).Properties.Required)
  452. {
  453. {
  454. isRequiredEmpty = true;
  455. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  456. }
  457. }
  458. }
  459. else if (field is DFLayoutBooleanField)
  460. {
  461. if ((field as DFLayoutBooleanField).Properties.Required)
  462. {
  463. {
  464. isRequiredEmpty = true;
  465. isRequiredMessage = (field as DFLayoutBooleanField).Description;
  466. }
  467. }
  468. }
  469. else if (field is DFLayoutDateField)
  470. {
  471. if ((field as DFLayoutDateField).Properties.Required)
  472. {
  473. {
  474. isRequiredEmpty = true;
  475. isRequiredMessage = (field as DFLayoutDateField).Description;
  476. }
  477. }
  478. }
  479. else if (field is DFLayoutTimeField)
  480. {
  481. if ((field as DFLayoutTimeField).Properties.Required)
  482. {
  483. {
  484. isRequiredEmpty = true;
  485. isRequiredMessage = (field as DFLayoutTimeField).Description;
  486. }
  487. }
  488. }
  489. else if (field is DFLayoutOptionField)
  490. {
  491. if ((field as DFLayoutOptionField).Properties.Required)
  492. {
  493. {
  494. isRequiredEmpty = true;
  495. isRequiredMessage = (field as DFLayoutOptionField).Description;
  496. }
  497. }
  498. }
  499. else if (field is DFLayoutLookupField)
  500. {
  501. if ((field as DFLayoutLookupField).Properties.Required)
  502. {
  503. {
  504. isRequiredEmpty = true;
  505. isRequiredMessage = (field as DFLayoutLookupField).Description;
  506. }
  507. }
  508. }
  509. else if (field is DFLayoutSignaturePad)
  510. {
  511. if ((field as DFLayoutSignaturePad).Properties.Required)
  512. {
  513. {
  514. isRequiredEmpty = true;
  515. isRequiredMessage = (field as DFLayoutSignaturePad).Description;
  516. }
  517. }
  518. }
  519. else if (field is DFLayoutEmbeddedImage)
  520. {
  521. if ((field as DFLayoutEmbeddedImage).Properties.Required)
  522. {
  523. {
  524. isRequiredEmpty = true;
  525. isRequiredMessage = (field as DFLayoutEmbeddedImage).Description;
  526. }
  527. }
  528. }
  529. else if (field is DFLayoutMultiImage)
  530. {
  531. if ((field as DFLayoutMultiImage).Properties.Required)
  532. {
  533. {
  534. isRequiredEmpty = true;
  535. isRequiredMessage = (field as DFLayoutMultiImage).Description;
  536. }
  537. }
  538. }
  539. else if (field is DFLayoutMultiSignaturePad)
  540. {
  541. if ((field as DFLayoutMultiSignaturePad).Properties.Required)
  542. {
  543. {
  544. isRequiredEmpty = true;
  545. isRequiredMessage = (field as DFLayoutMultiSignaturePad).Description;
  546. }
  547. }
  548. }
  549. }
  550. //
  551. // {
  552. // StreamImageSource streamImageSource = (StreamImageSource)source;
  553. // System.Threading.CancellationToken cancellationToken = System.Threading.CancellationToken.None;
  554. // Task<Stream> task = streamImageSource.Stream(cancellationToken);
  555. // Stream stream = task.Result;
  556. // byte[] bytes = new byte[stream.Length];
  557. // stream.Read(bytes, 0, bytes.Length);
  558. // string s = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
  559. // return s;
  560. // }
  561. //
  562. // private string FindIDForDesignLookupField(DataButtonControl button)
  563. // {
  564. // try
  565. // {
  566. // string userInputValue = button.Data;
  567. // string guidString = "";
  568. // if (userInputValue != nullOrInvalidType)
  569. // {
  570. // foreach (KeyValuePair<DFLayoutLookupField, Dictionary<Guid, string>> pair in dfLayoutLookupFieldLookupOptions)
  571. // {
  572. // foreach (KeyValuePair<Guid, string> innerPair in pair.Value)
  573. // {
  574. // if (innerPair.Value == userInputValue)
  575. // {
  576. // guidString = innerPair.Key.ToString();
  577. // }
  578. // }
  579. // }
  580. // }
  581. //
  582. // return guidString;
  583. // }
  584. // catch (Exception e)
  585. // {
  586. // MobileLogging.Log(e,"FindIDForDesignLookupField");
  587. // return "";
  588. // }
  589. // }
  590. #endregion
  591. #region Save Completion
  592. //point of determination for whether or not QA form gets completed or saved for later
  593. private void UpdateModel(DFSaveStorage save, bool saveForLater, bool deleteform)
  594. {
  595. if (save.Count() > 0 && _model != null)
  596. {
  597. // Blobs are uploaded in the background by DigitalFormDocumentHandler class,
  598. // so the blob breakup doesn't have to happen anymore :-)
  599. DigitalForm.SerializeFormData(_model.Instance, _model.Variables, save);
  600. if (_model.Instance.FormStarted == DateTime.MinValue)
  601. _model.Instance.FormStarted = timeStarted;
  602. _model.Instance.FormOpen += (DateTime.Now - timeStarted);
  603. if (!saveForLater)
  604. {
  605. _model.Instance.FormCompleted = DateTime.Now;
  606. _model.Instance.FormCompletedBy.ID = App.Data.Me.UserID;
  607. _model.Instance.Location.Longitude = location.Longitude;
  608. _model.Instance.Location.Latitude = location.Latitude;
  609. _model.Instance.Location.Timestamp = _model.Instance.FormCompleted;
  610. }
  611. if (deleteform)
  612. _model.Instance.FormCancelled = DateTime.Now;
  613. _model.Update(null);
  614. }
  615. }
  616. #endregion
  617. #region Expressions
  618. public object GetFieldValue(string name)
  619. {
  620. try
  621. {
  622. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, name));
  623. if (definition != null)
  624. return CoreUtils.GetPropertyValue(Bindings[definition],"Value");
  625. }
  626. catch (Exception e)
  627. {
  628. MobileLogging.Log(e,"SetFieldValue");
  629. }
  630. return null;
  631. }
  632. public void SetFieldValue(string name, object value)
  633. {
  634. try
  635. {
  636. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, name));
  637. if (definition != null)
  638. CoreUtils.SetPropertyValue(Bindings[definition],"Value",value);
  639. }
  640. catch (Exception e)
  641. {
  642. MobileLogging.Log(e,"SetFieldValue");
  643. }
  644. }
  645. public object GetFieldData(string fieldName, string dataField)
  646. {
  647. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, fieldName));
  648. if ((definition != null) && (Bindings[definition] is DigitalFormLookupView lookup))
  649. return lookup.OtherValue(dataField);
  650. return null;
  651. }
  652. public void SetFieldColour(string field, System.Drawing.Color? colour = null)
  653. {
  654. if (colour != null)
  655. {
  656. try
  657. {
  658. System.Drawing.Color color = (System.Drawing.Color)colour;
  659. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, field));
  660. if (definition != null)
  661. {
  662. Bindings[definition].BackgroundColor = Color.FromRgba(
  663. Convert.ToDouble(color.R),
  664. Convert.ToDouble(color.G),
  665. Convert.ToDouble(color.B),
  666. Convert.ToDouble(color.A)
  667. );
  668. }
  669. }
  670. catch (Exception e)
  671. {
  672. MobileLogging.Log(e,"SetFieldColor");
  673. }
  674. }
  675. }
  676. #endregion
  677. }
  678. }