DataEntryPanel.xaml.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. using Comal.Classes;
  2. using InABox.Clients;
  3. using InABox.Core;
  4. using InABox.DynamicGrid;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.ComponentModel;
  8. using System.Linq;
  9. using System.Windows;
  10. using System.Windows.Controls;
  11. using System.Reflection;
  12. namespace PRSDesktop
  13. {
  14. /// <summary>
  15. /// Interaction logic for DataEntryPanel.xaml
  16. /// </summary>
  17. /// <remarks>
  18. /// This is a host because it has a singular code popup editor
  19. /// </remarks>
  20. public partial class DataEntryPanel : UserControl, IBasePanel, IDynamicEditorHost
  21. {
  22. IPopupEditorControl? Popup;
  23. public DataEntryPanel()
  24. {
  25. InitializeComponent();
  26. }
  27. public void Setup()
  28. {
  29. var types = CoreUtils.Entities
  30. .Where(x => x.IsAssignableTo(typeof(Entity))
  31. && x.HasInterface(typeof(IRemotable))
  32. && x.HasInterface(typeof(IPersistent))
  33. && x.GetCustomAttribute<AutoEntity>() is null
  34. && Security.CanEdit(x)
  35. && x.HasInterface<IScannable>())
  36. .Select(x => new Tuple<string, Type?>(x.Name, x)).OrderBy(x => x.Item1).ToList();
  37. types.Insert(0, new("", null));
  38. TypeBox.ItemsSource = types;
  39. TypeBox.DisplayMemberPath = "Item1";
  40. TypeBox.SelectedValuePath = "Item2";
  41. ScanPanel.Setup();
  42. }
  43. public void Refresh()
  44. {
  45. ScanPanel.Refresh();
  46. }
  47. public bool IsReady { get; set; }
  48. public string SectionName => "Data Entry";
  49. public DataModel DataModel(Selection selection)
  50. {
  51. return new EmptyDataModel();
  52. }
  53. public event DataModelUpdateEvent? OnUpdateDataModel;
  54. public void CreateToolbarButtons(IPanelHost host)
  55. {
  56. if (Security.IsAllowed<CanSetupScanTags>())
  57. {
  58. host.CreateSetupAction(new PanelAction
  59. {
  60. Caption = "Scan Tags",
  61. OnExecute = (action) =>
  62. {
  63. var list = new MasterList(typeof(ScanTag));
  64. list.ShowDialog();
  65. }
  66. });
  67. }
  68. }
  69. public void Heartbeat(TimeSpan time)
  70. {
  71. }
  72. public Dictionary<string, object[]> Selected()
  73. {
  74. return new Dictionary<string, object[]>();
  75. }
  76. private void CheckSaved(CancelEventArgs cancel)
  77. {
  78. var result = MessageBox.Show("You have changes that have not been saved; do you wish to save these changes?", "Save Changes?", MessageBoxButton.YesNoCancel);
  79. if (result == MessageBoxResult.Yes)
  80. {
  81. Editor.SaveItem(cancel);
  82. if (!cancel.Cancel)
  83. {
  84. MessageBox.Show("Purchase Order saved.");
  85. }
  86. }
  87. else if (result == MessageBoxResult.Cancel)
  88. {
  89. cancel.Cancel = true;
  90. }
  91. }
  92. private bool CheckSaved()
  93. {
  94. var cancel = new CancelEventArgs();
  95. CheckSaved(cancel);
  96. return !cancel.Cancel;
  97. }
  98. public void Shutdown(CancelEventArgs? cancel)
  99. {
  100. if(bChanged)
  101. {
  102. CheckSaved(cancel);
  103. }
  104. if (cancel.Cancel == false)
  105. ScanPanel.Shutdown(cancel);
  106. }
  107. #region Host
  108. private HashSet<Type> _loadedTypes = new();
  109. public DynamicGridColumns Columns { get; set; } = new();
  110. IEnumerable<DynamicGridColumn> IDynamicEditorHost.Columns => Columns;
  111. public void LoadColumns(string column, Dictionary<string, string> columns)
  112. {
  113. var selectedType = TypeBox.SelectedValue as Type;
  114. if (selectedType is null) return;
  115. columns.Clear();
  116. foreach (var c in LookupFactory.DefineColumns(selectedType).ColumnNames().Where(x => x != "ID"))
  117. {
  118. columns.Add(c, c);
  119. }
  120. if (Popup?.EditorDefinition is CodePopupEditorControl codePopup && !columns.ContainsKey(codePopup.CodeColumn))
  121. {
  122. columns.Add(codePopup.CodeColumn, codePopup.CodeColumn);
  123. }
  124. }
  125. public IFilter? DefineFilter(Type type) => LookupFactory.DefineFilter(type);
  126. public void LoadLookups(ILookupEditorControl sender)
  127. {
  128. var editor = sender.EditorDefinition as ILookupEditor;
  129. var colname = sender.ColumnName;
  130. var values = editor.Values(colname, Editor.Items);
  131. sender.LoadLookups(values);
  132. }
  133. object?[] IDynamicEditorHost.GetItems() => Editor.Items;
  134. public BaseEditor? GetEditor(DynamicGridColumn column) => column.Editor.CloneEditor();
  135. #endregion
  136. private void ClearEditor(Type TEntity)
  137. {
  138. UpdateEditor(TEntity, null);
  139. if(Popup is not null)
  140. {
  141. Popup.Value = Guid.Empty;
  142. }
  143. }
  144. private bool EditorChanged = false;
  145. private bool bChanged = true;
  146. private IDynamicDataGrid UpdateEditor(Type TEntity, BaseObject[]? items)
  147. {
  148. bChanged = false;
  149. ScanPanel.ScanGrid.IsEnabled = true;
  150. DetailBorder.Child = null;
  151. Editor = new EmbeddedDynamicEditorForm();
  152. Editor.SetLayoutType<VerticalDynamicEditorGridLayout>();
  153. Editor.SetValue(Grid.RowProperty, 1);
  154. Editor.SetValue(Grid.ColumnProperty, 0);
  155. Editor.SetValue(Grid.ColumnSpanProperty, 4);
  156. EditorChanged = false;
  157. Editor.OnAfterEditorValueChanged += (sender, column) =>
  158. {
  159. EditorChanged = true;
  160. return null;
  161. };
  162. Editor.OnOK += () =>
  163. {
  164. var cancel = new System.ComponentModel.CancelEventArgs();
  165. Editor.SaveItem(cancel);
  166. if (!cancel.Cancel)
  167. {
  168. ClearEditor(TEntity);
  169. bChanged = false;
  170. ScanPanel.ScanGrid.IsEnabled = true; }
  171. };
  172. Editor.OnCancel += () =>
  173. {
  174. ClearEditor(TEntity);
  175. bChanged = false;
  176. ScanPanel.ScanGrid.IsEnabled = true;
  177. };
  178. Editor.OnChanged += (sender, args) =>
  179. {
  180. bChanged = true;
  181. ScanPanel.ScanGrid.IsEnabled = false;
  182. };
  183. DetailBorder.Child = Editor;
  184. var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), TEntity);
  185. grid.InitialiseEditorForm(Editor, items ?? new object[] { Activator.CreateInstance(TEntity)! });
  186. return (grid as IDynamicDataGrid)!;
  187. }
  188. private void TypeBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
  189. {
  190. var selectedType = TypeBox.SelectedValue as Type;
  191. if (selectedType is not null)
  192. {
  193. var dataGrid = UpdateEditor(selectedType, null);
  194. var editorColumns = dataGrid.LoadEditorColumns();
  195. if (Popup is UIElement element)
  196. DetailHeader.Children.Remove(element);
  197. var code = DatabaseSchema.Properties(selectedType)
  198. .Where(x => x.Parent is null && (x.Editor is CodeEditor || x.Editor is UniqueCodeEditor)
  199. && x.Editor.Editable.EditorVisible())
  200. .FirstOrDefault();
  201. BaseEditor editor;
  202. if (code is not null)
  203. {
  204. editor = new CodePopupEditor(selectedType) { CodeColumn = code.Name };
  205. Popup = new CodePopupEditorControl { Margin = new Thickness(5), CodeColumn = code.Name };
  206. }
  207. else
  208. {
  209. editor = new PopupEditor(selectedType);
  210. Popup = new PopupEditorControl { Margin = new Thickness(5) };
  211. }
  212. if (Popup is IPopupEditorControl popupEditor)
  213. {
  214. Popup.ColumnName = "ID";
  215. popupEditor.Host = this;
  216. Columns = new DynamicGridColumns();
  217. Columns.ExtractColumns(selectedType);
  218. }
  219. var el = (Popup as UIElement)!;
  220. el.SetValue(DockPanel.DockProperty,Dock.Left);
  221. Popup.EditorDefinition = editor;
  222. Popup.OnEditorValueChanged += (s, v) =>
  223. {
  224. var entityID = (Guid)v["ID"];
  225. BaseObject[]? objs = null;
  226. if (entityID != Guid.Empty)
  227. {
  228. var obj = Client.Create(selectedType)
  229. .Query(
  230. Filter.Create<Entity>(selectedType, x => x.ID).IsEqualTo(entityID),
  231. editorColumns)
  232. .ToObjects(selectedType)
  233. .FirstOrDefault();
  234. if (obj is not null)
  235. {
  236. objs = new BaseObject[] { obj };
  237. }
  238. }
  239. UpdateEditor(selectedType, objs);
  240. };
  241. Popup.Configure();
  242. Popup.Loaded = true;
  243. DetailHeader.Children.Add(el);
  244. }
  245. else
  246. {
  247. DetailBorder.Child = null;
  248. if (Popup is UIElement el)
  249. DetailHeader.Children.Remove(el);
  250. }
  251. }
  252. private void ScanPanel_OnSelectAppliesTo(string appliesTo)
  253. {
  254. CoreUtils.TryGetEntity(appliesTo, out var entity);
  255. TypeBox.SelectedValue = entity;
  256. }
  257. }
  258. }