using System.Collections.Generic; using System.Linq; using System.Text; using AyaNova.Models; using AyaNova.Biz; using Newtonsoft.Json.Linq; using Microsoft.EntityFrameworkCore; namespace AyaNova.DataList { /// /// DataList object base class /// internal abstract class DataListProcessingBase : IDataListProcessing { //CoreBizObject add here //well, not here exactly but add a new DATALIST class if it will be displayed as a list anywhere in the UI or reported on public DataListProcessingBase() { /* DefaultColumns = new List() { "XXX", "XXXX", "XXXX", "XXXX", "XXXX", "XXX", "XXXX", "XXXX", "XXXX", "XXXX" }; DefaultSortBy = new Dictionary() { { "XXXX", "+" }, { "XXXX", "-" } }; */ } public string SQLFrom { get; set; } public List FieldDefinitions { get; set; } public AuthorizationRoles AllowedRoles { get; set; } public AyaType DefaultListObjectType { get; set; } public long CurrentUserId { get; set; } public List DefaultColumns { get; set; } public Dictionary DefaultSortBy { get; set; } //set defaults if not provided in listOptions public void ProcessRequest(Models.DataListProcessingBase listOptions) { //columns, filter and sortby could all be null if (listOptions.Filter == null) listOptions.Filter = new List(); if (listOptions.SortBy == null) listOptions.SortBy = new Dictionary(); //Check Columns if (listOptions is DataListTableOptions) { var dlto = ((DataListTableOptions)listOptions); if (dlto.Columns == null) dlto.Columns = new List(); //if this doesn't work then just ditch this method in favor of local code, it's not really saving much if (dlto.Columns.Count == 0) dlto.Columns = DefaultColumns; } //Check SortBy if (listOptions.SortBy.Count == 0) listOptions.SortBy = DefaultSortBy; //Check filter if (listOptions.Filter == null) { } } // //return array of field keys in list view // public List GetFieldListFromListView(JArray listViewArray) // { // // [{key:"COLUMN UNIQUE KEY ID",sort:"-" or "+",filter:{any:true/false,items:[{FILTER OBJECT SEE BELOW}]} }, {key:"second column unique key"},{...etc...}] // List ret = new List(); // for (int i = 0; i < listViewArray.Count; i++) // { // var cm = listViewArray[i]; // ret.Add(cm["fld"].Value()); // } // return ret; // } public Newtonsoft.Json.Linq.JArray GenerateReturnListColumns(List columns) { // var ListViewFieldKeys = GetFieldListFromListView(listViewArray); var CustomFieldDefinitions = GetCustomFieldDefinitionsForList(); //Generate JSON fragment to return with column definitions StringBuilder sb = new StringBuilder(); sb.Append("["); bool FirstColumnAdded = false; foreach (string s in columns) { DataListFieldDefinition o = FieldDefinitions.FirstOrDefault(z => z.FieldKey == s); #if (DEBUG) //Developers little helper if (o == null) { throw new System.ArgumentNullException($"DEV ERROR in AyaDataList::GenerateReturnListColumns - field {s} specified in columns was NOT found in ObjectFields list"); } #endif if (o != null) {//Here is where we can vet the field name, if it doesn't exist. For production we'll just ignore those ones if (FirstColumnAdded) sb.Append(","); sb.Append("{"); //Build required part of column definition if (!o.IsCustomField) sb.Append($"\"cm\":\"{o.TKey}\",\"dt\":{(int)o.UiFieldDataType}"); else { //insert specific type for this custom field if (CustomFieldDefinitions.ContainsKey(o.TKey)) { var customFieldType = CustomFieldDefinitions[o.TKey]; sb.Append($"\"cm\":\"{o.TKey}\",\"dt\":{customFieldType}"); } else { //this is normal as there may not be a definition for a Custom field but it's been requested so just treat it like text sb.Append($"\"cm\":\"{o.TKey}\",\"dt\":{(int)UiFieldDataType.Text}"); } } //Has a AyObjectType? (linkable / openable) if (o.AyaObjectType != 0) sb.Append($",\"ay\":{(int)o.AyaObjectType}"); //Row ID column? if (o.IsRowId) { sb.Append($",\"rid\":1"); } //Has a Enumtype? if (!string.IsNullOrEmpty(o.EnumType)) sb.Append($",\"et\":\"{AyaNova.Util.StringUtil.TrimTypeName(o.EnumType)}\""); sb.Append("}"); FirstColumnAdded = true; } } sb.Append("]"); return JArray.Parse(sb.ToString()); } //Find and return a dictionary of all custom fields definitions for all types in list //used to build the column array and define specific type defined for custom fields so client datatable //knows how to format it private Dictionary GetCustomFieldDefinitionsForList() { //all keys and types can go in the same list since they are unique to each type of list //i.e. both users and widget custom fields can be in the same list Dictionary ret = new Dictionary(); List typesProcessed = new List(); //custom fields handling foreach (DataListFieldDefinition d in this.FieldDefinitions) { if (d.IsCustomField) { //this relies on the convention I'm using of AyaType name as the first part of all custom fields lT keys, e.g. //WidgetCustom1 -> Widget var ayatypename = d.TKey.Split("Custom")[0]; if (!typesProcessed.Contains(ayatypename)) { //make sure we do each type only once typesProcessed.Add(ayatypename); //fetch it and set it using (var ct = AyaNova.Util.ServiceProviderProvider.DBContext) { var fc = ct.FormCustom.AsNoTracking().SingleOrDefault(z => z.FormKey == ayatypename); //This is normal and expected in an empty db, removing this block // #if (DEBUG) // if (fc == null) // { // throw new System.ArgumentNullException($"AyaDataList:GetCustomFieldDefinitionsForList, Custom field object type {ayatypename} has no FormCustom defined"); // } // #endif //production handling of missing formcustom if (fc == null) continue; //iterate the fields and add each custom one with a type to the return dictionary var flds = JArray.Parse(fc.Template); foreach (JToken t in flds) { if (t["type"] != null) { ret.Add(t["fld"].Value(), t["type"].Value()); } } } } } } /*{[ { "fld": "Notes", "required": true }, { "fld": "WidgetCustom1", "required": false, "type": 1 }, { "fld": "WidgetCustom2", "required": true, "type": 4 }, { "fld": "WidgetCustom3", "required": false, "type": 5 }, { "fld": "WidgetCustom4", "required": false, "type": 6 }, { "fld": "WidgetCustom5", "required": false, "type": 8 }, { "fld": "WidgetCustom6", "required": false, "type": 2 }, { "fld": "WidgetCustom7", "required": false, "type": 3 } ]}*/ return ret; } }//eoc }//eons