using InABox.Clients; using InABox.Core; using InABox.Scripting; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; namespace InABox.Wpf.Dashboard; public interface IDynamicDashboardTable { string Key { get; set; } IEnumerable CoreColumns { get; } } public interface IDynamicDashboardDataQuery : IDynamicDashboardTable { Type Type { get; } IFilter? Filter { get; set; } IColumns Columns { get; set; } ISortOrder? SortOrder { get; set; } IEnumerable IDynamicDashboardTable.CoreColumns => Columns.Columns().Select(x => new CoreColumn { ColumnName = x.Name, DataType = x.Type }); } public class DynamicDashboardDataQuery : IDynamicDashboardDataQuery where T : Entity, IRemotable, new() { public string Key { get; set; } = typeof(T).Name; public Filter? Filter { get; set; } public Columns Columns { get; set; } = Core.Columns.None(); public SortOrder? SortOrder { get; set; } = null; #region IDynamicDashboardDataQuery Type IDynamicDashboardDataQuery.Type => typeof(T); IFilter? IDynamicDashboardDataQuery.Filter { get => Filter; set => Filter = value as Filter; } IColumns IDynamicDashboardDataQuery.Columns { get => Columns; set => Columns = (value as Columns) ?? Core.Columns.None(); } ISortOrder? IDynamicDashboardDataQuery.SortOrder { get => SortOrder; set => SortOrder = value as SortOrder; } #endregion } public class DynamicDashboardAdditionalTable : IDynamicDashboardTable { public string Key { get; set; } = ""; public List Columns { get; set; } = new(); private string? _script; public string? Script { get => _script; set { if(_script != value) { _script = value; _scriptDocument = null; } } } IEnumerable IDynamicDashboardTable.CoreColumns => Columns; private ScriptDocument? _scriptDocument; private ScriptDocument? ScriptDocument { get { if(_scriptDocument is null && Script is not null) { _scriptDocument = new(Script); _scriptDocument.Compile(); } return _scriptDocument; } } public static string DefaultScript() { return @"using InABox.Wpf.Dashboard; public class Module { public void PopulateTable(CoreTable table, DynamicDashboardData data) { // Populate 'table' using the data from 'data'. } }"; } public void PopulateTable(CoreTable table, DynamicDashboardData data) { if (ScriptDocument is null) return; ScriptDocument.Execute(methodname: "PopulateTable", parameters: [table, data]); } } public class DynamicDashboardDataComponent { public List Queries { get; set; } = new(); public List AdditionalTables { get; set; } = new(); public IEnumerable Tables => Queries.Concat(AdditionalTables); public IDynamicDashboardTable GetTable(string key) { return Tables.FirstOrDefault(x => x.Key == key) ?? throw new KeyNotFoundException($"Data table '{key}' does not exist."); } public bool TryGetTable(string key, [NotNullWhen(true)] out IDynamicDashboardTable? query) { query = Tables.FirstOrDefault(x => x.Key == key); return query != null; } private void PopulateAdditionalTables(DynamicDashboardData data) { foreach(var tableDef in AdditionalTables) { var table = new CoreTable(); table.Columns.AddRange(tableDef.Columns); tableDef.PopulateTable(table, data); data.Data.Add(tableDef.Key, table); } } /// /// Run the query to get the data according to the definitions of . /// /// Set to a non- value to limit the number of records returned. Used for preview mode. public DynamicDashboardData RunQuery(int? maxRecords = null) { var range = maxRecords.HasValue ? CoreRange.Database(maxRecords.Value) : null; var queryDefs = Queries.Select(x => new KeyedQueryDef(x.Key, x.Type, x.Filter, x.Columns, x.SortOrder, range)); var results = Client.QueryMultiple(queryDefs); var data = new DynamicDashboardData(results.Results); PopulateAdditionalTables(data); return data; } /// /// Run the query asynchronously to get the data according to the definitions of . /// /// Set to a non- value to limit the number of records returned. Used for preview mode. public async Task RunQueryAsync(int? maxRecords = null) { var range = maxRecords.HasValue ? CoreRange.Database(maxRecords.Value) : null; var queryDefs = Queries.Select(x => new KeyedQueryDef(x.Key, x.Type, x.Filter, x.Columns, x.SortOrder, range)); var results = await Client.QueryMultipleAsync(queryDefs); var data = new DynamicDashboardData(results.Results); PopulateAdditionalTables(data); return data; } } public class DynamicDashboardData(Dictionary data) { public Dictionary Data { get; set; } = data; public bool TryGetData(string key, [NotNullWhen(true)] out CoreTable? query) { return Data.TryGetValue(key, out query); } }