using Comal.Classes; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace PRSDesktop.Forms.Issues; public class IssuesGrid : DynamicGrid, ISpecificGrid { private readonly int ChunkSize = 500; private IClient _client; public Func ClientFactory { get; set; } private IClient Client { get { _client ??= (ClientFactory(typeof(Kanban)) as IClient)!; return _client; } } public Guid CustomerID { get; set; } public IssuesGrid() : base() { var cols = LookupFactory.DefineColumns(); // Minimum Columns for Lookup values foreach (var col in cols) HiddenColumns.Add(col); ActionColumns.Add(new DynamicMenuColumn(BuildMenu) { Position = DynamicActionColumnPosition.End }); } protected override void Init() { } protected override void DoReconfigure(DynamicGridOptions options) { options.Clear(); options.AddRows = true; options.EditRows = true; } private void BuildMenu(DynamicMenuColumn column, CoreRow? row) { if (row is null) return; var menu = column.GetMenu(); menu.AddItem("Add Note", null, row, AddNote_Click); menu.AddItem("Close Issue", null, row, CloseTask_Click); } public override Kanban CreateItem() { var item = base.CreateItem(); // item.UserProperties["CustomerID"] = CustomerID.ToString(); return item; } private void AddNote_Click(CoreRow row) { var kanban = row.ToObject(); } private void CloseTask_Click(CoreRow row) { } private Column[] AllowedColumns = [ new(x => x.Number), new(x => x.Title), new(x => x.Description), new(x => x.Notes), new(x => x.Type.ID)]; protected override void CustomiseEditor(Kanban[] items, DynamicGridColumn column, BaseEditor editor) { base.CustomiseEditor(items, column, editor); if(!AllowedColumns.Any(x => x.Property == column.ColumnName)) { editor.Editable = editor.Editable.Combine(Editable.Hidden); } } public virtual CoreTable LookupValues(DataLookupEditor editor, Type parent, string columnname, BaseObject[]? items) { var client = ClientFactory(editor.Type); var filter = LookupFactory.DefineLookupFilter(parent, editor.Type, columnname, items ?? (Array.CreateInstance(parent, 0) as BaseObject[])!); var columns = LookupFactory.DefineLookupColumns(parent, editor.Type, columnname); foreach (var key in editor.OtherColumns.Keys) columns.Add(key); var sort = LookupFactory.DefineSort(editor.Type); var result = client.Query(filter, columns, sort); result.Columns.Add(new CoreColumn { ColumnName = "Display", DataType = typeof(string) }); foreach (var row in result.Rows) { row["Display"] = LookupFactory.FormatLookup(parent, editor.Type, row, columnname); } return result; } protected override void DefineLookups(ILookupEditorControl sender, Kanban[] items, bool async = true) { if (sender.EditorDefinition is not DataLookupEditor editor) { base.DefineLookups(sender, items, async: async); return; } var colname = sender.ColumnName; if (async) { Task.Run(() => { try { var values = LookupValues(editor, typeof(Kanban), colname, items); Dispatcher.Invoke( () => { try { //Logger.Send(LogType.Information, typeof(T).Name, "Dispatching Results" + colname); sender.LoadLookups(values); } catch (Exception e2) { Logger.Send(LogType.Information, typeof(Kanban).Name, "Exception (2) in LoadLookups: " + e2.Message + "\n" + e2.StackTrace); } } ); } catch (Exception e) { Logger.Send(LogType.Information, typeof(Kanban).Name, "Exception (1) in LoadLookups: " + e.Message + "\n" + e.StackTrace); } }); } else { var values = LookupValues(editor, typeof(Kanban), colname, items); sender.LoadLookups(values); } } public override DynamicEditorPages LoadEditorPages(Kanban item) { var pages = new DynamicEditorPages { new DynamicDocumentGrid() }; return pages; } protected override DynamicGridColumns LoadColumns() { var columns = new DynamicGridColumns(); columns.Add(x => x.Number); columns.Add(x => x.Title); columns.Add(x => x.Type.Code); return columns; } #region Grid Stuff protected override string FormatRecordCount(int count) { return IsPaging ? $"{base.FormatRecordCount(count)} (loading..)" : base.FormatRecordCount(count); } protected override void Reload( Filters criteria, Columns columns, ref SortOrder? sort, CancellationToken token, Action action) { // criteria.Add(new Filter("CustomerID").IsEqualTo(CustomerID.ToString())); if(Options.PageSize > 0) { var inSort = sort; Task.Run(() => { var page = CoreRange.Database(Options.PageSize); var filter = criteria.Combine(); IsPaging = true; while (!token.IsCancellationRequested) { try { var data = Client.Query(filter, columns, inSort, page); data.Offset = page.Offset; IsPaging = data.Rows.Count == page.Limit; if (token.IsCancellationRequested) { break; } action(data, null); if (!IsPaging) break; // Proposal - Let's slow it down a bit to enhance UI responsiveness? Thread.Sleep(100); page.Next(); } catch (Exception e) { action(null, e); break; } } }, token); } else { Client.Query(criteria.Combine(), columns, sort, null, action); } } public override Kanban[] LoadItems(IList rows) { var results = new List(rows.Count); for (var i = 0; i < rows.Count; i += ChunkSize) { var chunk = rows.Skip(i).Take(ChunkSize); var filter = new Filter(x => x.ID).InList(chunk.Select(x => x.Get(x => x.ID)).ToArray()); var columns = DynamicGridUtils.LoadEditorColumns(Columns.None()); var data = Client.Query(filter, columns); results.AddRange(data.ToObjects()); } return results.ToArray(); } public override Kanban LoadItem(CoreRow row) { var id = row.Get(x => x.ID); return Client.Query( new Filter(x => x.ID).IsEqualTo(id), DynamicGridUtils.LoadEditorColumns(Columns.None())).ToObjects().FirstOrDefault() ?? throw new Exception($"No Kanban with ID {id}"); } public override void SaveItem(Kanban item) { Client.Save(item, "Edited by User"); } public override void SaveItems(IEnumerable items) { Client.Save(items, "Edited by User"); } public override void DeleteItems(params CoreRow[] rows) { var deletes = new List(); foreach (var row in rows) { var delete = new Kanban { ID = row.Get(x => x.ID) }; deletes.Add(delete); } Client.Delete(deletes, "Deleted on User Request"); } #endregion }