DataEntryPanel.xaml.cs 8.4 KB

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