QAFormViewer.cs 86 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using System.Threading;
  5. using System.Linq;
  6. using Xamarin.Forms;
  7. using XF.Material.Forms.UI.Dialogs;
  8. using InABox.Core;
  9. using InABox.Clients;
  10. using System.IO;
  11. using InABox.Mobile;
  12. using Syncfusion.XForms.SignaturePad;
  13. using comal.timesheets.Tasks;
  14. using Comal.Classes;
  15. using PRSClasses;
  16. using Newtonsoft.Json;
  17. using Java.Security.Cert;
  18. namespace comal.timesheets.QAForms
  19. {
  20. public class QAFormViewer : Grid, IDFRenderer
  21. {
  22. #region Fields
  23. public Dictionary<DFLayoutField, View> pairs = new Dictionary<DFLayoutField, View>();
  24. public Dictionary<String, String> results = new Dictionary<String, String>();
  25. public Dictionary<String, String> propertyResults = new Dictionary<String, String>();
  26. Dictionary<String, String> loadData = new Dictionary<String, String>();
  27. public Dictionary<DFLayoutLookupField, Dictionary<Guid, string>> dfLayoutLookupFieldLookupOptions = new Dictionary<DFLayoutLookupField, Dictionary<Guid, string>>();
  28. DFLayout dfLayout = null;
  29. public IDigitalFormDataModel model = null;
  30. const string nullOrInvalidType = "Null or Invalid Type";
  31. int rbGroup;
  32. private Guid userID;
  33. bool isRequired = false;
  34. bool readOnly = false;
  35. bool isSecure = false;
  36. bool loadRetainedForm = false;
  37. List<string> useSavedSignatures = new List<string>();
  38. public List<string> errors = new List<string>();
  39. public bool isRequiredEmpty { get; set; }
  40. public string isRequiredMessage { get; set; }
  41. InABox.Core.Location location = new InABox.Core.Location();
  42. Guid digitalFormID = Guid.Empty;
  43. Color isRequiredColor = Color.DarkOrange;
  44. public string FormData = "";
  45. public DateTime FormCompleted = DateTime.MinValue;
  46. public Guid JobID = Guid.Empty;
  47. DateTime timeStarted = DateTime.MinValue;
  48. List<DigitalFormsHeader> headersToCollapse = new List<DigitalFormsHeader>();
  49. int collapsedHeaderCount = 1;
  50. #endregion
  51. #region Constructor
  52. public QAFormViewer(IDigitalFormDataModel _model, DFLayout _dfLayout, bool newForm, bool _readOnly, Guid _jobid = default(Guid))
  53. {
  54. GetLocation();
  55. timeStarted = DateTime.Now;
  56. userID = ClientFactory.UserGuid;
  57. model = _model;
  58. dfLayout = _dfLayout;
  59. dfLayout.Renderer = this;
  60. readOnly = _readOnly;
  61. isRequiredEmpty = false;
  62. loadRetainedForm = false;
  63. isRequiredMessage = "";
  64. JobID = _jobid;
  65. if (RetainedResults.IsFormRetained)
  66. {
  67. loadRetainedForm = true;
  68. }
  69. if (newForm)
  70. {
  71. LoadForm();
  72. }
  73. else if (!newForm)
  74. {
  75. loadData.Clear();
  76. Dictionary<String, Object> data = DigitalForm.DeserializeFormData(model.Instance);
  77. if (data != null)
  78. {
  79. foreach (KeyValuePair<string, object> keyValuePair in data)
  80. {
  81. loadData.Add(keyValuePair.Key, keyValuePair.Value.ToString());
  82. }
  83. }
  84. LoadForm();
  85. }
  86. }
  87. #endregion
  88. #region Location
  89. private async void GetLocation()
  90. {
  91. await Task.Run(() =>
  92. {
  93. LocationServices locationServices = new LocationServices();
  94. locationServices.OnLocationFound += LocationFound;
  95. locationServices.OnLocationError += LocationError;
  96. locationServices.GetLocation();
  97. });
  98. }
  99. private async void LocationFound(LocationServices sender)
  100. {
  101. location.Latitude = sender.Latitude;
  102. location.Longitude = sender.Longitude;
  103. }
  104. private async void LocationError(LocationServices sender, Exception error)
  105. {
  106. errors.Add("Location error: " + error.Message);
  107. }
  108. #endregion Location
  109. #region Load Form Layout
  110. private async void LoadForm()
  111. {
  112. {
  113. LoadRowsAndColumns();
  114. LoadElements();
  115. }
  116. }
  117. private void LoadRowsAndColumns()
  118. {
  119. LoadRows();
  120. LoadColumns();
  121. }
  122. private void LoadRows()
  123. {
  124. foreach (var row in dfLayout.RowHeights)
  125. {
  126. RowDefinition def = new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) };
  127. if (int.TryParse(row, out int rowHeight))
  128. {
  129. def = new RowDefinition { Height = new GridLength(rowHeight, GridUnitType.Absolute) };
  130. if (def.Height.Value < 60)
  131. {
  132. def.SetValue(RowDefinition.HeightProperty, 60);
  133. }
  134. }
  135. else if (row.Contains("*"))
  136. {
  137. if (int.TryParse(row.Substring(0, row.IndexOf("*")), out int result))
  138. {
  139. def = new RowDefinition { Height = new GridLength(result, GridUnitType.Star) };
  140. }
  141. else
  142. def = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };
  143. }
  144. Device.BeginInvokeOnMainThread(() => { RowDefinitions.Add(def); });
  145. }
  146. }
  147. private void LoadColumns()
  148. {
  149. foreach (var col in dfLayout.ColumnWidths)
  150. {
  151. ColumnDefinition def = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) };
  152. if (int.TryParse(col, out int colWidth))
  153. def = new ColumnDefinition { Width = new GridLength(colWidth, GridUnitType.Absolute) };
  154. else if (col.Contains("*"))
  155. {
  156. if (int.TryParse(col.Substring(0, col.IndexOf("*")), out int result))
  157. {
  158. def = new ColumnDefinition { Width = new GridLength(result, GridUnitType.Star) };
  159. }
  160. else
  161. def = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };
  162. }
  163. Device.BeginInvokeOnMainThread(() => { ColumnDefinitions.Add(def); });
  164. }
  165. }
  166. private void LoadElements()
  167. {
  168. rbGroup = 0; //used for customboolean - has to be outside of foreach loop
  169. foreach (DFLayoutControl element in dfLayout.Elements)
  170. {
  171. if (!string.IsNullOrEmpty(element.Description))
  172. {
  173. LoadViewAccordingToElement(element);
  174. }
  175. }
  176. Task.Run(() =>
  177. {
  178. Thread.Sleep(1000);
  179. foreach (var header in headersToCollapse)
  180. {
  181. Device.BeginInvokeOnMainThread(() =>
  182. {
  183. AdjustHeaderSection(header, false);
  184. header.Collapse();
  185. });
  186. }
  187. });
  188. }
  189. #endregion
  190. #region Load Element Methods
  191. private void LoadViewAccordingToElement(DFLayoutControl element)
  192. {
  193. isSecure = false;
  194. if (element is DFLayoutBooleanField)
  195. {
  196. var tuple = LoadCustomBoolean(element);
  197. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  198. }
  199. else if (element is DFLayoutLabel)
  200. {
  201. var tuple = LoadLabel(element);
  202. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  203. }
  204. else if (element is DFLayoutStringField || element is DFLayoutIntegerField || element is DFLayoutDoubleField)
  205. {
  206. var tuple = LoadEditor(element);
  207. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  208. }
  209. else if (element is DFLayoutDateField)
  210. {
  211. var tuple = LoadDatePicker(element);
  212. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  213. }
  214. else if (element is DFLayoutTimeField)
  215. {
  216. var tuple = LoadTimePicker(element);
  217. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  218. }
  219. else if (element is DFLayoutOptionField)
  220. {
  221. var tuple = LoadOptionPicker(element);
  222. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  223. }
  224. else if (element is DFLayoutImage)
  225. {
  226. var tuple = LoadImage(element);
  227. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  228. }
  229. else if (element is DFLayoutLookupField)
  230. {
  231. var tuple = LoadLookupPicker(element);
  232. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  233. }
  234. else if (element is DFLayoutSignaturePad)
  235. {
  236. var tuple = LoadSignaturePad(element);
  237. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  238. }
  239. else if (element is DFLayoutEmbeddedImage)
  240. {
  241. var tuple = LoadEmbeddedImage(element);
  242. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  243. }
  244. else if (element is DFLayoutMultiImage)
  245. {
  246. var tuple = LoadMultiImage(element);
  247. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  248. }
  249. else if (element is DFLayoutMultiSignaturePad)
  250. {
  251. var tuple = LoadMultiSignaturePad(element);
  252. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  253. }
  254. else if (element is DFLayoutAddTaskField)
  255. {
  256. var tuple = LoadAddTaskField(element);
  257. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  258. }
  259. else if (element is DFLayoutHeader)
  260. {
  261. FormatAndAddView(LoadHeader(element), element, false);
  262. }
  263. }
  264. private View LoadHeader(DFLayoutControl element)
  265. {
  266. DFLayoutHeader dFLayoutHeader = (DFLayoutHeader)element;
  267. DigitalFormsHeader header = new DigitalFormsHeader(dFLayoutHeader.Collapsed);
  268. header.SetHeaderStyle(dFLayoutHeader);
  269. if (dFLayoutHeader.Collapsed)
  270. header = AddNumberToHeader(header);
  271. header.SetHeaderValue(dFLayoutHeader.Header);
  272. header.OnTapped += (bCollapsed) =>
  273. {
  274. AdjustHeaderSection(header, bCollapsed);
  275. };
  276. return header;
  277. }
  278. private DigitalFormsHeader AddNumberToHeader(DigitalFormsHeader header)
  279. {
  280. header.Number = collapsedHeaderCount;
  281. collapsedHeaderCount++;
  282. return header;
  283. }
  284. private void AdjustHeaderSection(DigitalFormsHeader header, bool collapsed)
  285. {
  286. try
  287. {
  288. var thisHeaderRow = GetRow(header);
  289. var headerRows = GetOtherHeaders(thisHeaderRow);
  290. if (headerRows.Any())
  291. AdjustHeightsToNextHeader(headerRows, thisHeaderRow, collapsed);
  292. else
  293. AdjustHeightsBelowHeader(headerRows, thisHeaderRow, collapsed);
  294. }
  295. catch
  296. {
  297. }
  298. }
  299. private List<int> GetOtherHeaders(int thisHeaderRow)
  300. {
  301. List<int> headerRows = new List<int>();
  302. foreach (var child in Children)
  303. {
  304. if (child is DigitalFormsHeader)
  305. {
  306. var dfheader = (DigitalFormsHeader)child;
  307. if (GetRow(dfheader) > thisHeaderRow)
  308. {
  309. headerRows.Add(GetRow(dfheader));
  310. }
  311. }
  312. }
  313. return headerRows;
  314. }
  315. private void AdjustHeightsToNextHeader(List<int> headerRows, int thisHeaderRow, bool collapsed)
  316. {
  317. headerRows.Sort();
  318. int nextHeaderRow = headerRows[0];
  319. for (int i = thisHeaderRow + 1; i < nextHeaderRow; i++)
  320. {
  321. AdjustHeight(i, collapsed);
  322. }
  323. }
  324. private void AdjustHeightsBelowHeader(List<int> headerRows, int thisHeaderRow, bool collapsed)
  325. {
  326. for (int i = thisHeaderRow + 1; i < RowDefinitions.Count; i++)
  327. {
  328. AdjustHeight(i, collapsed);
  329. }
  330. }
  331. private void AdjustHeight(int i, bool collapsed)
  332. {
  333. var rowdef = RowDefinitions[i];
  334. if (collapsed)
  335. {
  336. rowdef.Height = 60;
  337. AnimateChildren(i, 0, 250);
  338. }
  339. else
  340. {
  341. AnimateChildren(i, -60, 500);
  342. rowdef.Height = 0;
  343. }
  344. }
  345. private async void AnimateChildren(int i, int movement, int length)
  346. {
  347. foreach (var child in Children)
  348. {
  349. if (GetRow(child) == i)
  350. {
  351. await child.TranslateTo(0, movement, 250);
  352. }
  353. }
  354. }
  355. private Tuple<View, Boolean> LoadCustomBoolean(DFLayoutControl element)
  356. {
  357. string value = "";
  358. rbGroup++;
  359. CustomBoolean item = new CustomBoolean(rbGroup);
  360. DFLayoutBooleanField dfLayoutBooleanField = element as DFLayoutBooleanField;
  361. if (!string.IsNullOrWhiteSpace(dfLayoutBooleanField.Properties.TrueValue))
  362. item.trueBtn.Content = dfLayoutBooleanField.Properties.TrueValue;
  363. if (!string.IsNullOrWhiteSpace(dfLayoutBooleanField.Properties.FalseValue))
  364. item.falseBtn.Content = dfLayoutBooleanField.Properties.FalseValue;
  365. if (loadData.TryGetValue(dfLayoutBooleanField.Name, out value))
  366. {
  367. item.Value = bool.Parse(value);
  368. if (bool.Parse(value) == false)
  369. item.SetFalseValue();
  370. }
  371. if (loadRetainedForm)
  372. {
  373. if (RetainedResults.Results.TryGetValue(dfLayoutBooleanField.Name, out value))
  374. {
  375. item.Value = bool.Parse(value);
  376. }
  377. }
  378. if (dfLayoutBooleanField.Properties.Required)
  379. {
  380. item.trueBtn.BackgroundColor = isRequiredColor;
  381. item.falseBtn.BackgroundColor = isRequiredColor;
  382. }
  383. item.OnCustomBooleanValueChanged += (boolvalue) =>
  384. {
  385. dfLayout.ChangeField(dfLayoutBooleanField.Name);
  386. };
  387. return new Tuple<View, Boolean>(item, dfLayoutBooleanField.Properties.Required);
  388. }
  389. private Tuple<View, Boolean> LoadLabel(DFLayoutControl element)
  390. {
  391. DFLayoutLabel label = element as DFLayoutLabel;
  392. Label item = new Label();
  393. item.Text = label.Caption;
  394. item.TextColor = Color.Black;
  395. item.LineBreakMode = label.Style.TextWrapping == true ? LineBreakMode.WordWrap : LineBreakMode.NoWrap;
  396. item.VerticalOptions = LayoutOptions.FillAndExpand;
  397. item.MinimumHeightRequest = 60;
  398. item.BackgroundColor = label.Style.BackgroundColour;
  399. item.FontAttributes = label.Style.IsBold ? FontAttributes.Bold
  400. : label.Style.IsItalic ? FontAttributes.Italic
  401. : FontAttributes.None;
  402. item.TextDecorations = label.Style.Underline == UnderlineType.Single || label.Style.Underline == UnderlineType.Double ?
  403. TextDecorations.Underline : TextDecorations.None;
  404. item.FontSize = label.Style.FontSize > 5 && label.Style.FontSize < 37 ? label.Style.FontSize
  405. : Device.GetNamedSize(NamedSize.Medium, item);
  406. item.TextColor = label.Style.ForegroundColour;
  407. if (ColumnDefinitions.Count == 1)
  408. {
  409. item.HorizontalOptions = LayoutOptions.CenterAndExpand;
  410. item.HorizontalTextAlignment = TextAlignment.Center;
  411. }
  412. item.HorizontalTextAlignment = label.Style.HorizontalTextAlignment == DFLayoutAlignment.Start ? TextAlignment.Start
  413. : label.Style.HorizontalTextAlignment == DFLayoutAlignment.Middle ? TextAlignment.Center
  414. : label.Style.HorizontalTextAlignment == DFLayoutAlignment.End ? TextAlignment.End
  415. : item.HorizontalTextAlignment;
  416. item.VerticalTextAlignment = label.Style.VerticalTextAlignment == DFLayoutAlignment.Start ? TextAlignment.Start
  417. : label.Style.HorizontalTextAlignment == DFLayoutAlignment.Middle ? TextAlignment.Center
  418. : label.Style.HorizontalTextAlignment == DFLayoutAlignment.End ? TextAlignment.End
  419. : TextAlignment.Center;
  420. return new Tuple<View, Boolean>(item, false);
  421. }
  422. private Tuple<View, Boolean> LoadEditor(DFLayoutControl element)
  423. {
  424. string value = "";
  425. View view = null;
  426. Editor item = new Editor();
  427. item.AutoSize = EditorAutoSizeOption.TextChanges;
  428. var isrequired = false;
  429. var issecure = false;
  430. if (element is DFLayoutStringField)
  431. {
  432. DFLayoutStringField dfLayoutStringField = element as DFLayoutStringField;
  433. item.TextColor = Color.Black;
  434. item.Placeholder = "Enter answer";
  435. isrequired = dfLayoutStringField.Properties.Required;
  436. issecure = dfLayoutStringField.Properties.Secure;
  437. DataButtonControl button = new DataButtonControl();
  438. button.Clicked += (s, e) =>
  439. {
  440. PopupEditor edt = new PopupEditor(button.Data);
  441. edt.OnPopupEdtSaved += (text) =>
  442. {
  443. button.Data = text;
  444. button.Text = text.Length > 25 ? text.Substring(0, 25) + "..." : text;
  445. dfLayout.ChangeField(dfLayoutStringField.Name);
  446. };
  447. Navigation.PushAsync(edt);
  448. };
  449. button.Text = "Edit";
  450. if (loadData.TryGetValue(dfLayoutStringField.Name, out value))
  451. {
  452. item.Text = value;
  453. button.Text = value.Length > 25 ? value.Substring(0, 25) + "..." : value;
  454. }
  455. if (loadRetainedForm)
  456. {
  457. if (RetainedResults.Results.TryGetValue(dfLayoutStringField.Name, out value))
  458. {
  459. item.Text = value;
  460. button.Text = value.Length > 25 ? value.Substring(0, 25) + "..." : value;
  461. }
  462. }
  463. item.TextChanged += (object sender, TextChangedEventArgs e) =>
  464. {
  465. dfLayout.ChangeField(dfLayoutStringField.Name);
  466. };
  467. if (dfLayoutStringField.Properties.PopupEditor)
  468. view = button;
  469. else
  470. view = item;
  471. }
  472. else if (element is DFLayoutIntegerField)
  473. {
  474. DFLayoutIntegerField dfLayoutIntegerField = element as DFLayoutIntegerField;
  475. item.TextColor = Color.Black;
  476. item.Placeholder = "Enter number";
  477. item.Keyboard = Keyboard.Numeric;
  478. isrequired = dfLayoutIntegerField.Properties.Required;
  479. issecure = dfLayoutIntegerField.Properties.Secure;
  480. if (loadData.TryGetValue(dfLayoutIntegerField.Name, out value))
  481. {
  482. item.Text = value;
  483. }
  484. if (loadRetainedForm)
  485. {
  486. if (RetainedResults.Results.TryGetValue(dfLayoutIntegerField.Name, out value))
  487. {
  488. item.Text = value;
  489. }
  490. }
  491. item.TextChanged += (object sender, TextChangedEventArgs e) =>
  492. {
  493. dfLayout.ChangeField(dfLayoutIntegerField.Name);
  494. };
  495. view = item;
  496. }
  497. else if (element is DFLayoutDoubleField)
  498. {
  499. DFLayoutDoubleField dfLayoutDoubleField = element as DFLayoutDoubleField;
  500. item.TextColor = Color.Black;
  501. item.Placeholder = "Enter number";
  502. item.Keyboard = Keyboard.Numeric;
  503. isrequired = dfLayoutDoubleField.Properties.Required;
  504. issecure = dfLayoutDoubleField.Properties.Secure;
  505. if (loadData.TryGetValue(dfLayoutDoubleField.Name, out value))
  506. {
  507. item.Text = value;
  508. }
  509. if (loadRetainedForm)
  510. {
  511. if (RetainedResults.Results.TryGetValue(dfLayoutDoubleField.Name, out value))
  512. {
  513. item.Text = value;
  514. }
  515. }
  516. item.TextChanged += (object sender, TextChangedEventArgs e) =>
  517. {
  518. dfLayout.ChangeField(dfLayoutDoubleField.Name);
  519. };
  520. view = item;
  521. }
  522. if (isrequired) view.BackgroundColor = isRequiredColor;
  523. if (readOnly || issecure)
  524. {
  525. Label label = new Label();
  526. label.Text = item.Text;
  527. label.FontSize = Device.GetNamedSize(NamedSize.Medium, item);
  528. label.TextColor = Color.DarkGray;
  529. label.LineBreakMode = LineBreakMode.WordWrap;
  530. label.MaxLines = 5;
  531. label.VerticalTextAlignment = TextAlignment.Center;
  532. label.HorizontalTextAlignment = TextAlignment.Center;
  533. label.MinimumHeightRequest = 60;
  534. label.VerticalOptions = LayoutOptions.FillAndExpand;
  535. label.Margin = 9;
  536. view = label;
  537. }
  538. return new Tuple<View, Boolean>(view, isrequired);
  539. }
  540. private Tuple<View, Boolean> LoadDatePicker(DFLayoutControl element)
  541. {
  542. string value = "";
  543. DFLayoutDateField dfLayoutDateField = element as DFLayoutDateField;
  544. DatePicker item = new DatePicker();
  545. item.Format = "dd MMM yyyy";
  546. if (dfLayoutDateField.Properties.Required)
  547. item.BackgroundColor = isRequiredColor;
  548. item.HorizontalOptions = LayoutOptions.CenterAndExpand;
  549. if (loadData.TryGetValue(dfLayoutDateField.Name, out value))
  550. {
  551. item.Date = DateTime.Parse(value);
  552. }
  553. if (loadRetainedForm)
  554. {
  555. if (RetainedResults.Results.TryGetValue(dfLayoutDateField.Name, out value))
  556. {
  557. item.Date = DateTime.Parse(value);
  558. }
  559. }
  560. item.DateSelected += (object sender, DateChangedEventArgs e) =>
  561. {
  562. dfLayout.ChangeField(dfLayoutDateField.Name);
  563. };
  564. return new Tuple<View, Boolean>(item, dfLayoutDateField.Properties.Required);
  565. }
  566. private Tuple<View, Boolean> LoadTimePicker(DFLayoutControl element)
  567. {
  568. string value = "";
  569. DFLayoutTimeField dfLayoutTimeField = element as DFLayoutTimeField;
  570. TimePicker item = new TimePicker();
  571. if (dfLayoutTimeField.Properties.Required)
  572. item.BackgroundColor = isRequiredColor;
  573. item.HorizontalOptions = LayoutOptions.Center;
  574. if (loadData.TryGetValue(dfLayoutTimeField.Name, out value))
  575. {
  576. item.Time = DateTime.Parse(value).TimeOfDay;
  577. }
  578. if (loadRetainedForm)
  579. {
  580. if (RetainedResults.Results.TryGetValue(dfLayoutTimeField.Name, out value))
  581. {
  582. item.Time = DateTime.Parse(value).TimeOfDay;
  583. }
  584. }
  585. item.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) =>
  586. {
  587. if (e.PropertyName == "Time")
  588. dfLayout.ChangeField(dfLayoutTimeField.Name);
  589. };
  590. return new Tuple<View, Boolean>(item, dfLayoutTimeField.Properties.Required);
  591. }
  592. private Tuple<View, Boolean> LoadOptionPicker(DFLayoutControl element)
  593. {
  594. View view = null;
  595. try
  596. {
  597. string value = "";
  598. var isrequired = false;
  599. DFLayoutOptionField dfLayoutOptionField = element as DFLayoutOptionField;
  600. isrequired = dfLayoutOptionField.Properties.Required;
  601. if (GlobalVariables.DeviceString == "i" || GlobalVariables.DeviceString == "I")
  602. {
  603. CustomPickeriOS item = new CustomPickeriOS();
  604. string s = dfLayoutOptionField.Properties.Options;
  605. string[] substrings = s.Split(',');
  606. var optionList = substrings.ToList();
  607. item.AddItems(optionList);
  608. if (!string.IsNullOrEmpty(dfLayoutOptionField.Properties.Default))
  609. {
  610. int index = optionList.IndexOf(dfLayoutOptionField.Properties.Default);
  611. item.SelectedIndex = index;
  612. item.SelectedItem = optionList[index];
  613. item.SetDefault(optionList[index]);
  614. }
  615. if (loadData.TryGetValue(dfLayoutOptionField.Name, out value))
  616. {
  617. int index = optionList.IndexOf(value);
  618. item.SelectedIndex = index;
  619. item.SelectedItem = optionList[index];
  620. item.SetDefault(optionList[index]);
  621. }
  622. if (loadRetainedForm)
  623. {
  624. if (RetainedResults.Results.TryGetValue(dfLayoutOptionField.Name, out value))
  625. {
  626. int index = optionList.IndexOf(value);
  627. item.SelectedIndex = index;
  628. item.SelectedItem = optionList[index];
  629. item.SetDefault(optionList[index]);
  630. }
  631. }
  632. if (isrequired)
  633. {
  634. item.BackgroundColor = isRequiredColor;
  635. item.SetBackGroundColor(isRequiredColor);
  636. }
  637. item.CustomPickeriOSValueChanged += () =>
  638. {
  639. dfLayout.ChangeField(dfLayoutOptionField.Name);
  640. };
  641. view = item;
  642. }
  643. else
  644. {
  645. Picker picker = new Picker();
  646. picker.Title = "Select an option";
  647. picker.VerticalTextAlignment = TextAlignment.Center;
  648. picker.HorizontalTextAlignment = TextAlignment.Center;
  649. string s = dfLayoutOptionField.Properties.Options;
  650. string[] substrings = s.Split(',');
  651. var optionList = substrings.ToList();
  652. picker.ItemsSource = optionList;
  653. if (!string.IsNullOrEmpty(dfLayoutOptionField.Properties.Default))
  654. {
  655. int index = optionList.IndexOf(dfLayoutOptionField.Properties.Default);
  656. picker.SelectedIndex = index;
  657. picker.SelectedItem = optionList[index];
  658. }
  659. if (loadData.TryGetValue(dfLayoutOptionField.Name, out value))
  660. {
  661. int index = optionList.IndexOf(value);
  662. picker.SelectedIndex = index;
  663. picker.SelectedItem = optionList[index];
  664. }
  665. if (loadRetainedForm)
  666. {
  667. if (RetainedResults.Results.TryGetValue(dfLayoutOptionField.Name, out value))
  668. {
  669. int index = optionList.IndexOf(value);
  670. picker.SelectedIndex = index;
  671. picker.SelectedItem = optionList[index];
  672. }
  673. }
  674. if (isrequired)
  675. {
  676. picker.BackgroundColor = isRequiredColor;
  677. }
  678. picker.SelectedIndexChanged += (object sender, EventArgs e) =>
  679. {
  680. dfLayout.ChangeField(dfLayoutOptionField.Name);
  681. };
  682. view = picker;
  683. }
  684. return new Tuple<View, Boolean>(view, isrequired);
  685. }
  686. catch
  687. {
  688. return new Tuple<View, Boolean>(view, false);
  689. }
  690. }
  691. private Tuple<View, Boolean> LoadImage(DFLayoutControl element)
  692. {
  693. View view = null;
  694. DFLayoutImage dfLayoutImage = element as DFLayoutImage;
  695. Image img = new Image();
  696. CoreTable table = new Client<Document>().Query(
  697. new Filter<Document>(x => x.ID).IsEqualTo(dfLayoutImage.Image.ID),
  698. null,
  699. null);
  700. if (table.Rows.Any())
  701. {
  702. CoreRow row = table.Rows.FirstOrDefault();
  703. byte[] data = row.Get<Document, byte[]>(x => x.Data);
  704. ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  705. img.MinimumHeightRequest = 150;
  706. img.MinimumWidthRequest = 150;
  707. img.Aspect = Aspect.AspectFit;
  708. img.Source = src;
  709. img.HorizontalOptions = LayoutOptions.FillAndExpand;
  710. img.VerticalOptions = LayoutOptions.FillAndExpand;
  711. img.GestureRecognizers.Add(new TapGestureRecognizer
  712. {
  713. Command = new Command(OnTap),
  714. CommandParameter = src,
  715. NumberOfTapsRequired = 1
  716. });
  717. if (img != null)
  718. {
  719. view = img;
  720. }
  721. }
  722. return new Tuple<View, Boolean>(view, false);
  723. }
  724. private void OnTap(object obj)
  725. {
  726. ImageViewer viewer = new ImageViewer(obj as ImageSource);
  727. Navigation.PushAsync(viewer);
  728. }
  729. private Tuple<View, Boolean> LoadLookupPicker(DFLayoutControl element)
  730. {
  731. View view = null;
  732. string value = "";
  733. DFLayoutLookupField dfLayoutLookupField = element as DFLayoutLookupField;
  734. var isrequired = dfLayoutLookupField.Properties.Required;
  735. Dictionary<Guid, string> lookupFieldOptions = new Dictionary<Guid, string>();
  736. string type = dfLayoutLookupField.Properties.LookupType;
  737. Type lookuptype = CoreUtils.GetEntityOrNull(type);
  738. if (lookuptype == typeof(DrawingTemplate))
  739. view = LoadDrawingTemplateLookupButton(lookuptype, dfLayoutLookupField, lookupFieldOptions, element);
  740. else if (!string.IsNullOrWhiteSpace(dfLayoutLookupField.Properties.Filter))
  741. view = LoadGenericLookupButton(lookuptype, dfLayoutLookupField, lookupFieldOptions, element);
  742. else if (lookuptype == typeof(Product))
  743. view = LoadProductLookupPicker(view, dfLayoutLookupField, value);
  744. else if (lookuptype != null)
  745. view = LoadGenericLookupButton(lookuptype, dfLayoutLookupField, lookupFieldOptions, element);
  746. else if (lookuptype == null)
  747. view = new Label { Text = "Null lookup selected", HorizontalOptions = LayoutOptions.Center, HorizontalTextAlignment = TextAlignment.Center };
  748. return new Tuple<View, Boolean>(view, isrequired);
  749. }
  750. private View LoadGenericLookupButton(Type lookuptype, DFLayoutLookupField dfLayoutLookupField, Dictionary<Guid, string> lookupFieldOptions, DFLayoutControl element)
  751. {
  752. string value = "";
  753. CoreTable table = new CoreTable();
  754. var client = ClientFactory.CreateClient(lookuptype);
  755. var columns = LookupFactory.DefineColumns(lookuptype);
  756. var sort = LookupFactory.DefineSort(lookuptype);
  757. var filter = LookupFactory.DefineFilter(lookuptype);
  758. foreach (var property in dfLayoutLookupField.Properties.AdditionalPropertiesList)
  759. {
  760. columns.Add(property);
  761. }
  762. if (!string.IsNullOrWhiteSpace(dfLayoutLookupField.Properties.Filter))
  763. filter = ReturnFilter(dfLayoutLookupField, lookuptype);
  764. if (lookuptype == typeof(ProductStyle) && JobID != Guid.Empty)
  765. table = ReturnJobStyleProducts(table, client, columns, sort);
  766. if (table.Rows.Count == 0)
  767. table = client.Query(filter, columns, sort); // do generic query if a specific one hasn't already been done
  768. Dictionary<Guid, Dictionary<string, object>> additionalPropertyValues = new Dictionary<Guid, Dictionary<string, object>>();
  769. foreach (var row in table.Rows)
  770. {
  771. Guid id = row.Get<Guid>("ID");
  772. Dictionary<string, object> values = row.ToDictionary(new string[] { "ID" });
  773. additionalPropertyValues.Add(id, values);
  774. string display = LookupFactory.FormatLookup(lookuptype, values, new string[] { });
  775. lookupFieldOptions[id] = display;
  776. }
  777. dfLayoutLookupFieldLookupOptions[element as DFLayoutLookupField] = lookupFieldOptions;
  778. List<string> itemList = lookupFieldOptions.Values.ToList();
  779. DataButtonControl button = new DataButtonControl()
  780. {
  781. Text = "Choose Option",
  782. Margin = 0,
  783. ExtraData = additionalPropertyValues,
  784. LookupFieldOptions = lookupFieldOptions
  785. };
  786. button.Clicked += (object sender, EventArgs eventArgs) =>
  787. {
  788. ListSelectionPage selectionPage = new ListSelectionPage(lookupFieldOptions);
  789. selectionPage.OnSimpleListTapped += (s) =>
  790. {
  791. button.Data = s;
  792. button.Text = s;
  793. dfLayout.ChangeField(dfLayoutLookupField.Name);
  794. };
  795. selectionPage.OnDictionaryItemTapped += (id, s) =>
  796. {
  797. button.Data = s;
  798. button.Text = s;
  799. button.ChosenID = id;
  800. dfLayout.ChangeField(dfLayoutLookupField.Name);
  801. };
  802. Navigation.PushAsync(selectionPage);
  803. };
  804. if (loadData.TryGetValue(dfLayoutLookupField.Name, out value))
  805. {
  806. button.Data = value;
  807. button.Text = value;
  808. }
  809. if (loadRetainedForm)
  810. {
  811. if (RetainedResults.Results.TryGetValue(dfLayoutLookupField.Name, out value))
  812. {
  813. button.Data = value;
  814. button.Text = value;
  815. }
  816. }
  817. if (isRequired)
  818. {
  819. button.BackgroundColor = isRequiredColor;
  820. }
  821. return button;
  822. }
  823. private View LoadDrawingTemplateLookupButton(Type lookuptype, DFLayoutLookupField dfLayoutLookupField, Dictionary<Guid, string> lookupFieldOptions, DFLayoutControl element)
  824. {
  825. string value = "";
  826. var columns = new Columns<DrawingTemplate>(x => x.Code, x => x.Document.ID);
  827. CoreTable table = new Client<DrawingTemplate>().Query(null, columns);
  828. Dictionary<string, Guid> dictionary = new Dictionary<string, Guid>();
  829. foreach (var row in table.Rows)
  830. {
  831. List<object> list = row.Values;
  832. if (list[0] != null && list[1] != null)
  833. dictionary.Add(list[0].ToString(), Guid.Parse(list[1].ToString()));
  834. }
  835. DataButtonControl button = new DataButtonControl()
  836. {
  837. Text = "Choose Option",
  838. };
  839. button.Clicked += (object sender, EventArgs eventArgs) =>
  840. {
  841. ListSelectionPage selectionPage = new ListSelectionPage(dictionary);
  842. selectionPage.OnSimpleListTapped += (s) =>
  843. {
  844. button.Data = s;
  845. button.Text = s;
  846. dfLayout.ChangeField(dfLayoutLookupField.Name);
  847. };
  848. Navigation.PushAsync(selectionPage);
  849. };
  850. if (loadData.TryGetValue(dfLayoutLookupField.Name, out value))
  851. {
  852. button.Data = value;
  853. button.Text = value;
  854. }
  855. if (loadRetainedForm)
  856. {
  857. if (RetainedResults.Results.TryGetValue(dfLayoutLookupField.Name, out value))
  858. {
  859. button.Data = value;
  860. button.Text = value;
  861. }
  862. }
  863. if (isRequired)
  864. {
  865. button.BackgroundColor = isRequiredColor;
  866. }
  867. return button;
  868. }
  869. private IFilter ReturnFilter(DFLayoutLookupField dfLayoutLookupField, Type lookuptype)
  870. {
  871. var propertyFilter = dfLayoutLookupField.Properties.Filter;
  872. var filtertype = typeof(Filter<>).MakeGenericType(lookuptype);
  873. var deserialised = Serialization.Deserialize(filtertype, propertyFilter);
  874. IFilter filter = deserialised as IFilter;
  875. return filter;
  876. }
  877. private CoreTable ReturnJobStyleProducts(CoreTable table, IClient client, IColumns columns, ISortOrder sort)
  878. {
  879. CoreTable jobStyleTable = new Client<JobStyle>().Query(new Filter<JobStyle>(x => x.Job.ID).IsEqualTo(JobID),
  880. new Columns<JobStyle>(x => x.Style.ID));
  881. if (jobStyleTable.Rows.Any())
  882. {
  883. Guid firstID = Guid.Parse(jobStyleTable.Rows.FirstOrDefault().Values[0].ToString());
  884. var stylefilter = new Filter<ProductStyle>(x => x.ID).IsEqualTo(firstID);
  885. foreach (CoreRow jobStyleRow in jobStyleTable.Rows)
  886. {
  887. if (jobStyleRow != jobStyleTable.Rows.FirstOrDefault())
  888. {
  889. stylefilter = stylefilter.Or(x => x.ID).IsEqualTo(Guid.Parse(jobStyleRow.Values[0].ToString()));
  890. }
  891. }
  892. table = client.Query(stylefilter, columns, sort);
  893. }
  894. return table;
  895. }
  896. private View LoadProductLookupPicker(View view, DFLayoutLookupField dfLayoutLookupField, string value)
  897. {
  898. FrameButton framebutton = new FrameButton();
  899. if (loadData.TryGetValue(dfLayoutLookupField.Name, out value))
  900. {
  901. framebutton.SetButtonText(value);
  902. framebutton.Data = value + "," + (GlobalVariables.ProductShells.FirstOrDefault(x => x.Code == value)).ID.ToString();
  903. //CoreTable productTable = new Client<Product>().Query(new Filter<Product>(x => x.Code).IsEqualTo(value),
  904. // new Columns<Product>(x => x.Image.ID));
  905. //if (productTable.Rows.Any())
  906. //{
  907. // CoreTable imageTable1 = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(Guid.Parse(productTable.Rows.First().Values[0].ToString())),
  908. // new Columns<Document>(x => x.Data));
  909. // CoreRow docrow = imageTable1.Rows.FirstOrDefault();
  910. // if (docrow != null)
  911. // {
  912. // byte[] data = docrow.Get<Document, byte[]>(x => x.Data);
  913. // ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  914. // if (src != null)
  915. // {
  916. // framebutton.SetImage(src);
  917. // }
  918. // }
  919. //}
  920. }
  921. framebutton.OnFrameButtonClicked += (() =>
  922. {
  923. ProductList productList = new ProductList(GlobalVariables.ProductShells, true);
  924. productList.OnProductSelected += () =>
  925. {
  926. framebutton.SetButtonText(productList.SelectedProduct.Code);
  927. framebutton.Data = productList.SelectedProduct.Code + "," + productList.SelectedProduct.ID.ToString();
  928. //CoreTable imageTable = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(productList.SelectedProduct.ImageID),
  929. // new Columns<Document>(x => x.Data));
  930. //CoreRow docrow = imageTable.Rows.FirstOrDefault();
  931. //if (docrow != null)
  932. //{
  933. // byte[] data = docrow.Get<Document, byte[]>(x => x.Data);
  934. // ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  935. // if (src != null)
  936. // {
  937. // framebutton.SetImage(src);
  938. // }
  939. //}
  940. dfLayout.ChangeField(dfLayoutLookupField.Name);
  941. };
  942. Navigation.PushAsync(productList);
  943. });
  944. view = framebutton;
  945. return view;
  946. }
  947. private Tuple<View, Boolean> LoadSignaturePad(DFLayoutControl element)
  948. {
  949. string value = "";
  950. View view = null;
  951. DFLayoutSignaturePad dFLayoutSignaturePad = element as DFLayoutSignaturePad;
  952. var isrequired = dFLayoutSignaturePad.Properties.Required;
  953. if (loadData.TryGetValue(dFLayoutSignaturePad.Name, out value))
  954. {
  955. EmbeddedImageCapture embeddedImageCapture = new EmbeddedImageCapture();
  956. byte[] data = Convert.FromBase64String(value);
  957. embeddedImageCapture.DataToImage(data);
  958. view = embeddedImageCapture;
  959. view.IsEnabled = false;
  960. }
  961. else
  962. {
  963. SfSignaturePad signaturePad = new SfSignaturePad();
  964. EmbeddedImageCapture hiddenEmbeddedImageCapture = new EmbeddedImageCapture() { HeightRequest = 200, IsVisible = false, IsEnabled = false };
  965. if (isrequired) signaturePad.BackgroundColor = isRequiredColor;
  966. signaturePad.MinimumHeightRequest = 200;
  967. signaturePad.MinimumStrokeWidth = 0.2;
  968. signaturePad.MaximumStrokeWidth = 17;
  969. Button clearButton = new Button()
  970. {
  971. Text = "Clear",
  972. HorizontalOptions = LayoutOptions.FillAndExpand,
  973. VerticalOptions = LayoutOptions.End,
  974. Margin = 0,
  975. BackgroundColor = Color.FromHex("#15C7C1"),
  976. FontAttributes = FontAttributes.Bold,
  977. TextColor = Color.White,
  978. CornerRadius = 5,
  979. Padding = 1
  980. };
  981. clearButton.Clicked += (object sender, EventArgs e) =>
  982. {
  983. signaturePad.IsVisible = true;
  984. hiddenEmbeddedImageCapture.IsVisible = false;
  985. useSavedSignatures.Remove(dFLayoutSignaturePad.Name);
  986. signaturePad.Clear();
  987. };
  988. Grid.SetColumn(clearButton, 2);
  989. Button signNowButton = new Button()
  990. {
  991. Text = "Apply Saved",
  992. HorizontalOptions = LayoutOptions.FillAndExpand,
  993. VerticalOptions = LayoutOptions.End,
  994. Margin = 0,
  995. BackgroundColor = Color.FromHex("#15C7C1"),
  996. FontAttributes = FontAttributes.Bold,
  997. TextColor = Color.White,
  998. CornerRadius = 5,
  999. Padding = 1
  1000. };
  1001. signNowButton.Clicked += (object sender, EventArgs e) =>
  1002. {
  1003. if (Application.Current.Properties.ContainsKey("SavedSignature"))
  1004. {
  1005. Task.Run(() =>
  1006. {
  1007. hiddenEmbeddedImageCapture.DataToImage((Application.Current.Properties["SavedSignature"]) as byte[]);
  1008. });
  1009. Thread.Sleep(1000);
  1010. signaturePad.IsVisible = false;
  1011. hiddenEmbeddedImageCapture.IsVisible = true;
  1012. if (!useSavedSignatures.Contains(dFLayoutSignaturePad.Name))
  1013. useSavedSignatures.Add(dFLayoutSignaturePad.Name);
  1014. }
  1015. };
  1016. Grid.SetColumn(signNowButton, 1);
  1017. Button createSignatureButton = new Button()
  1018. {
  1019. Text = "Save New",
  1020. HorizontalOptions = LayoutOptions.FillAndExpand,
  1021. VerticalOptions = LayoutOptions.End,
  1022. Margin = 0,
  1023. BackgroundColor = Color.FromHex("#15C7C1"),
  1024. FontAttributes = FontAttributes.Bold,
  1025. TextColor = Color.White,
  1026. CornerRadius = 5,
  1027. Padding = 1
  1028. };
  1029. createSignatureButton.Clicked += (object sender, EventArgs e) =>
  1030. {
  1031. SignatureSaver saver = new SignatureSaver();
  1032. saver.OnSignatureSaved += () =>
  1033. {
  1034. Task.Run(() =>
  1035. {
  1036. hiddenEmbeddedImageCapture.DataToImage((Application.Current.Properties["SavedSignature"]) as byte[]);
  1037. });
  1038. Thread.Sleep(1000);
  1039. signaturePad.IsVisible = false;
  1040. hiddenEmbeddedImageCapture.IsVisible = true;
  1041. if (!useSavedSignatures.Contains(dFLayoutSignaturePad.Name))
  1042. useSavedSignatures.Add(dFLayoutSignaturePad.Name);
  1043. };
  1044. Navigation.PushAsync(saver);
  1045. };
  1046. Grid.SetColumn(createSignatureButton, 0);
  1047. Grid buttonsGrid = new Grid { Margin = 0, Padding = 0, VerticalOptions = LayoutOptions.End };
  1048. buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  1049. buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  1050. buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  1051. buttonsGrid.Children.Add(createSignatureButton);
  1052. buttonsGrid.Children.Add(signNowButton);
  1053. buttonsGrid.Children.Add(clearButton);
  1054. Grid grid = new Grid() { Margin = 0, Padding = 0 };
  1055. grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(200, GridUnitType.Absolute) });
  1056. Grid.SetRow(signaturePad, 0);
  1057. Grid.SetRow(hiddenEmbeddedImageCapture, 0);
  1058. grid.Children.Add(hiddenEmbeddedImageCapture);
  1059. grid.Children.Add(signaturePad);
  1060. grid.Children.Add(buttonsGrid);
  1061. view = grid;
  1062. }
  1063. return new Tuple<View, Boolean>(view, isrequired);
  1064. }
  1065. private Tuple<View, Boolean> LoadEmbeddedImage(DFLayoutControl element)
  1066. {
  1067. string value = "";
  1068. bool disableLibrary = false;
  1069. DFLayoutEmbeddedImage dfLayoutEmbeddedImage = element as DFLayoutEmbeddedImage;
  1070. try
  1071. {
  1072. disableLibrary = dfLayoutEmbeddedImage.Properties.DisableLibrary;
  1073. }
  1074. catch { }
  1075. EmbeddedImageCapture embeddedImageCapture = new EmbeddedImageCapture(disableLibrary);
  1076. if (disableLibrary)
  1077. embeddedImageCapture.LibraryButton.BackgroundColor = Color.LightGray;
  1078. if (loadData.TryGetValue(dfLayoutEmbeddedImage.Name, out value))
  1079. {
  1080. byte[] data = Convert.FromBase64String(value);
  1081. embeddedImageCapture.DataToImage(data);
  1082. }
  1083. else
  1084. {
  1085. if (dfLayoutEmbeddedImage.Properties.Required)
  1086. {
  1087. embeddedImageCapture.CameraButton.BackgroundColor = isRequiredColor;
  1088. embeddedImageCapture.CameraButton.BorderWidth = 1;
  1089. embeddedImageCapture.CameraButton.BorderColor = Color.Black;
  1090. if (!disableLibrary)
  1091. {
  1092. embeddedImageCapture.LibraryButton.BackgroundColor = isRequiredColor;
  1093. embeddedImageCapture.LibraryButton.BorderWidth = 1;
  1094. embeddedImageCapture.LibraryButton.BorderColor = Color.Black;
  1095. }
  1096. }
  1097. }
  1098. return new Tuple<View, Boolean>(embeddedImageCapture, dfLayoutEmbeddedImage.Properties.Required);
  1099. }
  1100. private Tuple<View, Boolean> LoadMultiImage(DFLayoutControl element)
  1101. {
  1102. string value = "";
  1103. bool disableLibrary = false;
  1104. DFLayoutMultiImage dfLayoutMultiEmbeddedImage = element as DFLayoutMultiImage;
  1105. try
  1106. {
  1107. disableLibrary = dfLayoutMultiEmbeddedImage.Properties.DisableLibrary;
  1108. }
  1109. catch { }
  1110. MultiImageCapture multiImageCapture = new MultiImageCapture(disableLibrary);
  1111. if (loadData.TryGetValue(dfLayoutMultiEmbeddedImage.Name, out value))
  1112. {
  1113. List<string> values = Serialization.Deserialize<List<string>>(value);
  1114. foreach (string s in values)
  1115. {
  1116. byte[] data = Convert.FromBase64String(s);
  1117. multiImageCapture.DataToImage(data);
  1118. }
  1119. }
  1120. return new Tuple<View, bool>(multiImageCapture, dfLayoutMultiEmbeddedImage.Properties.Required);
  1121. }
  1122. private Tuple<View, bool> LoadMultiSignaturePad(DFLayoutControl element)
  1123. {
  1124. string value = "";
  1125. DFLayoutMultiSignaturePad dfLayoutMultiSignaturePad = element as DFLayoutMultiSignaturePad;
  1126. DataButtonControl button = new DataButtonControl
  1127. {
  1128. Text = "Add Signatures",
  1129. };
  1130. if (loadData.TryGetValue(dfLayoutMultiSignaturePad.Name, out value))
  1131. {
  1132. button.Data = value;
  1133. }
  1134. MultiSignaturePad multiSignaturePad = new MultiSignaturePad(button.Data);
  1135. multiSignaturePad.OnMultiSignatureSaved += (result) =>
  1136. {
  1137. button.Data = result;
  1138. };
  1139. button.Clicked += (object sender, EventArgs e) =>
  1140. {
  1141. Navigation.PushAsync(multiSignaturePad);
  1142. };
  1143. return new Tuple<View, bool>(button, dfLayoutMultiSignaturePad.Properties.Required);
  1144. }
  1145. private Tuple<View, bool> LoadAddTaskField(DFLayoutControl element)
  1146. {
  1147. string value = "";
  1148. DFLayoutAddTaskField field = element as DFLayoutAddTaskField;
  1149. DFCreateTaskView taskView = new DFCreateTaskView();
  1150. taskView.OnAddTaskButtonClicked += () =>
  1151. {
  1152. AddEditTask addEditTask = new AddEditTask(Guid.Empty, "New task from Digital Form");
  1153. if (field.Properties.TaskType != null)
  1154. {
  1155. addEditTask.kanban.Type.ID = field.Properties.TaskType.ID;
  1156. try
  1157. {
  1158. addEditTask.kanban.Type.Description = new Client<KanbanType>().Query
  1159. (new Filter<KanbanType>(x => x.ID).IsEqualTo(field.Properties.TaskType.ID),
  1160. new Columns<KanbanType>(x => x.Description)).Rows.FirstOrDefault().Values[0].ToString();
  1161. }
  1162. catch { }
  1163. addEditTask.UpdateScreen(true);
  1164. }
  1165. addEditTask.OnTaskSaved += (taskNumber) =>
  1166. {
  1167. taskView.DisableButton();
  1168. taskView.TaskNumber = taskNumber.ToString();
  1169. };
  1170. Navigation.PushAsync(addEditTask);
  1171. };
  1172. if (loadData.TryGetValue(field.Name, out value))
  1173. {
  1174. taskView.TaskNumber = value;
  1175. taskView.DisableButton();
  1176. }
  1177. return new Tuple<View, bool>(taskView, field.Properties.Required);
  1178. }
  1179. private void FormatAndAddView(View view, DFLayoutControl element, bool isrequired)
  1180. {
  1181. try
  1182. {
  1183. if (element is DFLayoutField)
  1184. {
  1185. pairs[element as DFLayoutField] = view;
  1186. if (isSecure || readOnly || !string.IsNullOrWhiteSpace((element as DFLayoutField).GetPropertyValue<string>("Expression")))
  1187. view.IsEnabled = false;
  1188. Frame frame = new Frame
  1189. {
  1190. Content = view,
  1191. BorderColor = Color.FromHex("#15C7C1"),
  1192. BackgroundColor = Color.Default,
  1193. CornerRadius = 5,
  1194. Padding = 2,
  1195. HasShadow = false,
  1196. };
  1197. if (readOnly || isSecure)
  1198. {
  1199. frame.BorderColor = Color.Gray;
  1200. frame.BackgroundColor = Color.LightGray;
  1201. frame.VerticalOptions = LayoutOptions.FillAndExpand;
  1202. frame.MinimumHeightRequest = 60;
  1203. }
  1204. if (isrequired)
  1205. {
  1206. frame.BackgroundColor = isRequiredColor;
  1207. }
  1208. view = frame;
  1209. }
  1210. if (element.Row > 0) SetRow(view, element.Row - 1); //rows and columns coming in from the desktop designer start from 1, not 0 (most of the time??)
  1211. else if (element.Row == 0) SetRow(view, dfLayout.RowHeights.Count + 1);
  1212. if (element.RowSpan > 0) SetRowSpan(view, element.RowSpan);
  1213. else if (element.RowSpan == 0) SetRowSpan(view, 1);
  1214. if (element.Column > 0) SetColumn(view, element.Column - 1); //rows and columns coming in from the desktop designer start from 1, not 0 (most of the time??)
  1215. if (element.ColumnSpan > 0) SetColumnSpan(view, element.ColumnSpan);
  1216. if (element.ColumnSpan > 1)
  1217. {
  1218. view.HorizontalOptions = LayoutOptions.FillAndExpand;
  1219. if (view is Label)
  1220. {
  1221. view.HorizontalOptions = LayoutOptions.CenterAndExpand;
  1222. Label lblView = view as Label;
  1223. lblView.HorizontalTextAlignment = TextAlignment.Center;
  1224. view = lblView;
  1225. }
  1226. }
  1227. else if (element.ColumnSpan == 0) SetColumnSpan(view, 1);
  1228. view.SetValue(Grid.MarginProperty, 0.01);
  1229. if (element is DFLayoutSignaturePad)
  1230. {
  1231. view.Margin = new Thickness(25, 0, 25, 0);
  1232. }
  1233. Device.BeginInvokeOnMainThread(() => { Children.Add(view); });
  1234. if (element is DFLayoutHeader)
  1235. if ((element as DFLayoutHeader).Collapsed)
  1236. headersToCollapse.Add(view as DigitalFormsHeader);
  1237. }
  1238. catch
  1239. { }
  1240. }
  1241. #endregion
  1242. #region Save
  1243. public void SaveData(bool saveForLater)
  1244. {
  1245. try
  1246. {
  1247. results.Clear();
  1248. propertyResults.Clear();
  1249. isRequiredEmpty = false;
  1250. isRequiredMessage = "";
  1251. foreach (DFLayoutField field in pairs.Keys)
  1252. {
  1253. View view = pairs[field];
  1254. String userInput = AddResultsToDictionary(field, view);
  1255. if (isRequiredEmpty)
  1256. {
  1257. if (!saveForLater)
  1258. return;
  1259. }
  1260. AddPropertyToDictionary(field, userInput);
  1261. }
  1262. UpdateInstanceAndModel(saveForLater);
  1263. }
  1264. catch (Exception ex)
  1265. {
  1266. errors.Add(ex.Message);
  1267. }
  1268. }
  1269. #region Adding Results to dictionaries
  1270. private string AddResultsToDictionary(DFLayoutField field, View view, bool AddToDictionary = true) //"results" dictionary is the data to be saved in Form.Data
  1271. {
  1272. string userInput = "";
  1273. if (field is DFLayoutStringField || field is DFLayoutIntegerField || field is DFLayoutDoubleField)
  1274. {
  1275. if (field is DFLayoutStringField && (field as DFLayoutStringField).Properties.PopupEditor)
  1276. userInput = (view as DataButtonControl).Data;
  1277. else
  1278. userInput = (view as Editor).Text;
  1279. }
  1280. else if (field is DFLayoutBooleanField)
  1281. {
  1282. if ((view as CustomBoolean).ValueChanged)
  1283. {
  1284. userInput = (view as CustomBoolean).Value.ToString();
  1285. }
  1286. }
  1287. else if (field is DFLayoutDateField)
  1288. {
  1289. userInput = ((view as DatePicker).Date).ToString("dd-MM-yyyy");
  1290. }
  1291. else if (field is DFLayoutTimeField)
  1292. {
  1293. userInput = ((view as TimePicker).Time).ToString("c");
  1294. }
  1295. else if (field is DFLayoutOptionField)
  1296. {
  1297. userInput = GetStringFromOptionField(view);
  1298. }
  1299. else if (field is DFLayoutLookupField)
  1300. {
  1301. if (view is DataButtonControl)
  1302. {
  1303. var button = view as DataButtonControl;
  1304. userInput = FindIDForDesignLookupField(button); //userinput is used to set guid later on for properties, but will not get added to form data only for lookupfields
  1305. results.Add(field.Name, button.Data);
  1306. if (RetainedResults.IsFormRetained)
  1307. if ((field as DFLayoutLookupField).Properties.Retain)
  1308. RetainedResults.Results.Add(field.Name, button.Data);
  1309. }
  1310. else if (view is FrameButton) //currently only used for Products - we already have the Product.ID in Framebutton.Data (saved as Code,ID)
  1311. {
  1312. FrameButton framebutton = view as FrameButton;
  1313. if (!string.IsNullOrWhiteSpace(framebutton.Data))
  1314. {
  1315. string[] buttonData = framebutton.Data.Split(',');
  1316. if (AddToDictionary)
  1317. results.Add(field.Name, buttonData[0]); //[0] is product.code
  1318. userInput = buttonData[1]; //[1] is product id as string
  1319. if (RetainedResults.IsFormRetained)
  1320. if ((field as DFLayoutLookupField).Properties.Retain)
  1321. RetainedResults.Results.Add(field.Name, buttonData[0]);
  1322. }
  1323. }
  1324. }
  1325. else if (field is DFLayoutSignaturePad)
  1326. {
  1327. string value = "";
  1328. var grid = view as Grid;
  1329. var signaturePad = grid.Children.OfType<SfSignaturePad>().FirstOrDefault();
  1330. DFLayoutSignaturePad dFLayoutSignaturePad = field as DFLayoutSignaturePad;
  1331. if (loadData.TryGetValue(dFLayoutSignaturePad.Name, out value))
  1332. {
  1333. userInput = value;
  1334. }
  1335. else
  1336. {
  1337. if (useSavedSignatures.Contains(dFLayoutSignaturePad.Name))
  1338. {
  1339. ImageSource src = ImageSource.FromStream(() => new MemoryStream((Application.Current.Properties["SavedSignature"]) as byte[]));
  1340. userInput = ImageSourceToBase64(src);
  1341. }
  1342. else
  1343. {
  1344. signaturePad.Save();
  1345. if (signaturePad.ImageSource != null)
  1346. {
  1347. userInput = ImageSourceToBase64(signaturePad.ImageSource);
  1348. }
  1349. }
  1350. }
  1351. }
  1352. else if (field is DFLayoutEmbeddedImage)
  1353. {
  1354. var embeddedImage = view as EmbeddedImageCapture;
  1355. if (embeddedImage.Image.Source != null)
  1356. {
  1357. try
  1358. {
  1359. userInput = ImageSourceToBase64(embeddedImage.Image.Source);
  1360. }
  1361. catch (Exception e)
  1362. {
  1363. userInput = "";
  1364. }
  1365. }
  1366. }
  1367. else if (field is DFLayoutMultiImage)
  1368. {
  1369. var multiImage = view as MultiImageCapture;
  1370. if (multiImage.Images.Count > 0)
  1371. {
  1372. try
  1373. {
  1374. userInput = ImagesToBase64(multiImage.Images);
  1375. }
  1376. catch (Exception e)
  1377. {
  1378. userInput = "";
  1379. }
  1380. }
  1381. }
  1382. else if (field is DFLayoutAddTaskField)
  1383. {
  1384. var addTaskButton = view as DFCreateTaskView;
  1385. if (!string.IsNullOrWhiteSpace(addTaskButton.TaskNumber))
  1386. {
  1387. userInput = addTaskButton.TaskNumber;
  1388. }
  1389. }
  1390. else if (field is DFLayoutMultiSignaturePad)
  1391. {
  1392. var databutton = view as DataButtonControl;
  1393. if (!string.IsNullOrWhiteSpace(databutton.Data))
  1394. userInput = databutton.Data;
  1395. }
  1396. //add the field name and input to 'results' dictionary for processing outside of QAFormViewer
  1397. if (!String.IsNullOrWhiteSpace(userInput) && AddToDictionary)
  1398. {
  1399. if (field is DFLayoutLookupField)
  1400. { /*do nothing as results have already been added*/ }
  1401. else
  1402. {
  1403. try
  1404. {
  1405. results.Add(field.Name, userInput);
  1406. }
  1407. catch (Exception e)
  1408. {
  1409. errors.Add(e.Message);
  1410. }
  1411. if (RetainedResults.IsFormRetained)
  1412. {
  1413. AddRetainedToDictionary(field, userInput);
  1414. }
  1415. }
  1416. }
  1417. else CheckRequired(field);
  1418. return userInput;
  1419. }
  1420. private void AddPropertyToDictionary(DFLayoutField field, String userInput)
  1421. {
  1422. if (!string.IsNullOrWhiteSpace(userInput))
  1423. {
  1424. try
  1425. {
  1426. string property = "";
  1427. if (field is DFLayoutStringField)
  1428. property = (field as DFLayoutStringField).Properties.Property;
  1429. else if (field is DFLayoutIntegerField)
  1430. property = (field as DFLayoutIntegerField).Properties.Property;
  1431. else if (field is DFLayoutDoubleField)
  1432. property = (field as DFLayoutDoubleField).Properties.Property;
  1433. else if (field is DFLayoutBooleanField)
  1434. property = (field as DFLayoutBooleanField).Properties.Property;
  1435. else if (field is DFLayoutDateField)
  1436. property = (field as DFLayoutDateField).Properties.Property;
  1437. else if (field is DFLayoutTimeField)
  1438. property = (field as DFLayoutTimeField).Properties.Property;
  1439. else if (field is DFLayoutOptionField)
  1440. property = (field as DFLayoutOptionField).Properties.Property;
  1441. else if (field is DFLayoutLookupField)
  1442. property = (field as DFLayoutLookupField).Properties.Property;
  1443. //'propertyResults' dictionary for processing outside of QAFormViewer
  1444. if (!string.IsNullOrWhiteSpace(property)) propertyResults.Add(property, userInput);
  1445. }
  1446. catch (Exception e)
  1447. {
  1448. errors.Add(e.Message);
  1449. return;
  1450. }
  1451. }
  1452. }
  1453. private async void AddRetainedToDictionary(DFLayoutField field, string userInput)
  1454. {
  1455. await Task.Run(() =>
  1456. {
  1457. try
  1458. {
  1459. if (field is DFLayoutStringField)
  1460. {
  1461. if ((field as DFLayoutStringField).Properties.Retain)
  1462. RetainedResults.Results.Add(field.Name, userInput);
  1463. }
  1464. else if (field is DFLayoutIntegerField)
  1465. {
  1466. if ((field as DFLayoutIntegerField).Properties.Retain)
  1467. RetainedResults.Results.Add(field.Name, userInput);
  1468. }
  1469. else if (field is DFLayoutDoubleField)
  1470. {
  1471. if ((field as DFLayoutDoubleField).Properties.Retain)
  1472. RetainedResults.Results.Add(field.Name, userInput);
  1473. }
  1474. else if (field is DFLayoutBooleanField)
  1475. {
  1476. if ((field as DFLayoutBooleanField).Properties.Retain)
  1477. RetainedResults.Results.Add(field.Name, userInput);
  1478. }
  1479. else if (field is DFLayoutDateField)
  1480. {
  1481. if ((field as DFLayoutDateField).Properties.Retain)
  1482. RetainedResults.Results.Add(field.Name, userInput);
  1483. }
  1484. else if (field is DFLayoutTimeField)
  1485. {
  1486. if ((field as DFLayoutTimeField).Properties.Retain)
  1487. RetainedResults.Results.Add(field.Name, userInput);
  1488. }
  1489. else if (field is DFLayoutOptionField)
  1490. {
  1491. if ((field as DFLayoutOptionField).Properties.Retain)
  1492. RetainedResults.Results.Add(field.Name, userInput);
  1493. }
  1494. }
  1495. catch (Exception e)
  1496. {
  1497. errors.Add("Retained results error: " + e.Message);
  1498. }
  1499. });
  1500. }
  1501. #endregion
  1502. #region Checks / Custom methods
  1503. private void CheckRequired(DFLayoutField field)
  1504. {
  1505. if (field is DFLayoutStringField)
  1506. {
  1507. if ((field as DFLayoutStringField).Properties.Required)
  1508. {
  1509. isRequiredEmpty = true;
  1510. isRequiredMessage = (field as DFLayoutStringField).Description;
  1511. }
  1512. }
  1513. else if (field is DFLayoutIntegerField)
  1514. {
  1515. if ((field as DFLayoutIntegerField).Properties.Required)
  1516. {
  1517. isRequiredEmpty = true;
  1518. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  1519. }
  1520. }
  1521. else if (field is DFLayoutDoubleField)
  1522. {
  1523. if ((field as DFLayoutDoubleField).Properties.Required)
  1524. {
  1525. {
  1526. isRequiredEmpty = true;
  1527. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  1528. }
  1529. }
  1530. }
  1531. else if (field is DFLayoutBooleanField)
  1532. {
  1533. if ((field as DFLayoutBooleanField).Properties.Required)
  1534. {
  1535. {
  1536. isRequiredEmpty = true;
  1537. isRequiredMessage = (field as DFLayoutBooleanField).Description;
  1538. }
  1539. }
  1540. }
  1541. else if (field is DFLayoutDateField)
  1542. {
  1543. if ((field as DFLayoutDateField).Properties.Required)
  1544. {
  1545. {
  1546. isRequiredEmpty = true;
  1547. isRequiredMessage = (field as DFLayoutDateField).Description;
  1548. }
  1549. }
  1550. }
  1551. else if (field is DFLayoutTimeField)
  1552. {
  1553. if ((field as DFLayoutTimeField).Properties.Required)
  1554. {
  1555. {
  1556. isRequiredEmpty = true;
  1557. isRequiredMessage = (field as DFLayoutTimeField).Description;
  1558. }
  1559. }
  1560. }
  1561. else if (field is DFLayoutOptionField)
  1562. {
  1563. if ((field as DFLayoutOptionField).Properties.Required)
  1564. {
  1565. {
  1566. isRequiredEmpty = true;
  1567. isRequiredMessage = (field as DFLayoutOptionField).Description;
  1568. }
  1569. }
  1570. }
  1571. else if (field is DFLayoutLookupField)
  1572. {
  1573. if ((field as DFLayoutLookupField).Properties.Required)
  1574. {
  1575. {
  1576. isRequiredEmpty = true;
  1577. isRequiredMessage = (field as DFLayoutLookupField).Description;
  1578. }
  1579. }
  1580. }
  1581. else if (field is DFLayoutSignaturePad)
  1582. {
  1583. if ((field as DFLayoutSignaturePad).Properties.Required)
  1584. {
  1585. {
  1586. isRequiredEmpty = true;
  1587. isRequiredMessage = (field as DFLayoutSignaturePad).Description;
  1588. }
  1589. }
  1590. }
  1591. else if (field is DFLayoutEmbeddedImage)
  1592. {
  1593. if ((field as DFLayoutEmbeddedImage).Properties.Required)
  1594. {
  1595. {
  1596. isRequiredEmpty = true;
  1597. isRequiredMessage = (field as DFLayoutEmbeddedImage).Description;
  1598. }
  1599. }
  1600. }
  1601. else if (field is DFLayoutMultiImage)
  1602. {
  1603. if ((field as DFLayoutMultiImage).Properties.Required)
  1604. {
  1605. {
  1606. isRequiredEmpty = true;
  1607. isRequiredMessage = (field as DFLayoutMultiImage).Description;
  1608. }
  1609. }
  1610. }
  1611. else if (field is DFLayoutMultiSignaturePad)
  1612. {
  1613. if ((field as DFLayoutMultiSignaturePad).Properties.Required)
  1614. {
  1615. {
  1616. isRequiredEmpty = true;
  1617. isRequiredMessage = (field as DFLayoutMultiSignaturePad).Description;
  1618. }
  1619. }
  1620. }
  1621. }
  1622. private string ImagesToBase64(List<Image> images)
  1623. {
  1624. List<string> strings = new List<string>();
  1625. foreach (Image image in images)
  1626. {
  1627. strings.Add(ImageSourceToBase64(image.Source));
  1628. }
  1629. return Serialization.Serialize(strings);
  1630. }
  1631. private string ImageSourceToBase64(ImageSource source)
  1632. {
  1633. StreamImageSource streamImageSource = (StreamImageSource)source;
  1634. System.Threading.CancellationToken cancellationToken = System.Threading.CancellationToken.None;
  1635. Task<Stream> task = streamImageSource.Stream(cancellationToken);
  1636. Stream stream = task.Result;
  1637. byte[] bytes = new byte[stream.Length];
  1638. stream.Read(bytes, 0, bytes.Length);
  1639. string s = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
  1640. return s;
  1641. }
  1642. private string FindIDForDesignLookupField(DataButtonControl button)
  1643. {
  1644. try
  1645. {
  1646. string userInputValue = button.Data;
  1647. string guidString = "";
  1648. if (userInputValue != nullOrInvalidType)
  1649. {
  1650. foreach (KeyValuePair<DFLayoutLookupField, Dictionary<Guid, string>> pair in dfLayoutLookupFieldLookupOptions)
  1651. {
  1652. foreach (KeyValuePair<Guid, string> innerPair in pair.Value)
  1653. {
  1654. if (innerPair.Value == userInputValue)
  1655. {
  1656. guidString = innerPair.Key.ToString();
  1657. }
  1658. }
  1659. }
  1660. }
  1661. return guidString;
  1662. }
  1663. catch
  1664. {
  1665. return "";
  1666. }
  1667. }
  1668. #endregion
  1669. #region Save Completion
  1670. //point of determination for whether or not QA form gets completed or saved for later
  1671. private void UpdateInstanceAndModel(bool saveForLater)
  1672. {
  1673. if (results.Count != 0)
  1674. {
  1675. if (!saveForLater)
  1676. {
  1677. CompleteForm();
  1678. }
  1679. model.Instance.FormCompletedBy.ID = userID;
  1680. if (digitalFormID != Guid.Empty) model.Instance.Form.ID = digitalFormID;
  1681. DigitalForm.SerializeFormData(model.Instance, QueryVariables(model.Instance), results.ToDictionary(x => x.Key, x => x.Value as object));
  1682. FormData = model.Instance.FormData;
  1683. if (model.Instance.FormStarted == DateTime.MinValue)
  1684. {
  1685. model.Instance.FormStarted = timeStarted;
  1686. }
  1687. TimeSpan span = DateTime.Now - timeStarted;
  1688. model.Instance.FormOpen = model.Instance.FormOpen + span;
  1689. model.Update(null);
  1690. }
  1691. }
  1692. public List<DigitalFormVariable> QueryVariables(IDigitalFormInstance form)
  1693. {
  1694. List<DigitalFormVariable> variables = new List<DigitalFormVariable>();
  1695. var table = new Client<DigitalFormVariable>().Query(
  1696. new Filter<DigitalFormVariable>(x => x.Form.ID).IsEqualTo(form.Form.ID),
  1697. new Columns<DigitalFormVariable>(x => x.Code, x => x.Parameters, x => x.Description, x => x.VariableType),
  1698. null
  1699. );
  1700. foreach (CoreRow coreRow in table.Rows)
  1701. {
  1702. var variable = coreRow.ToObject<DigitalFormVariable>();
  1703. variables.Add(variable);
  1704. }
  1705. return variables;
  1706. }
  1707. private void CompleteForm()
  1708. {
  1709. model.Instance.FormCompleted = DateTime.Now;
  1710. FormCompleted = model.Instance.FormCompleted;
  1711. model.Instance.Location.Longitude = location.Longitude;
  1712. model.Instance.Location.Latitude = location.Latitude;
  1713. model.Instance.Location.Timestamp = model.Instance.FormCompleted;
  1714. }
  1715. #endregion
  1716. #endregion
  1717. #region Expressions
  1718. public object GetFieldValue(string field)
  1719. {
  1720. try
  1721. {
  1722. Tuple<DFLayoutField, View> tuple = FindView(field);
  1723. return GetValueFromView(tuple.Item1, tuple.Item2);
  1724. }
  1725. catch
  1726. {
  1727. return "";
  1728. }
  1729. }
  1730. public void SetFieldValue(string field, object value)
  1731. {
  1732. try
  1733. {
  1734. Tuple<DFLayoutField, View> tuple = FindView(field);
  1735. SetValueOfView(tuple.Item1, tuple.Item2, value);
  1736. }
  1737. catch { }
  1738. }
  1739. private void SetValueOfView(DFLayoutField field, View view, object value)
  1740. {
  1741. if (field is DFLayoutBooleanField)
  1742. (view as CustomBoolean).Value = (bool)value;
  1743. else if (field is DFLayoutStringField || field is DFLayoutIntegerField || field is DFLayoutDoubleField)
  1744. {
  1745. if (field is DFLayoutStringField && (field as DFLayoutStringField).Properties.PopupEditor)
  1746. {
  1747. (view as DataButtonControl).Data = value.ToString();
  1748. (view as DataButtonControl).Text = value.ToString();
  1749. }
  1750. else
  1751. (view as Editor).Text = value.ToString();
  1752. }
  1753. else if (field is DFLayoutDateField)
  1754. (view as DatePicker).Date = (DateTime)(value as DateTime?);
  1755. else if (field is DFLayoutDateTimeField)
  1756. (view as TimePicker).Time = (TimeSpan)(value as TimeSpan?);
  1757. else if (field is DFLayoutOptionField)
  1758. AssignPickerOption(view, field as DFLayoutOptionField, value as string);
  1759. else if (field is DFLayoutLookupField)
  1760. AssignLookupOption(view, value as string);
  1761. else if (field is DFLayoutEmbeddedImage)
  1762. AssignImage(view, value as byte[]);
  1763. }
  1764. private void AssignImage(View view, byte[] bytes)
  1765. {
  1766. var imageCapture = view as EmbeddedImageCapture;
  1767. imageCapture.DataToImage(bytes);
  1768. }
  1769. private void AssignLookupOption(View view, string value)
  1770. {
  1771. if (view is DataButtonControl)
  1772. {
  1773. (view as DataButtonControl).Text = value;
  1774. (view as DataButtonControl).Data = value;
  1775. }
  1776. else if (view is FrameButton) //currently only used for Products - we already have the Product.ID in Framebutton.Data (saved as Code,ID)
  1777. {
  1778. (view as FrameButton).SetButtonText(value);
  1779. (view as FrameButton).Data = value + "," + Guid.Empty.ToString();
  1780. }
  1781. }
  1782. private Tuple<DFLayoutField, View> FindView(string field)
  1783. {
  1784. DFLayoutField dflayoutfield = pairs.Keys.FirstOrDefault(x => x.Name == field);
  1785. View view = pairs[dflayoutfield];
  1786. return new Tuple<DFLayoutField, View>(dflayoutfield, view);
  1787. }
  1788. private void AssignPickerOption(View view, DFLayoutOptionField field, string value)
  1789. {
  1790. string s = field.Properties.Options;
  1791. string[] substrings = s.Split(',');
  1792. var optionList = substrings.ToList();
  1793. if (GlobalVariables.DeviceString == "i" || GlobalVariables.DeviceString == "I")
  1794. {
  1795. var iOSPicker = view as CustomPickeriOS;
  1796. iOSPicker.SelectedIndex = optionList.IndexOf(value);
  1797. }
  1798. else
  1799. {
  1800. var picker = view as Picker;
  1801. picker.SelectedIndex = optionList.IndexOf(value);
  1802. }
  1803. }
  1804. private object GetValueFromView(DFLayoutField field, View view)
  1805. {
  1806. if (field is DFLayoutBooleanField)
  1807. return (view as CustomBoolean).Value;
  1808. if (field is DFLayoutStringField)
  1809. {
  1810. if ((field as DFLayoutStringField).Properties.PopupEditor)
  1811. return (view as DataButtonControl).Data;
  1812. else
  1813. return (view as Editor).Text;
  1814. }
  1815. else if (field is DFLayoutIntegerField)
  1816. return int.Parse((view as Editor).Text);
  1817. else if (field is DFLayoutDoubleField)
  1818. return double.Parse((view as Editor).Text);
  1819. else if (field is DFLayoutDateField)
  1820. return (view as DatePicker).Date;
  1821. else if (field is DFLayoutDateTimeField)
  1822. return (view as TimePicker).Time;
  1823. else if (field is DFLayoutOptionField)
  1824. return GetStringFromOptionField(view);
  1825. else if (field is DFLayoutLookupField)
  1826. return GetStringFromLookupField(view);
  1827. else if (field is DFLayoutSignaturePad)
  1828. return GetByteArrayFromSignaturePad(view, field.Name);
  1829. else if (field is DFLayoutEmbeddedImage)
  1830. return GetByteArrayFromEmbeddedImage(view);
  1831. else if (field is DFLayoutMultiImage)
  1832. return GetByteArrayListFromMultiImage(view);
  1833. else return "";
  1834. }
  1835. private object GetByteArrayListFromMultiImage(View view)
  1836. {
  1837. List<byte[]> list = new List<byte[]>();
  1838. var multiImage = view as MultiImageCapture;
  1839. if (multiImage.Images.Count > 0)
  1840. {
  1841. foreach (Image image in multiImage.Images)
  1842. {
  1843. string base64 = ImageSourceToBase64(image.Source);
  1844. list.Add(Convert.FromBase64String(base64));
  1845. }
  1846. }
  1847. return list;
  1848. }
  1849. private object GetByteArrayFromEmbeddedImage(View view)
  1850. {
  1851. var embeddedImage = view as EmbeddedImageCapture;
  1852. if (embeddedImage.Image.Source != null)
  1853. {
  1854. string base64 = ImageSourceToBase64(embeddedImage.Image.Source);
  1855. return Convert.FromBase64String(base64);
  1856. }
  1857. else
  1858. return null;
  1859. }
  1860. private byte[] GetByteArrayFromSignaturePad(View view, string name)
  1861. {
  1862. var grid = view as Grid;
  1863. var signaturePad = grid.Children.OfType<SfSignaturePad>().FirstOrDefault();
  1864. if (useSavedSignatures.Contains(name))
  1865. {
  1866. return Application.Current.Properties["SavedSignature"] as byte[];
  1867. }
  1868. else
  1869. {
  1870. signaturePad.Save();
  1871. if (signaturePad.ImageSource != null)
  1872. {
  1873. string base64 = ImageSourceToBase64(signaturePad.ImageSource);
  1874. return Convert.FromBase64String(base64);
  1875. }
  1876. else
  1877. return null;
  1878. }
  1879. }
  1880. private object GetStringFromLookupField(View view)
  1881. {
  1882. string value = "";
  1883. if (view is DataButtonControl)
  1884. {
  1885. var button = view as DataButtonControl;
  1886. value = FindIDForDesignLookupField(button); //userinput is used to set guid later on for properties, but will not get added to form data only for lookupfields
  1887. }
  1888. else if (view is FrameButton) //currently only used for Products - we already have the Product.ID in Framebutton.Data (saved as Code,ID)
  1889. {
  1890. FrameButton framebutton = view as FrameButton;
  1891. if (!string.IsNullOrWhiteSpace(framebutton.Data))
  1892. {
  1893. string[] buttonData = framebutton.Data.Split(',');
  1894. value = buttonData[1]; //[1] is product id as string
  1895. }
  1896. }
  1897. return value;
  1898. }
  1899. private string GetStringFromOptionField(View view)
  1900. {
  1901. if (GlobalVariables.DeviceString == "i" || GlobalVariables.DeviceString == "I")
  1902. {
  1903. var iOSPicker = view as CustomPickeriOS;
  1904. if (iOSPicker.SelectedIndex != -1)
  1905. {
  1906. return iOSPicker.SelectedItem.ToString();
  1907. }
  1908. else
  1909. return "";
  1910. }
  1911. else
  1912. {
  1913. var picker = view as Picker;
  1914. if (picker.SelectedIndex != -1)
  1915. {
  1916. return picker.SelectedItem.ToString();
  1917. }
  1918. else
  1919. return "";
  1920. }
  1921. }
  1922. public object GetFieldData(string fieldName, string dataField)
  1923. {
  1924. Tuple<DFLayoutField, View> tuple = FindView(fieldName);
  1925. try
  1926. {
  1927. if (tuple.Item1 is DFLayoutLookupField)
  1928. {
  1929. DFLayoutLookupField field = tuple.Item1 as DFLayoutLookupField;
  1930. string type = field.Properties.LookupType;
  1931. Type lookuptype = CoreUtils.GetEntityOrNull(type);
  1932. if (lookuptype == typeof(Product))
  1933. {
  1934. var framebutton = tuple.Item2 as FrameButton;
  1935. string[] buttonData = framebutton.Data.Split(',');
  1936. string id = buttonData[1]; //[1] is product id as string
  1937. CoreTable table = new Client<Product>().Query(new Filter<Product>(x => x.ID).IsEqualTo(Guid.Parse(id)), new Columns<Product>(x => x.Image.ID));
  1938. if (table.Rows.Any())
  1939. {
  1940. Guid returnid = table.Rows.FirstOrDefault().Get<Product, Guid>(x => x.Image.ID);
  1941. return returnid;
  1942. }
  1943. else
  1944. return null;
  1945. }
  1946. else
  1947. {
  1948. var button = tuple.Item2 as DataButtonControl;
  1949. Dictionary<string, object> dict = button.ExtraData[button.ChosenID];
  1950. return dict[dataField];
  1951. }
  1952. }
  1953. else
  1954. return null;
  1955. }
  1956. catch
  1957. {
  1958. return null;
  1959. }
  1960. }
  1961. public void SetFieldColour(string field, System.Drawing.Color? colour = null)
  1962. {
  1963. //find the view, set the background colour
  1964. }
  1965. #endregion
  1966. }
  1967. }