diff --git a/devdocs/specs/core-list-graph-datatable-filtering-sorting-paging.txt b/devdocs/specs/core-list-graph-datatable-filtering-sorting-paging.txt index 8e553973..02b2b9e3 100644 --- a/devdocs/specs/core-list-graph-datatable-filtering-sorting-paging.txt +++ b/devdocs/specs/core-list-graph-datatable-filtering-sorting-paging.txt @@ -62,7 +62,7 @@ NOTES ABOUT WHY I DID THE FILTEROPTIONS LIKE I DID: SORTING =-=-=-=- - Sorting is done same as filtering but property on datafilter is called Sort and it's also a json Array Fields are: "fld" which is the same column name as in a datafilter and "dir" for direction which will contain a single character either a "-" or a "+" for descending and ascending respectively +If no Sort is defined the default will be by ID number descending meaning the most recent records in that table will be first diff --git a/server/AyaNova/biz/DataFilterBiz.cs b/server/AyaNova/biz/DataFilterBiz.cs index c0ed44c8..f43f067a 100644 --- a/server/AyaNova/biz/DataFilterBiz.cs +++ b/server/AyaNova/biz/DataFilterBiz.cs @@ -317,8 +317,6 @@ namespace AyaNova.Biz } - - //VALIDATE SORT //Filter json must parse if (!string.IsNullOrWhiteSpace(inObj.Sort)) @@ -330,12 +328,12 @@ namespace AyaNova.Biz { var sortItem = v[i]; if (sortItem["fld"] == null) - AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, object is missing required \"fld\" property "); + AddError(ValidationErrorType.RequiredPropertyEmpty, "Sort", $"Sort array item {i}, object is missing required \"fld\" property "); else { var fld = sortItem["fld"].Value(); if (string.IsNullOrWhiteSpace(fld)) - AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, \"fld\" property is empty and required"); + AddError(ValidationErrorType.RequiredPropertyEmpty, "Sort", $"Sort array item {i}, \"fld\" property is empty and required"); //validate the field name if we can if (ListValidFilterOptions != null) @@ -343,32 +341,19 @@ namespace AyaNova.Biz if (!ListValidFilterOptions.Flds.Exists(x => x.Fld == fld)) { - AddError(ValidationErrorType.InvalidValue, "Filter", $"Filter array item {i}, fld property value \"{fld}\" is not a valid value for ListKey specified"); + AddError(ValidationErrorType.InvalidValue, "Sort", $"Sort array item {i}, fld property value \"{fld}\" is not a valid value for ListKey specified"); } } } - if (sortItem["op"] == null) - AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, object is missing required \"op\" property "); + if (sortItem["dir"] == null) + AddError(ValidationErrorType.RequiredPropertyEmpty, "Sort", $"Sort array item {i}, object is missing required \"dir\" sort direction property "); else { - var opType = sortItem["op"].Value(); - if (!FilterComparisonOperator.Operators.Contains(opType)) - AddError(ValidationErrorType.InvalidValue, "Filter", $"Filter array item {i}, \"op\" property value of \"{opType}\" is not a valid FilterComparisonOperator type"); + var sortDir = sortItem["dir"].Value(); + if (sortDir != "+" && sortDir != "-") + AddError(ValidationErrorType.InvalidValue, "Sort", $"Sort array item {i}, \"dir\" property value of \"{sortDir}\" is not a valid sort direction value, must be \"+\" or \"-\" only"); } - - if (sortItem["value"] == null) - AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, object is missing or is empty the required \"value\" property "); - else - { - if (sortItem["value"].Type == JTokenType.String && string.IsNullOrWhiteSpace(sortItem["value"].Value())) - AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, object is missing or is empty the required \"value\" property "); - - if (sortItem["value"].Type == JTokenType.Array && sortItem["value"].Count() == 0) - AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, object is missing or is empty the required \"value\" property ARRAY "); - } - - //NOTE: value of nothing, null or empty is a valid value so no checking for it here } } diff --git a/server/AyaNova/biz/FilterSqlOrderByBuilder.cs b/server/AyaNova/biz/FilterSqlOrderByBuilder.cs new file mode 100644 index 00000000..08ee9de0 --- /dev/null +++ b/server/AyaNova/biz/FilterSqlOrderByBuilder.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using System; +using System.Globalization; +using System.Text; +using Newtonsoft.Json.Linq; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace AyaNova.Biz +{ + public static class FilterSqlOrderByBuilder + { + + public static string DefaultOrderBy(){ + return " ORDER BY ID DESC"; + } + + public static string DataFilterToSQLOrderBy(AyaNova.Models.DataFilter dataFilter) + { + + if (string.IsNullOrWhiteSpace(dataFilter.Sort)) + { + return ""; + } + + StringBuilder sb = new StringBuilder(); + + //iterate the datafilter and concatenate a sql query from it + var SortArray = JArray.Parse(dataFilter.Filter); + for (int i = 0; i < SortArray.Count; i++) + { + + var SortItem = SortArray[i]; + var fld = SortItem["fld"].Value(); + var opType = SortItem["op"].Value(); + List tagList = new List(); + string val = string.Empty; + if (SortItem["value"].Type != JTokenType.Array) + val = SortItem["value"].Value(); + else + { + tagList = SortItem["value"].ToObject>(); + } + + + sb.Append("("); + + if (i < SortArray.Count - 1) + { + sb.Append(") AND "); + } + } + + return " ORDER BY " + sb.ToString() + ")"; + } + + + + }//eoc +}//ens diff --git a/server/AyaNova/biz/WidgetBiz.cs b/server/AyaNova/biz/WidgetBiz.cs index 3bdf1164..0f0a0a72 100644 --- a/server/AyaNova/biz/WidgetBiz.cs +++ b/server/AyaNova/biz/WidgetBiz.cs @@ -180,7 +180,7 @@ namespace AyaNova.Biz //base query var q = "SELECT *, xmin FROM AWIDGET "; - //GET THE FILTER + //GET THE FILTER / SORT if (pagingOptions.DataFilterId > 0) { var TheFilter = await ct.DataFilter.FirstOrDefaultAsync(x => x.Id == pagingOptions.DataFilterId); @@ -188,6 +188,9 @@ namespace AyaNova.Biz //BUILD WHERE AND APPEND IT q = q + FilterSqlCriteriaBuilder.DataFilterToSQLCriteria(TheFilter, WidgetBiz.FilterOptions(), UserId); + //BUILD ORDER BY AND APPEND IT + q = q + FilterSqlCriteriaBuilder.DataFilterToSQLCriteria(TheFilter, WidgetBiz.FilterOptions(), UserId); + //TESTING: // //TODO: remove this from production build // //LOG THE CRIT AND QUERY @@ -196,14 +199,15 @@ namespace AyaNova.Biz // log.LogInformation(TheFilter.Filter); // log.LogInformation("Generated SQL:"); // log.LogInformation(q); + }else{ + //GET DEFAULT ORDER BY } - //BUILD ORDER BY AND APPEND IT - //TODO: Code a separate order by builder block - - + + + #pragma warning disable EF1000 var items = await ct.Widget