From 3ffc01f393c03eca79342981d5e57dca8fbc3cee Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Wed, 27 Jan 2021 00:59:36 +0000 Subject: [PATCH] Right in the middle of conversion, not compilable yet --- .../AyaNova/Controllers/DataListController.cs | 2 +- server/AyaNova/DataList/AttachmentDataList.cs | 2 + server/AyaNova/DataList/AyaDataList.cs | 18 ++- server/AyaNova/DataList/CustomerDataList.cs | 8 +- .../AyaNova/DataList/CustomerNoteDataList.cs | 10 +- .../CustomerServiceRequestDataList.cs | 1 + server/AyaNova/DataList/DataListFetcher.cs | 76 +++++----- server/AyaNova/DataList/DataListOptions.cs | 68 +++++++++ .../DataListSqlFilterCriteriaBuilder.cs | 133 ++++++++++-------- .../DataListSqlFilterOrderByBuilder.cs | 2 +- server/AyaNova/DataList/EventDataList.cs | 1 + server/AyaNova/DataList/HeadOfficeDataList.cs | 2 + server/AyaNova/DataList/IAyaDataList.cs | 9 +- .../DataList/IAyaDataListExtraCriteria.cs | 6 +- server/AyaNova/DataList/InsideUserDataList.cs | 1 + server/AyaNova/DataList/ListOptions.cs | 36 ----- server/AyaNova/DataList/LoanUnitDataList.cs | 2 + server/AyaNova/DataList/MemoDataList.cs | 11 +- .../AyaNova/DataList/OutsideUserDataList.cs | 1 + server/AyaNova/DataList/ReminderDataList.cs | 6 +- server/AyaNova/DataList/ReviewDataList.cs | 20 +-- server/AyaNova/DataList/TestWidgetDataList.cs | 2 + .../{PickListParams.cs => PickListOptions.cs} | 0 23 files changed, 250 insertions(+), 167 deletions(-) create mode 100644 server/AyaNova/DataList/DataListOptions.cs delete mode 100644 server/AyaNova/DataList/ListOptions.cs rename server/AyaNova/PickList/{PickListParams.cs => PickListOptions.cs} (100%) diff --git a/server/AyaNova/Controllers/DataListController.cs b/server/AyaNova/Controllers/DataListController.cs index bbb4a8c7..09b9db2d 100644 --- a/server/AyaNova/Controllers/DataListController.cs +++ b/server/AyaNova/Controllers/DataListController.cs @@ -74,7 +74,7 @@ namespace AyaNova.Api.Controllers try { - ApiDataListResponse r = await DataListFetcher.GetResponseAsync(listOptions.DataListKey, ct, listOptions, UserRoles, log, UserId); + ApiDataListResponse r = await DataListFetcher.GetResponseAsync(ct, listOptions, UserRoles, log, UserId); return Ok(r); } catch (System.UnauthorizedAccessException) diff --git a/server/AyaNova/DataList/AttachmentDataList.cs b/server/AyaNova/DataList/AttachmentDataList.cs index 437ddd7d..4541a87f 100644 --- a/server/AyaNova/DataList/AttachmentDataList.cs +++ b/server/AyaNova/DataList/AttachmentDataList.cs @@ -93,5 +93,7 @@ namespace AyaNova.DataList } + + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/DataList/AyaDataList.cs b/server/AyaNova/DataList/AyaDataList.cs index e6d2ec35..f016cdff 100644 --- a/server/AyaNova/DataList/AyaDataList.cs +++ b/server/AyaNova/DataList/AyaDataList.cs @@ -16,7 +16,7 @@ namespace AyaNova.DataList //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 AyaDataList() - { + { } @@ -25,9 +25,22 @@ namespace AyaNova.DataList public AuthorizationRoles AllowedRoles { get; set; } public AyaType DefaultListObjectType { get; set; } - public string DefaultListView { get; set; } + + public long CurrentUserId { get; set; } + public List DefaultColumns { get; set; } + public List DefaultSortBy { get; set; } + + //set defaults if not provided in listOptions + public void SetListOptionDefaultsIfNecessary(DataListOptions listOptions) + { + if (listOptions.Columns.Count == 0) + listOptions.Columns = DefaultColumns; + if (listOptions.SortBy.Count == 0) + listOptions.SortBy = DefaultSortBy; + } + //return array of field keys in list view public List GetFieldListFromListView(JArray listViewArray) @@ -215,7 +228,6 @@ namespace AyaNova.DataList } - }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/DataList/CustomerDataList.cs b/server/AyaNova/DataList/CustomerDataList.cs index e15ecd8c..5fc24e24 100644 --- a/server/AyaNova/DataList/CustomerDataList.cs +++ b/server/AyaNova/DataList/CustomerDataList.cs @@ -12,6 +12,7 @@ namespace AyaNova.DataList var RoleSet = BizRoles.GetRoleSet(DefaultListObjectType); AllowedRoles = RoleSet.ReadFullRecord | RoleSet.Change; + //######## DEFAULT VIEW WHEN NO VIEW CHOSEN ############ //Default ListView dynamic dlistView = new JArray(); @@ -29,11 +30,11 @@ namespace AyaNova.DataList cm.fld = "customeremail"; dlistView.Add(cm); - + cm = new JObject(); cm.fld = "customerheadoffice"; dlistView.Add(cm); - + DefaultListView = dlistView.ToString(Newtonsoft.Json.Formatting.None); @@ -308,5 +309,8 @@ namespace AyaNova.DataList FieldDefinitions.Add(new AyaDataListFieldDefinition { TKey = "CustomerCustom15", FieldKey = "customercustom15", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "acustomer.customfields" }); FieldDefinitions.Add(new AyaDataListFieldDefinition { TKey = "CustomerCustom16", FieldKey = "customercustom16", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "acustomer.customfields" }); } + + + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/DataList/CustomerNoteDataList.cs b/server/AyaNova/DataList/CustomerNoteDataList.cs index b5c8d95e..931a1705 100644 --- a/server/AyaNova/DataList/CustomerNoteDataList.cs +++ b/server/AyaNova/DataList/CustomerNoteDataList.cs @@ -1,9 +1,11 @@ using System.Collections.Generic; using Newtonsoft.Json.Linq; using AyaNova.Biz; +using AyaNova.Models; + namespace AyaNova.DataList { - internal class CustomerNoteDataList : AyaDataList + internal class CustomerNoteDataList : AyaDataList, IAyaDataListServerCriteria { public CustomerNoteDataList() { @@ -75,5 +77,11 @@ namespace AyaNova.DataList IsMeta = true }); } + + public string DataListServerCriteria(AyaNova.Models.AyContext ct, long currentUserId, DataListOptions dataListOptions) + { + throw new System.NotImplementedException(); + } + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/DataList/CustomerServiceRequestDataList.cs b/server/AyaNova/DataList/CustomerServiceRequestDataList.cs index dfbd3692..2d104a58 100644 --- a/server/AyaNova/DataList/CustomerServiceRequestDataList.cs +++ b/server/AyaNova/DataList/CustomerServiceRequestDataList.cs @@ -170,5 +170,6 @@ namespace AyaNova.DataList FieldDefinitions.Add(new AyaDataListFieldDefinition { TKey = "CustomerServiceRequestCustom15", FieldKey = "customerservicerequestcustom15", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "acustomerservicerequest.customfields" }); FieldDefinitions.Add(new AyaDataListFieldDefinition { TKey = "CustomerServiceRequestCustom16", FieldKey = "customerservicerequestcustom16", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "acustomerservicerequest.customfields" }); } + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/DataList/DataListFetcher.cs b/server/AyaNova/DataList/DataListFetcher.cs index 40452a99..c957f5ac 100644 --- a/server/AyaNova/DataList/DataListFetcher.cs +++ b/server/AyaNova/DataList/DataListFetcher.cs @@ -18,57 +18,45 @@ namespace AyaNova.DataList // Get the data list data requested // // - internal static async Task GetResponseAsync(string DataListKey, AyContext ct, DataListOptions listOptions, AuthorizationRoles UserRoles, ILogger log, long userId) + internal static async Task GetResponseAsync(AyContext ct, DataListOptions listOptions, AuthorizationRoles userRoles, ILogger log, long userId) { - var DataList = DataListFactory.GetAyaDataList(DataListKey); + var DataList = DataListFactory.GetAyaDataList(listOptions.DataListKey); //was the name not found as a list? if (DataList == null) - throw new System.ArgumentOutOfRangeException($"DataList \"{DataListKey}\" specified does not exist"); + throw new System.ArgumentOutOfRangeException($"DataList \"{listOptions.DataListKey}\" specified does not exist"); //check rights - if (!UserRoles.HasAnyFlags(DataList.AllowedRoles)) + if (!userRoles.HasAnyFlags(DataList.AllowedRoles)) throw new System.UnauthorizedAccessException("User roles insufficient for this datalist"); - //do we need to default the listView? - if (string.IsNullOrWhiteSpace(listOptions.ListView)) - listOptions.ListView = DataList.DefaultListView; - - //parse the list view(s) - //This one is for the return list to the Client for grid column display - var PublicListViewArray = JArray.Parse(listOptions.ListView); + DataList.SetListOptionDefaultsIfNecessary(listOptions); - - //this one is for internal use here to build the filter and sort etc - var InternalListViewArray = JArray.Parse(listOptions.ListView); - - //Hard coded extra criteria from server end - if (DataList is IAyaDataListViewServerCriteria) - { - var ServerCriteriaListView = JArray.Parse(((IAyaDataListViewServerCriteria)DataList).ListViewServerCriteria(await ct.User.AsNoTracking().FirstOrDefaultAsync(z => z.Id == userId), ct)); - foreach (JToken jt in ServerCriteriaListView) - InternalListViewArray.Add(jt); - } - - //Hard coded extra criteria from Client end - var MetaListViewArray = JArray.Parse(listOptions.MetaView ?? "[]"); - foreach (JToken jt in MetaListViewArray) - InternalListViewArray.Add(jt); + //STATIC filter options from server + List StaticServerFilterOptions = null; + if (DataList is IAyaDataListServerCriteria) + StaticServerFilterOptions = ((IAyaDataListServerCriteria)DataList).DataListServerCriteria(userId, userRoles, listOptions); //Get the public field key names in a list from the listview - List PublicListViewFieldList = DataList.GetFieldListFromListView(PublicListViewArray); + List PublicListViewFieldList = listOptions.Columns; - //Get the internal only field key names from the internal list view - List InternalListViewFieldList = DataList.GetFieldListFromListView(InternalListViewArray); + //Get the combination of all unique fields from both StaticServerFilterOptions and listOptions + //NOTE: this assumes no list options filter colums that don't exist in listoptions.columns + var AllUniqueFieldKeysRequiredForQuery = PublicListViewFieldList.Union(StaticServerFilterOptions.Select(z => z.Column).ToList()).ToList(); + //Add the internal filters into the listoptions existing filters + //NOTE: There is currently no overlap between internal filtered columns and filters coming from the client + foreach (DataListFilterOption dfo in StaticServerFilterOptions) + listOptions.Filter.Add(dfo); - //BUILD THE QUERY - //SELECT FRAGMENT COLUMNS FROM TEMPLATE - var SelectBuild = DataListSqlSelectBuilder.Build(DataList.FieldDefinitions, InternalListViewFieldList); + //BUILD THE QUERY + + //SELECT CLAUSE + var qSelect = DataListSqlSelectBuilder.Build(DataList.FieldDefinitions, AllUniqueFieldKeysRequiredForQuery); //FROM CLAUSE var qFrom = DataList.SQLFrom; @@ -77,11 +65,11 @@ namespace AyaNova.DataList var qOrderBy = string.Empty; //WHERE CLAUSE - FILTER - qWhere = DataListSqlFilterCriteriaBuilder.DataFilterToSQLCriteria(DataList.FieldDefinitions, InternalListViewArray); + qWhere = DataListSqlFilterCriteriaBuilder.DataFilterToSQLCriteria(DataList.FieldDefinitions, listOptions); //ORDER BY CLAUSE - SORT //BUILD ORDER BY - qOrderBy = DataListSqlFilterOrderByBuilder.DataFilterToSQLOrderBy(DataList.FieldDefinitions, InternalListViewArray); + qOrderBy = DataListSqlFilterOrderByBuilder.DataFilterToSQLOrderBy(DataList.FieldDefinitions, listOptions); //LIMIT AND OFFSET CLAUSE - PAGING listOptions.Offset = listOptions.Offset ?? DataListOptions.DefaultOffset; @@ -92,7 +80,7 @@ namespace AyaNova.DataList string qDataQuery = string.Empty; string qTotalRecordsQuery = string.Empty; - qDataQuery = $"{SelectBuild.Select} {qFrom} {qWhere} {qOrderBy} {qLimitOffset}".Replace(" ", " "); + qDataQuery = $"{qSelect.Select} {qFrom} {qWhere} {qOrderBy} {qLimitOffset}".Replace(" ", " "); qTotalRecordsQuery = $"SELECT COUNT(*) {qFrom} {qWhere}".Replace(" ", " "); //RETURN OBJECTS @@ -126,7 +114,7 @@ namespace AyaNova.DataList { AyaFieldData AyaField = new AyaFieldData(); - var cust = dr.GetString(SelectBuild.map[f.GetSqlValueColumnName()]); + var cust = dr.GetString(qSelect.map[f.GetSqlValueColumnName()]); if (!string.IsNullOrWhiteSpace(cust)) { JObject j = JObject.Parse(cust); @@ -165,7 +153,7 @@ namespace AyaNova.DataList else { AyaFieldData AyaField = new AyaFieldData(); - AyaField.v = dr.GetValue(SelectBuild.map[f.GetSqlValueColumnName()]); + AyaField.v = dr.GetValue(qSelect.map[f.GetSqlValueColumnName()]); if (f.IsRowId) { @@ -178,21 +166,21 @@ namespace AyaNova.DataList if (f.SqlIdColumnName != null) { - var ordinal = SelectBuild.map[f.SqlIdColumnName]; + var ordinal = qSelect.map[f.SqlIdColumnName]; if (!await dr.IsDBNullAsync(ordinal)) AyaField.i = dr.GetInt64(ordinal); } if (f.SqlAyTypeColumnName != null) { - var ordinal = SelectBuild.map[f.SqlAyTypeColumnName]; + var ordinal = qSelect.map[f.SqlAyTypeColumnName]; if (!await dr.IsDBNullAsync(ordinal)) AyaField.ot = dr.GetInt32(ordinal); } if (f.SqlColorColumnName != null) { - var ordinal = SelectBuild.map[f.SqlColorColumnName]; + var ordinal = qSelect.map[f.SqlColorColumnName]; if (!await dr.IsDBNullAsync(ordinal)) AyaField.clr = dr.GetString(ordinal); } @@ -242,7 +230,7 @@ namespace AyaNova.DataList //BUILD THE COLUMNS RETURN PROPERTY JSON FRAGMENT Newtonsoft.Json.Linq.JArray ColumnsJSON = null; - ColumnsJSON = DataList.GenerateListColumnsJSONFromListView(PublicListViewArray); + ColumnsJSON = DataList.GenerateListColumnsJSONFromListView(listOptions.Columns); return new ApiDataListResponse(rows, totalRecordCount, ColumnsJSON); @@ -275,9 +263,9 @@ namespace AyaNova.DataList //Hard coded extra criteria from server end - if (DataList is IAyaDataListViewServerCriteria) + if (DataList is IAyaDataListServerCriteria) { - var ServerCriteriaListView = JArray.Parse(((IAyaDataListViewServerCriteria)DataList).ListViewServerCriteria(await ct.User.AsNoTracking().FirstOrDefaultAsync(z => z.Id == userId), ct)); + var ServerCriteriaListView = JArray.Parse(((IAyaDataListServerCriteria)DataList).DataListServerCriteria(await ct.User.AsNoTracking().FirstOrDefaultAsync(z => z.Id == userId), ct)); foreach (JToken jt in ServerCriteriaListView) ListViewArray.Add(jt); } diff --git a/server/AyaNova/DataList/DataListOptions.cs b/server/AyaNova/DataList/DataListOptions.cs new file mode 100644 index 00000000..70fe5a10 --- /dev/null +++ b/server/AyaNova/DataList/DataListOptions.cs @@ -0,0 +1,68 @@ +using System.ComponentModel.DataAnnotations; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; + +namespace AyaNova.DataList +{ + + public sealed class DataListOptions + { + public const int MaxPageSize = 1000; + public const int DefaultOffset = 0; + public const int DefaultLimit = 25; + + [FromBody] + public int? Offset { get; set; } + + [FromBody] + public int? Limit { get; set; } + + [FromBody, Required] + public string DataListKey { get; set; } + + /* + OLD EXAMPLE: + {"offset":0,"limit":10,"dataListKey":"CustomerDataList", + "listView":"[ + {\"fld\":\"customername\",\"sort\":\"+\",\"filter\":{\"items\":[{\"op\":\"=\",\"value\":\"dfdfdf\"},{\"op\":\"=\",\"value\":\"3333\"}],\"any\":true}}, + {\"fld\":\"customerphone1\",\"filter\":{\"items\":[{\"op\":\">\",\"value\":\"44444\"}, + {\"op\":\"<\",\"value\":\"7777\"}]}}, + {\"fld\":\"customeremail\"} + {\"fld\":\"customerheadoffice\"}, + {\"fld\":\"customertags\",\"sort\":\"+\"}]"} + + NEW: + columns:["PartInventoryTransactionEntryDate","PartPartNumber","PartWarehouseName","PartInventoryTransactionQuantity","PartInventoryTransactionDescription","PartInventoryTransactionSource","PartInventoryBalance"] + sortBy:[{"PartInventoryTransactionEntryDate":"-"}],//All sorted columns here as keyvalue pairs value is a string of "+" for ascending "-" for descending + filter:[{column:"PartPartNumber",any:true/false,items:[{op: "=",value: "400735"}]}], + clientCriteria:"2" //could be anything here that makes sense to the list, in this case an example customer id for customernotedatalist + */ + [FromBody] + public List Columns { get; set; } + [FromBody] + public Dictionary SortBy { get; set; } + [FromBody] + public List Filter { get; set; } + [FromBody] + public string ClientCriteria { get; set; } + } + + + public class DataListFilterOption + { + public string Column { get; set; } + public List items { get; set; } + public bool Any {get;set;}//means "or" the filter conditions + DataListFilterOption() + { + items = new List(); + } + } + + public class DataListColumnFilter + { + public string op { get; set; } + public string value { get; set; } + } + +} \ No newline at end of file diff --git a/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs b/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs index dc65c782..68fc7047 100644 --- a/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs +++ b/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs @@ -10,10 +10,10 @@ namespace AyaNova.DataList { public static class DataListSqlFilterCriteriaBuilder { - public static string DataFilterToSQLCriteria(List objectFieldsList, JArray listViewArray) + public static string DataFilterToSQLCriteria(List objectFieldsList, DataListOptions listOptions) { - if (listViewArray == null || listViewArray.Count == 0) + if (listOptions.Filter == null || listOptions.Filter.Count == 0) { return ""; } @@ -21,23 +21,25 @@ namespace AyaNova.DataList //List to compile each columns where clause fragment for later assembly into sql query List ColumnWhereClauses = new List(); - for (int i = 0; i < listViewArray.Count; i++) + // for (int i = 0; i < listViewArray.Count; i++) + + foreach (DataListFilterOption f in listOptions.Filter) { StringBuilder sb = new StringBuilder(); - var cm = listViewArray[i]; - //skip it if FILTER is not defined - if (cm["filter"] == null) - { - continue; - } + // var cm = listViewArray[i]; + // //skip it if FILTER is not defined + // if (cm["filter"] == null) + // { + // continue; + // } //Get some info about this column / field - var fld = cm["fld"].Value(); + // var fld = cm["fld"].Value(); //var dataType = objectFieldsList.Find(z => z.FieldKey.ToLowerInvariant() == fld.ToLowerInvariant()).UiFieldDataType; - AyaDataListFieldDefinition DataListField = objectFieldsList.FirstOrDefault(z => z.FieldKey == fld); + AyaDataListFieldDefinition DataListField = objectFieldsList.FirstOrDefault(z => z.FieldKey == f.Column); var dataType = DataListField.UiFieldDataType; @@ -50,26 +52,29 @@ namespace AyaNova.DataList //Developers little helper if (DataListField == null) { - throw new System.ArgumentNullException($"DEV ERROR in DataListSqlFilterCriteriaBuilder.cs: field {fld} specified in template was NOT found in ObjectFields list"); + throw new System.ArgumentNullException($"DEV ERROR in DataListSqlFilterCriteriaBuilder.cs: field {f.Column} specified in template was NOT found in ObjectFields list"); } #endif //get filter items collection for this field view definition - var filterItems = (JArray)cm["filter"]["items"]; + // var filterItems = (JArray)cm["filter"]["items"]; + + // var IsOrFilter = false; + // if (cm["filter"]["any"] != null) + // { + // IsOrFilter = cm["filter"]["any"].Value(); + // } - var IsOrFilter = false; - if (cm["filter"]["any"] != null) - { - IsOrFilter = cm["filter"]["any"].Value(); - } //Iterate filter items building this WHERE segment bool ThisIsTheFirstFilterItemForThisColumn = true; - var ThereAreMultipleFilterItems = filterItems.Count > 1; + //var ThereAreMultipleFilterItems = filterItems.Count > 1; + var ThereAreMultipleFilterItems = f.items.Count > 1; - for (int y = 0; y < filterItems.Count; y++) + // for (int y = 0; y < filterItems.Count; y++) + foreach (DataListColumnFilter filterItem in f.items) { //close or open another parenthetic group @@ -84,7 +89,8 @@ namespace AyaNova.DataList if (!ThisIsTheFirstFilterItemForThisColumn) { //Close last filter item and start new one - if (IsOrFilter) + // if (IsOrFilter) + if (f.Any) sb.Append(") OR ("); else sb.Append(") AND ("); @@ -93,39 +99,47 @@ namespace AyaNova.DataList //gather filter data - var filterItem = (JObject)filterItems[y]; - var opType = filterItem["op"].Value(); - List tagList = new List(); - string val = string.Empty; - bool IsPossibleIdValue = filterItem["value"].Type == JTokenType.Integer; - if (filterItem["value"].Type != JTokenType.Array) - val = filterItem["value"].Value(); - else - { - tagList = filterItem["value"].ToObject>(); - } - //prep for possible ID field filter instead + //var filterItem = (JObject)filterItems[y]; + // var opType = filterItem["op"].Value(); + + //#### Commented out this block as much of it is related to filter by ID as it says it's not used and I think that's true still when switched to new listOptions with split filter / view + // List tagList = new List(); + // string val = string.Empty; + // bool IsPossibleIdValue = filterItem["value"].Type == JTokenType.Integer; + // if (filterItem["value"].Type != JTokenType.Array) + // val = filterItem["value"].Value(); + // else + // { + // tagList = filterItem["value"].ToObject>(); + // } + // //prep for possible ID field filter instead + // string columnNameToFilter = string.Empty; + // UiFieldDataType DataTypeToFilter = UiFieldDataType.NoType; + // //Check if filtering by ID rather than by name + // //this is indicated by this column being an id type + // //and by the comparison operator being eq or neq + // //and the value being a number not a string + // //NOTE: This is not actually used anywhere at the client or on server, only defined here in this class + // //it was probabaly for supporting filtering by ID but I have found that unnecessary so far + // // if (DataListField.HasIdColumn() && IsPossibleIdValue && (opType == DataListFilterComparisonOperator.Equality || opType == DataListFilterComparisonOperator.NotEqual)) + // if (DataListField.HasIdColumn() && IsPossibleIdValue && (filterItem.op == DataListFilterComparisonOperator.Equality || filterItem.op == DataListFilterComparisonOperator.NotEqual)) + // { + // columnNameToFilter = DataListField.SqlIdColumnName; + // DataTypeToFilter = UiFieldDataType.InternalId; + // } + // else + // { + // DataTypeToFilter = (UiFieldDataType)dataType; + // columnNameToFilter = DataListField.GetSqlValueColumnName(); + // } + + //replaced above with simplified block here string columnNameToFilter = string.Empty; UiFieldDataType DataTypeToFilter = UiFieldDataType.NoType; - //Check if filtering by ID rather than by name - //this is indicated by this column being an id type - //and by the comparison operator being eq or neq - //and the value being a number not a string - //NOTE: This is not actually used anywhere at the client or on server, only defined here in this class - //it was probabaly for supporting filtering by ID but I have found that unnecessary so far - if (DataListField.HasIdColumn() && IsPossibleIdValue && (opType == DataListFilterComparisonOperator.Equality || opType == DataListFilterComparisonOperator.NotEqual)) - { - columnNameToFilter = DataListField.SqlIdColumnName; - DataTypeToFilter = UiFieldDataType.InternalId; - } - else - { - DataTypeToFilter = (UiFieldDataType)dataType; - columnNameToFilter = DataListField.GetSqlValueColumnName(); - } - + DataTypeToFilter = (UiFieldDataType)dataType; + columnNameToFilter = DataListField.GetSqlValueColumnName(); //Append this filter's criteria - sb.Append(DataFilterToColumnCriteria(columnNameToFilter, DataTypeToFilter, opType, val, tagList)); + sb.Append(DataFilterToColumnCriteria(columnNameToFilter, DataTypeToFilter, filterItem.op, filterItem.value)); ThisIsTheFirstFilterItemForThisColumn = false; @@ -160,12 +174,17 @@ namespace AyaNova.DataList } } + + //sTags is redundant now as the sValue can contain a array of strings and dataType already gives away if it's a tag filter or no + // private static string DataFilterToColumnCriteria(string SqlColumnNameToFilter, UiFieldDataType DataType, string sOperator, string sValue, List sTags)//, bool IsCompound) /// /// Translate DataFilter to Postgres friendly SQL criteria /// - private static string DataFilterToColumnCriteria(string SqlColumnNameToFilter, UiFieldDataType DataType, string sOperator, string sValue, List sTags)//, bool IsCompound) + private static string DataFilterToColumnCriteria(string SqlColumnNameToFilter, UiFieldDataType DataType, string sOperator, string sValue) { - bool TagFilter = sTags.Count < 0; + + // bool TagFilter = sTags.Count < 0; Nope, the datatype already states if it's tags or not no need for redundancy + StringBuilder sb = new StringBuilder(); //Column name //sb.Append(" "); @@ -173,7 +192,7 @@ namespace AyaNova.DataList sb.Append(" "); //handle null values separately - if (!TagFilter && sValue == "*NULL*") + if (DataType != UiFieldDataType.Tags && sValue == "*NULL*") { switch (DataType) { @@ -212,7 +231,7 @@ namespace AyaNova.DataList //so.... //Special addition to handle nulls - if (!TagFilter) + if (DataType != UiFieldDataType.Tags) { switch (sOperator) { @@ -562,7 +581,9 @@ namespace AyaNova.DataList //sounds like it might fuck up when using other languages so... StringBuilder sbTags = new StringBuilder(); sbTags.Append("@> array["); - List normalizedTags = TagBiz.NormalizeTags(sTags); + //List normalizedTags = TagBiz.NormalizeTags(sTags); + //Note: with listOptions change to split filter and view the tags are now in sValue as a string of comma delimited strings so split them out here + List normalizedTags = TagBiz.NormalizeTags(sValue.Split(',').ToList()); foreach (string s in normalizedTags) { diff --git a/server/AyaNova/DataList/DataListSqlFilterOrderByBuilder.cs b/server/AyaNova/DataList/DataListSqlFilterOrderByBuilder.cs index 0c2e097e..f20f0deb 100644 --- a/server/AyaNova/DataList/DataListSqlFilterOrderByBuilder.cs +++ b/server/AyaNova/DataList/DataListSqlFilterOrderByBuilder.cs @@ -9,7 +9,7 @@ namespace AyaNova.DataList { - public static string DataFilterToSQLOrderBy(List objectFieldsList, JArray listViewArray) + public static string DataFilterToSQLOrderBy(List objectFieldsList, DataListOptions listOptions) { StringBuilder sb = new StringBuilder(); diff --git a/server/AyaNova/DataList/EventDataList.cs b/server/AyaNova/DataList/EventDataList.cs index cd8c1428..5dcd0ced 100644 --- a/server/AyaNova/DataList/EventDataList.cs +++ b/server/AyaNova/DataList/EventDataList.cs @@ -109,5 +109,6 @@ namespace AyaNova.DataList } + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/DataList/HeadOfficeDataList.cs b/server/AyaNova/DataList/HeadOfficeDataList.cs index f2a1f155..bd68b64a 100644 --- a/server/AyaNova/DataList/HeadOfficeDataList.cs +++ b/server/AyaNova/DataList/HeadOfficeDataList.cs @@ -269,5 +269,7 @@ namespace AyaNova.DataList FieldDefinitions.Add(new AyaDataListFieldDefinition { TKey = "HeadOfficeCustom15", FieldKey = "headofficecustom15", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "aheadoffice.customfields" }); FieldDefinitions.Add(new AyaDataListFieldDefinition { TKey = "HeadOfficeCustom16", FieldKey = "headofficecustom16", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "aheadoffice.customfields" }); } + + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/DataList/IAyaDataList.cs b/server/AyaNova/DataList/IAyaDataList.cs index ba8d49d8..acd6dd71 100644 --- a/server/AyaNova/DataList/IAyaDataList.cs +++ b/server/AyaNova/DataList/IAyaDataList.cs @@ -18,13 +18,18 @@ namespace AyaNova.DataList //Default object type to open for rows of this list (use no object if no) AyaType DefaultListObjectType { get; set; } - //Default / STOCK DataListView when none is specified - string DefaultListView { get; set; } + //Defaults when none is specified (see DataListOptions for formats and notes) + List DefaultColumns { get; set; } + List DefaultSortBy { get; set; } + + void SetListOptionDefaultsIfNecessary(DataListOptions listOptions); Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromListView(JArray listViewArray); List GetFieldListFromListView(JArray listViewArray); + + } } \ No newline at end of file diff --git a/server/AyaNova/DataList/IAyaDataListExtraCriteria.cs b/server/AyaNova/DataList/IAyaDataListExtraCriteria.cs index 420786ab..d91c4d0a 100644 --- a/server/AyaNova/DataList/IAyaDataListExtraCriteria.cs +++ b/server/AyaNova/DataList/IAyaDataListExtraCriteria.cs @@ -1,9 +1,11 @@ namespace AyaNova.DataList { - internal interface IAyaDataListViewServerCriteria + internal interface IAyaDataListServerCriteria { //Additional criteria for security or other reasons //hard coded into some lists (e.g. MemoDataList so users can't get other people's memos) - string ListViewServerCriteria(AyaNova.Models.User user, AyaNova.Models.AyContext ct); + //User is just to look up for roles and stuff + //clientCriteria is additional criteria provided by client to list to process as it sees fit (e.g. CustomerNoteDataList requires customer id from client) + System.Collections.Generic.List DataListServerCriteria(long currentUserId, AyaNova.Biz.AuthorizationRoles userRoles, DataListOptions dataListOptions); } } \ No newline at end of file diff --git a/server/AyaNova/DataList/InsideUserDataList.cs b/server/AyaNova/DataList/InsideUserDataList.cs index 46ae2a8a..d4862d59 100644 --- a/server/AyaNova/DataList/InsideUserDataList.cs +++ b/server/AyaNova/DataList/InsideUserDataList.cs @@ -124,5 +124,6 @@ namespace AyaNova.DataList } + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/DataList/ListOptions.cs b/server/AyaNova/DataList/ListOptions.cs deleted file mode 100644 index 861f8f1d..00000000 --- a/server/AyaNova/DataList/ListOptions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Microsoft.AspNetCore.Mvc; - -namespace AyaNova.DataList -{ - - public sealed class DataListOptions - { - public const int MaxPageSize = 1000; - public const int DefaultOffset = 0; - public const int DefaultLimit = 25; - - [FromBody] - public int? Offset { get; set; } - - [FromBody] - public int? Limit { get; set; } - - [FromBody, Required] - public string DataListKey { get; set; } - -/* -columns:["PartInventoryTransactionEntryDate","PartPartNumber","PartWarehouseName","PartInventoryTransactionQuantity","PartInventoryTransactionDescription","PartInventoryTransactionSource","PartInventoryBalance"] -sortBy:["PartInventoryTransactionEntryDate"],//same as grid natively does all columns here -sortDesc:[true],//same as grid natively does, all columns here true or false each -filter:[{column:"PartPartNumber",items:[{op: "=",value: "400735"}]}], -variant:"string" -*/ - [FromBody] - public string ListView { get; set; }//optional, if null or empty will use default list view built into DataList - - [FromBody] - public string MetaView { get; set; }//optional meta list view to integrate into the standard list view. Used by client to add "meta" filter conditions above the user's choices e.g. customer notes customer id - } - -} \ No newline at end of file diff --git a/server/AyaNova/DataList/LoanUnitDataList.cs b/server/AyaNova/DataList/LoanUnitDataList.cs index 2f8a4f2d..8049880f 100644 --- a/server/AyaNova/DataList/LoanUnitDataList.cs +++ b/server/AyaNova/DataList/LoanUnitDataList.cs @@ -181,5 +181,7 @@ namespace AyaNova.DataList FieldDefinitions.Add(new AyaDataListFieldDefinition { TKey = "LoanUnitCustom15", FieldKey = "loanunitcustom15", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "aloanunit.customfields" }); FieldDefinitions.Add(new AyaDataListFieldDefinition { TKey = "LoanUnitCustom16", FieldKey = "loanunitcustom16", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "aloanunit.customfields" }); } + + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/DataList/MemoDataList.cs b/server/AyaNova/DataList/MemoDataList.cs index 255a4fa7..0eff8630 100644 --- a/server/AyaNova/DataList/MemoDataList.cs +++ b/server/AyaNova/DataList/MemoDataList.cs @@ -4,7 +4,7 @@ using AyaNova.Models; using AyaNova.Biz; namespace AyaNova.DataList { - internal class MemoDataList : AyaDataList, IAyaDataListViewServerCriteria + internal class MemoDataList : AyaDataList, IAyaDataListServerCriteria { public MemoDataList() { @@ -135,12 +135,9 @@ namespace AyaNova.DataList - - - - string IAyaDataListViewServerCriteria.ListViewServerCriteria(User user, AyaNova.Models.AyContext ct) - { - return "[{\"fld\":\"metamemoto\",\"filter\":{\"items\":[{\"op\":\"=\",\"value\":" + user.Id.ToString() + "}]}}]"; + string IAyaDataListServerCriteria.DataListServerCriteria(AyaNova.Models.AyContext ct, long currentUserId, DataListOptions dataListOptions) + { + return "[{\"fld\":\"metamemoto\",\"filter\":{\"items\":[{\"op\":\"=\",\"value\":" + currentUserId.ToString() + "}]}}]"; } }//eoc diff --git a/server/AyaNova/DataList/OutsideUserDataList.cs b/server/AyaNova/DataList/OutsideUserDataList.cs index 7c8b1117..3094c291 100644 --- a/server/AyaNova/DataList/OutsideUserDataList.cs +++ b/server/AyaNova/DataList/OutsideUserDataList.cs @@ -129,5 +129,6 @@ namespace AyaNova.DataList } + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/DataList/ReminderDataList.cs b/server/AyaNova/DataList/ReminderDataList.cs index d1eb3c50..af7d2db2 100644 --- a/server/AyaNova/DataList/ReminderDataList.cs +++ b/server/AyaNova/DataList/ReminderDataList.cs @@ -4,7 +4,7 @@ using AyaNova.Models; using AyaNova.Biz; namespace AyaNova.DataList { - internal class ReminderDataList : AyaDataList, IAyaDataListViewServerCriteria + internal class ReminderDataList : AyaDataList, IAyaDataListServerCriteria { public ReminderDataList() { @@ -114,9 +114,9 @@ namespace AyaNova.DataList } //Ensure only current user can fetch their reminders - string IAyaDataListViewServerCriteria.ListViewServerCriteria(User user, AyContext ct) + string IAyaDataListServerCriteria.DataListServerCriteria(AyaNova.Models.AyContext ct, long currentUserId, DataListOptions dataListOptions) { - return "[{\"fld\":\"metareminderuser\",\"filter\":{\"items\":[{\"op\":\"=\",\"value\":" + user.Id.ToString() + "}]}}]"; + return "[{\"fld\":\"metareminderuser\",\"filter\":{\"items\":[{\"op\":\"=\",\"value\":" + currentUserId.ToString() + "}]}}]"; } }//eoc diff --git a/server/AyaNova/DataList/ReviewDataList.cs b/server/AyaNova/DataList/ReviewDataList.cs index e9e41557..05a1dcce 100644 --- a/server/AyaNova/DataList/ReviewDataList.cs +++ b/server/AyaNova/DataList/ReviewDataList.cs @@ -1,10 +1,12 @@ using System.Collections.Generic; using Newtonsoft.Json.Linq; using AyaNova.Models; +using Microsoft.EntityFrameworkCore; +using System.Linq; using AyaNova.Biz; namespace AyaNova.DataList { - internal class ReviewDataList : AyaDataList, IAyaDataListViewServerCriteria + internal class ReviewDataList : AyaDataList, IAyaDataListServerCriteria { public ReviewDataList() { @@ -187,17 +189,17 @@ namespace AyaNova.DataList - string IAyaDataListViewServerCriteria.ListViewServerCriteria(User user, AyaNova.Models.AyContext ct) + string IAyaDataListServerCriteria.DataListServerCriteria(long currentUserId, AyaNova.Biz.AuthorizationRoles userRoles, DataListOptions dataListOptions) { - var CurrentUserRoles = user.Roles; + bool HasSupervisorRole = - CurrentUserRoles.HasFlag(AuthorizationRoles.BizAdminFull) || - CurrentUserRoles.HasFlag(AuthorizationRoles.DispatchFull) || - CurrentUserRoles.HasFlag(AuthorizationRoles.InventoryFull) || - CurrentUserRoles.HasFlag(AuthorizationRoles.SalesFull) || - CurrentUserRoles.HasFlag(AuthorizationRoles.AccountingFull); + userRoles.HasFlag(AuthorizationRoles.BizAdminFull) || + userRoles.HasFlag(AuthorizationRoles.DispatchFull) || + userRoles.HasFlag(AuthorizationRoles.InventoryFull) || + userRoles.HasFlag(AuthorizationRoles.SalesFull) || + userRoles.HasFlag(AuthorizationRoles.AccountingFull); if (!HasSupervisorRole) - return "[{\"fld\":\"metareviewuser\",\"filter\":{\"items\":[{\"op\":\"=\",\"value\":" + user.Id.ToString() + "}]}}]"; + return "[{\"fld\":\"metareviewuser\",\"filter\":{\"items\":[{\"op\":\"=\",\"value\":" + currentUserId.ToString() + "}]}}]"; return "[]";//this means effectively don't process this at all } diff --git a/server/AyaNova/DataList/TestWidgetDataList.cs b/server/AyaNova/DataList/TestWidgetDataList.cs index 97f8ae8c..84978f94 100644 --- a/server/AyaNova/DataList/TestWidgetDataList.cs +++ b/server/AyaNova/DataList/TestWidgetDataList.cs @@ -45,6 +45,8 @@ namespace AyaNova.DataList DefaultListView = dlistView.ToString(Newtonsoft.Json.Formatting.None); + DefaultColumns="" + // DefaultDataListView = @" diff --git a/server/AyaNova/PickList/PickListParams.cs b/server/AyaNova/PickList/PickListOptions.cs similarity index 100% rename from server/AyaNova/PickList/PickListParams.cs rename to server/AyaNova/PickList/PickListOptions.cs