Files
raven/server/AyaNova/DataList/DataListProcessingBase.cs
2021-01-29 21:40:08 +00:00

263 lines
10 KiB
C#

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
{
/// <summary>
/// DataList object base class
/// </summary>
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<string>() { "XXX", "XXXX", "XXXX", "XXXX", "XXXX", "XXX", "XXXX", "XXXX", "XXXX", "XXXX" };
DefaultSortBy = new Dictionary<string, string>() { { "XXXX", "+" }, { "XXXX", "-" } };
*/
}
public string SQLFrom { get; set; }
public List<DataListFieldDefinition> FieldDefinitions { get; set; }
public AuthorizationRoles AllowedRoles { get; set; }
public AyaType DefaultListObjectType { get; set; }
public long CurrentUserId { get; set; }
public List<string> DefaultColumns { get; set; }
public Dictionary<string, string> 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<DataListFilterOption>();
if (listOptions.SortBy == null)
listOptions.SortBy = new Dictionary<string, string>();
//Check Columns
if (listOptions is DataListTableOptions)
{
var dlto = ((DataListTableOptions)listOptions);
if (dlto.Columns == null)
dlto.Columns = new List<string>();
//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<string> 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<string> ret = new List<string>();
// for (int i = 0; i < listViewArray.Count; i++)
// {
// var cm = listViewArray[i];
// ret.Add(cm["fld"].Value<string>());
// }
// return ret;
// }
public Newtonsoft.Json.Linq.JArray GenerateReturnListColumns(List<string> 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<string, int> 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<string, int> ret = new Dictionary<string, int>();
List<string> typesProcessed = new List<string>();
//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<string>(), t["type"].Value<int>());
}
}
}
}
}
}
/*{[
{
"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