using Comal.Classes; using InABox.Clients; using InABox.Core; using InABox.DynamicGrid; using InABox.Wpf; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using InABox.Configuration; using PRSDesktop.Panels.DataEntry.Grids; namespace PRSDesktop; public class DataEntryPanelSettings : BaseObject, IUserConfigurationSettings { private static readonly double DefaultCacheAge = 7; [NullEditor] public double PreviewWidth { get; set; } [Comment("Age of cached documents before they are deleted (days)")] [DoubleEditor] public double CacheAge { get; set; } = DefaultCacheAge; } /// /// Interaction logic for DataEntryPanel.xaml /// public partial class DataEntryPanel : UserControl, IBasePanel, IDynamicEditorHost { private DataEntryPanelSettings _settings; //IPopupEditorControl? _popup; private IDynamicDataGrid? _grid; private Type? _selectedType; // The id of the entity currently being edited. private Guid _entityID; // The id of the entity we selected from the grid, as it was when we selected it; this is to cancel, because the lookup for the item // updates _entityID, and we need to set it back when cancelling. private Guid _originalID; private bool _processenabled; private Entity? _entity; private Button? _process; private bool _isChanged; private bool IsChanged { get => _isChanged; set { if(_isChanged != value) { _isChanged = value; Editor.HideButtons = !value; if (_process != null) _process.IsEnabled = value; _documents._dataEntryGrid.IsEnabled = !value; } } } public void Select(Type? type, Guid id) { ClearEditor(); _selectedType = type; _entityID = id; if (_selectedType != null) { CreateEditor(); PopulateEditor(); //LoadPopup(); } } private void ScanPanel_OnSelectScan(string appliesto, Guid entityid, bool processenabled) { _processenabled = processenabled; _originalID = entityid; Select( CoreUtils.GetEntityOrNull(appliesto), entityid ); } public DataEntryPanel() { InitializeComponent(); LoadSettings(); } private void LoadSettings() { _settings = new UserConfiguration().Load(); _panel.AnchorWidth = _settings.PreviewWidth > 0.0F ? _settings.PreviewWidth : 500F; } public void Setup() { _documents.Setup(); IsChanged = false; } public void Refresh() { if (CheckSaved()) { _documents.Refresh(); IsChanged = false; } } public bool IsReady { get; set; } public string SectionName => "Data Entry"; public DataModel DataModel(Selection selection) { return new EmptyDataModel(); } public event DataModelUpdateEvent? OnUpdateDataModel; public void CreateToolbarButtons(IPanelHost host) { if (Security.IsAllowed()) { host.CreateSetupAction(new PanelAction("Data Entry Tags", null, (action) => { var list = new MasterList(typeof(DataEntryTag)); list.ShowDialog(); })); host.CreateSetupAction(new PanelAction("Settings", null, (action) => { var settings = new UserConfiguration().Load(); var grid = new DynamicItemsListGrid(); if (grid.EditItems(new DataEntryPanelSettings[] { settings })) { new UserConfiguration().Save(settings); LoadSettings(); } })); } } public void Heartbeat(TimeSpan time) { } public Dictionary Selected() { return new Dictionary(); } private void CheckSaved(CancelEventArgs cancel) { if (!_isChanged) { return; } var result = MessageBox.Show("You have changes that have not been saved; do you wish to save these changes?", "Save Changes?", MessageBoxButton.YesNoCancel); if (result == MessageBoxResult.Yes) { if (!Editor.Validate()) { cancel.Cancel = true; return; } DoSave(false); if (!cancel.Cancel) MessageBox.Show("Item saved."); } else if (result == MessageBoxResult.Cancel) { cancel.Cancel = true; } } private bool CheckSaved() { var cancel = new CancelEventArgs(); CheckSaved(cancel); return !cancel.Cancel; } public void Shutdown(CancelEventArgs? cancel) { if (cancel != null) CheckSaved(cancel); if (cancel?.Cancel != true) _documents.Shutdown(cancel); } #region Host public Type GetEditorType() => _selectedType ?? typeof(BaseObject); public void LoadLookups(ILookupEditorControl sender) { var colname = sender.ColumnName; var values = sender.LookupEditorDefinition.Values(colname, Editor.Items); sender.LoadLookups(values); } BaseObject[] IDynamicEditorHost.GetItems() => Editor.Items; public BaseEditor? GetEditor(DynamicGridColumn column) => column.Editor.CloneEditor(); #endregion private void ClearEditor() { DetailBorder.Child = null; IsChanged = false; //if (_popup is UIElement element) // DetailHeader.Children.Remove(element); } private void CreateEditor() { if (_selectedType == null) return; Editor = new EmbeddedDynamicEditorForm(); if (_selectedType == typeof(Bill)) Editor.SetLayoutType(); else Editor.SetLayoutType(); Editor.HighlightButtons = true; Editor.HideButtons = true; Editor.SetValue(Grid.RowProperty, 1); Editor.SetValue(Grid.ColumnProperty, 0); Editor.SetValue(Grid.ColumnSpanProperty, 4); Editor.OnOK += () => { DoSave(false); }; Editor.OnCancel += () => { _entityID = _originalID; Select(_selectedType, _entityID); }; Editor.OnChanged += (sender, args) => IsChanged = true; DetailBorder.Child = Editor; _grid = (DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), _selectedType) as IDynamicDataGrid)!; _grid.OnCustomiseEditor += (sender, items, column, editor) => { if ((editor is BaseCodeEditor be) && editor.Editable.EditorVisible()) { be.Buttons = new[] { new EditorButton(null, "..", 30, DoLookup, false) }; } }; _grid.OnAfterEditorValueChangedEvent += (sender, args) => { IsChanged = IsChanged || (_entity?.IsChanged() == true || _originalID != _entityID); return null; }; if (_grid is DynamicDataGrid milestoneGrid) { milestoneGrid.OnValidate += (o, items, err) => { if (items.Any(x => x.ID == Guid.Empty)) { err.Add("Cannot create a new milestone from Data Entry screen. Please select a milestone to edit."); } }; } } private void DoLookup(object editor, object? item) { if (_selectedType == null) return; if (editor is CodeEditorControl ce) { Dictionary? filter = null; if (ce.Value != null) { filter = new Dictionary { [ce.ColumnName] = ce.Value }; } Type? gridType = null; if (_selectedType == typeof(JobDocumentSetMileStone)) { gridType = typeof(JobDocumentSetMileStoneDataEntryPopupGrid); } var popup = new PopupList(_selectedType, _entityID, Array.Empty(), filter, gridType: gridType); popup.OnDefineFilter += LookupFactory.DefineFilter; if (popup.ShowDialog() == true) { _entityID = popup.ID; Select(_selectedType, _entityID); } } } private void SaveDocument(DataEntryDocument dataEntryDocument) { var doctype = CoreUtils.TypeList(x => { var entityDoc = x.GetInterfaceDefinition(typeof(IEntityDocument<>)); if (entityDoc is null) { return false; } var linkType = entityDoc.GenericTypeArguments[0].GetInterfaceDefinition(typeof(IEntityLink<>)); if (linkType is null) { return false; } return linkType.GenericTypeArguments[0] == _selectedType; }).FirstOrDefault(); if(doctype is null) { return; } var doc = (IEntityDocument)Activator.CreateInstance(doctype)!; CoreUtils.SetPropertyValue(doc, "EntityLink.ID", _entityID); doc.DocumentLink.ID = dataEntryDocument.Document.ID; doc.Thumbnail = dataEntryDocument.Thumbnail; ClientFactory.CreateClient(doctype).Save(doc,"Added from Data Entry Screen"); } private void DoSave(bool markasprocessed) { var cancel = new System.ComponentModel.CancelEventArgs(); if (markasprocessed && (_entity is IDataEntryInstance scannable)) scannable.DataEntered = DateTime.Now; Editor.SaveItem(cancel); if (!cancel.Cancel) { _originalID = _entityID; _entityID = _entity.ID; IsChanged = false; var row = _documents._dataEntryGrid.SelectedRows.FirstOrDefault(); if (row != null) { var scan = row.ToObject(); scan.EntityID = _entity.ID; if (markasprocessed) { SaveDocument(scan); scan.Archived = DateTime.Now; } if (scan.IsChanged()) { new Client().Save(scan, "Updated from Data Entry Screen"); _documents.Refresh(); } } } } private void PopulateEditor() { if (_selectedType == null) return; _entity = null; if (_entityID != Guid.Empty) { _entity = Client.Create(_selectedType) .Query( Filter.Create(_selectedType, x => x.ID).IsEqualTo(_entityID), _grid.LoadEditorColumns() ) .ToObjects(_selectedType) .OfType() .FirstOrDefault(); } _entity ??= Activator.CreateInstance(_selectedType) as Entity; if (_entity == null) return; _grid?.InitialiseEditorForm(Editor, new object[] { _entity }, null, true); _process = new Button() { Content = "Mark as Processed", BorderBrush = new SolidColorBrush(Colors.DarkBlue), Background = new SolidColorBrush(Colors.DodgerBlue), Margin = new Thickness(0, 0, 5, 0), Padding = new Thickness(10, 0, 10, 0), IsEnabled = _processenabled }; _process.Click += (sender, args) => { if (Editor.Validate()) { DoSave(true); } }; Editor.AddButton(_process); IsChanged = false; if (_selectedType == typeof(JobDocumentSetMileStone)) { var disabled = _entityID == Guid.Empty; foreach (var page in Editor.Pages) { if (page is DynamicEditorGrid.DynamicEditPage editPage) { foreach (var editor in editPage.Editors) { if (editor.EditorDefinition is not BaseCodeEditor) { editor.IsEnabled = !disabled && editor.EditorDefinition.Editable.IsEditable(); } } } else { page.ReadOnly = disabled; } } } } private void _panel_OnOnChanged(object sender, DynamicSplitPanelSettings e) { _settings.PreviewWidth = e.AnchorWidth; new UserConfiguration().Save(_settings); } }