This commit is contained in:
@@ -27,8 +27,7 @@ Users can select a datalistview for a picklist DataList which will in turn affec
|
||||
Users will get the default hard coded DataListView built into the DataList that is specified for that picklist unless it's changed to an alternative datalistview
|
||||
There is a default PickList format and a default DataTable format pre-defined and hard coded at the server with each dataList definition object
|
||||
|
||||
If the client isn't using a particular dataListView it MUST send the DataListView json as one of the following:
|
||||
{default:"PickList"} or {default:"DataTable"}
|
||||
If the client isn't using a particular dataListView it MUST send the ListView json as empty string or omit it entirely.
|
||||
This will instruct the server to use the pre-defined format instead
|
||||
|
||||
JSON DataListView format:
|
||||
@@ -47,6 +46,10 @@ Example:
|
||||
DataListView JSON:
|
||||
[{key:"COLUMN UNIQUE KEY ID",sort:"-" or "+",filter:{any:true/false,items:[{FILTER OBJECT SEE BELOW}]} }, {key:"second column unique key"},{...etc...}]
|
||||
|
||||
Sort property definition
|
||||
ID VS NAME
|
||||
if it's an name *and* id field
|
||||
|
||||
Filter object definition:
|
||||
Has an "any" boolean property which if true means make an OR query of the conditions if more than one, if nore present or false it means AND each condition (if more than one)
|
||||
|
||||
|
||||
@@ -63,14 +63,7 @@ namespace AyaNova.Api.Controllers
|
||||
{
|
||||
listOptions.Offset = 0;
|
||||
}
|
||||
//this is to workaround a quirk in the api explorer with default values
|
||||
if(listOptions.SortJson=="string"){
|
||||
listOptions.SortJson=string.Empty;
|
||||
}
|
||||
if(listOptions.FilterJson=="string"){
|
||||
listOptions.FilterJson=string.Empty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
return BadRequest(new ApiErrorResponse(ModelState));
|
||||
|
||||
@@ -20,107 +20,103 @@ namespace AyaNova.DataList
|
||||
|
||||
public string SQLFrom { get; set; }
|
||||
public List<AyaDataListFieldDefinition> FieldDefinitions { get; set; }//NOTE: First field after df is used as the title above the narrow grid view so it should be the name of the item to be shown that is most identifiable
|
||||
public AuthorizationRoles FullListAllowedRoles { get; set; }
|
||||
public AuthorizationRoles MiniListAllowedRoles { get; set; }
|
||||
public AuthorizationRoles AllowedRoles { get; set; }
|
||||
public AyaType DefaultListObjectType { get; set; }
|
||||
public string ListKey { get; set; }
|
||||
public string DefaultDataListDisplayTemplate { get; set; }
|
||||
|
||||
public Newtonsoft.Json.Linq.JArray GenerateMINIListColumnsJSON()
|
||||
public string DefaultListView { get; set; }
|
||||
|
||||
|
||||
|
||||
public Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromListView(string listView)
|
||||
{
|
||||
//return $"[ {{\"cm\":\"df\",\"dt\":0,\"ay\":{(int)DefaultListObjectType}}},{{\"cm\":\"Widget\",\"dt\":{(int)AyaUiFieldDataType.Text},\"ay\":{(int)DefaultListObjectType}}}]";
|
||||
return JArray.Parse($"[ {{\"cm\":\"df\",\"dt\":0,\"ay\":{(int)DefaultListObjectType}}},{{\"cm\":\"Widget\",\"dt\":{(int)UiFieldDataType.Text},\"ay\":{(int)DefaultListObjectType}}}]");
|
||||
}
|
||||
|
||||
public Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromTemplate(string template)
|
||||
{
|
||||
//parse the template
|
||||
var jtemplate = JObject.Parse(template);
|
||||
throw new System.NotImplementedException("AyaDataList:GenerateListColumnsJSONFromListView not coded yet ");
|
||||
// //parse the template
|
||||
// var jtemplate = JObject.Parse(listView);
|
||||
|
||||
|
||||
//convert to strings (https://stackoverflow.com/a/33836599/8939)
|
||||
var fullFields = ((JArray)jtemplate["full"]).ToObject<string[]>();
|
||||
// //convert to strings (https://stackoverflow.com/a/33836599/8939)
|
||||
// var fullFields = ((JArray)jtemplate["full"]).ToObject<string[]>();
|
||||
|
||||
//Generate JSON fragment to return with column definitions
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// //Generate JSON fragment to return with column definitions
|
||||
// StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.Append("[");
|
||||
//df First column is always the df column
|
||||
sb.Append($"{{\"cm\":\"df\",\"dt\":0,\"ay\":{(int)DefaultListObjectType}}}");
|
||||
// sb.Append("[");
|
||||
// //df First column is always the df column
|
||||
// sb.Append($"{{\"cm\":\"df\",\"dt\":0,\"ay\":{(int)DefaultListObjectType}}}");
|
||||
|
||||
foreach (string s in fullFields)
|
||||
{
|
||||
AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
||||
#if (DEBUG)
|
||||
//Developers little helper
|
||||
if (o == null)
|
||||
{
|
||||
throw new System.ArgumentNullException($"DEV ERROR in AyaDataList::GenerateListColumnsJSONFromTemplate - field {s} specified in template was NOT found in ObjectFields list");
|
||||
}
|
||||
#endif
|
||||
// foreach (string s in fullFields)
|
||||
// {
|
||||
// AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
||||
// #if (DEBUG)
|
||||
// //Developers little helper
|
||||
// if (o == null)
|
||||
// {
|
||||
// throw new System.ArgumentNullException($"DEV ERROR in AyaDataList::GenerateListColumnsJSONFromTemplate - field {s} specified in template 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 (o != null)
|
||||
// {//Here is where we can vet the field name, if it doesn't exist. For production we'll just ignore those ones
|
||||
|
||||
sb.Append(",");
|
||||
sb.Append("{");
|
||||
//Build required part of column definition
|
||||
sb.Append($"\"cm\":\"{o.LtKey}\",\"dt\":{(int)o.UiFieldDataType}");
|
||||
// sb.Append(",");
|
||||
// sb.Append("{");
|
||||
// //Build required part of column definition
|
||||
// sb.Append($"\"cm\":\"{o.LtKey}\",\"dt\":{(int)o.UiFieldDataType}");
|
||||
|
||||
//Has a AyObjectType? (linkable / openable)
|
||||
if (o.AyaObjectType != 0)
|
||||
sb.Append($",\"ay\":{(int)o.AyaObjectType}");
|
||||
// //Has a AyObjectType? (linkable / openable)
|
||||
// if (o.AyaObjectType != 0)
|
||||
// sb.Append($",\"ay\":{(int)o.AyaObjectType}");
|
||||
|
||||
//Has a Enumtype?
|
||||
if (!string.IsNullOrEmpty(o.EnumType))
|
||||
sb.Append($",\"et\":\"{AyaNova.Util.StringUtil.TrimTypeName(o.EnumType)}\"");
|
||||
// //Has a Enumtype?
|
||||
// if (!string.IsNullOrEmpty(o.EnumType))
|
||||
// sb.Append($",\"et\":\"{AyaNova.Util.StringUtil.TrimTypeName(o.EnumType)}\"");
|
||||
|
||||
sb.Append("}");
|
||||
// sb.Append("}");
|
||||
|
||||
}
|
||||
}
|
||||
sb.Append("]");
|
||||
// }
|
||||
// }
|
||||
// sb.Append("]");
|
||||
|
||||
return JArray.Parse(sb.ToString());
|
||||
// return JArray.Parse(sb.ToString());
|
||||
}
|
||||
|
||||
|
||||
//make sure the template parses and all the fields specified are really existant
|
||||
//this is more for dev errors or api users becuase the client shouldn't generate bad templates
|
||||
public bool ValidateTemplate(string template)
|
||||
{
|
||||
try
|
||||
{
|
||||
//parse the template
|
||||
var jtemplate = JObject.Parse(template);
|
||||
var fullFields = ((JArray)jtemplate["full"]).ToObject<string[]>();
|
||||
var miniFields = ((JArray)jtemplate["mini"]).ToObject<string[]>();
|
||||
// //make sure the template parses and all the fields specified are really existant
|
||||
// //this is more for dev errors or api users becuase the client shouldn't generate bad templates
|
||||
// public bool ValidateTemplate(string template)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// //parse the template
|
||||
// var jtemplate = JObject.Parse(template);
|
||||
// var fullFields = ((JArray)jtemplate["full"]).ToObject<string[]>();
|
||||
// var miniFields = ((JArray)jtemplate["mini"]).ToObject<string[]>();
|
||||
|
||||
foreach (string s in fullFields)
|
||||
{
|
||||
AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
||||
if (o == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// foreach (string s in fullFields)
|
||||
// {
|
||||
// AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
||||
// if (o == null)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
foreach (string s in miniFields)
|
||||
{
|
||||
AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
||||
if (o == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// foreach (string s in miniFields)
|
||||
// {
|
||||
// AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
||||
// if (o == null)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
// return true;
|
||||
// }
|
||||
|
||||
}//eoc
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ namespace AyaNova.DataList
|
||||
}
|
||||
else
|
||||
{
|
||||
ColumnsJSON = DataList.GenerateListColumnsJSONFromTemplate(JSONDataListTemplate);
|
||||
ColumnsJSON = DataList.GenerateListColumnsJSONFromListView(JSONDataListTemplate);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,34 +4,25 @@ namespace AyaNova.DataList
|
||||
{
|
||||
internal interface IAyaDataList
|
||||
{
|
||||
//Unique key to identify this list
|
||||
string ListKey { get; set; }
|
||||
|
||||
|
||||
//sql query from fragment with table joins et
|
||||
string SQLFrom { get; set; }
|
||||
|
||||
//List of fields for this object
|
||||
List<AyaDataListFieldDefinition> FieldDefinitions { get; set; }//NOTE: First field after df is used as the title above the narrow grid view so it should be the name of the item to be shown that is most identifiable
|
||||
|
||||
//allowed roles to access the full list templated fields
|
||||
AuthorizationRoles FullListAllowedRoles { get; set; }
|
||||
|
||||
//allowed roles to access mini list templated fields
|
||||
//generally this will be *any* because most forms will need to allow this for picklists such as usernames etc
|
||||
// but this is a safety valve for sensitive lists like financial reports where there is just no need for untrusted roles to see it
|
||||
AuthorizationRoles MiniListAllowedRoles { get; set; }
|
||||
|
||||
List<AyaDataListFieldDefinition> FieldDefinitions { get; set; }
|
||||
|
||||
//allowed roles to access this list
|
||||
AuthorizationRoles AllowedRoles { get; set; }
|
||||
|
||||
//Default object type to open for rows of this list (use no object if no)
|
||||
AyaType DefaultListObjectType { get; set; }
|
||||
|
||||
//Default list display template if none found in db or is invalid, this ensures the data will flow even if people fuck up the templates somehow
|
||||
string DefaultDataListDisplayTemplate { get; set; }
|
||||
//Default / STOCK DataListView when none is specified
|
||||
string DefaultListView { get; set; }
|
||||
|
||||
Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromListView(string template);
|
||||
|
||||
Newtonsoft.Json.Linq.JArray GenerateMINIListColumnsJSON();
|
||||
Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromTemplate(string template);
|
||||
|
||||
bool ValidateTemplate(string template);
|
||||
// bool ValidateTemplate(string template);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace AyaNova.Api.ControllerHelpers
|
||||
namespace AyaNova.DataList
|
||||
{
|
||||
|
||||
public sealed class ListOptions
|
||||
@@ -15,23 +15,15 @@ namespace AyaNova.Api.ControllerHelpers
|
||||
|
||||
[FromBody]
|
||||
public int? Limit { get; set; }
|
||||
|
||||
// //Data filter id to use with this list query
|
||||
// //0 or less means no filter
|
||||
// [FromBody]
|
||||
// public long DataFilterId { get; set; }
|
||||
|
||||
|
||||
public bool? Mini { get; set; }
|
||||
|
||||
|
||||
[FromBody, Required]
|
||||
public string DataListKey { get; set; }
|
||||
|
||||
[FromBody]
|
||||
public string FilterJson { get; set; }
|
||||
public string ListView { get; set; }//optional, if null or empty will use default list view built into DataList
|
||||
|
||||
[FromBody]
|
||||
public string SortJson { get; set; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using AyaNova.Biz;
|
||||
namespace AyaNova.DataList
|
||||
{
|
||||
@@ -7,18 +8,52 @@ namespace AyaNova.DataList
|
||||
//No JOINS just straight up widgets
|
||||
public TestWidgetDataList()
|
||||
{
|
||||
ListKey = nameof(TestWidgetDataList);
|
||||
|
||||
DefaultListObjectType = AyaType.Widget;
|
||||
SQLFrom = "from awidget left outer join auser on (awidget.userid=auser.id)";
|
||||
FullListAllowedRoles = BizRoles.GetRoleSet(DefaultListObjectType).ReadFullRecord;
|
||||
MiniListAllowedRoles = AuthorizationRoles.All;//anyone (so can select on forms)
|
||||
AllowedRoles = BizRoles.GetRoleSet(DefaultListObjectType).ReadFullRecord;
|
||||
|
||||
DefaultDataListDisplayTemplate = @"
|
||||
{
|
||||
""full"":[""widgetname"",""widgetserial"",""widgetdollaramount"",""widgetusertype"",""widgetstartdate"",""widgetactive"",""username""],
|
||||
""mini"":[""widgetname"",""widgetserial""]
|
||||
}
|
||||
";
|
||||
//Default ListView
|
||||
dynamic dlistView = new JArray();
|
||||
dynamic cm=new JObject();
|
||||
cm.fld="widgetname";
|
||||
dlistView.Add(cm);
|
||||
cm=new JObject();
|
||||
cm.fld="widgetname";
|
||||
dlistView.Add(cm);
|
||||
|
||||
cm=new JObject();
|
||||
cm.fld="widgetname";
|
||||
dlistView.Add(cm);
|
||||
cm=new JObject();
|
||||
cm.fld="widgetname";
|
||||
dlistView.Add(cm);
|
||||
cm=new JObject();
|
||||
cm.fld="widgetname";
|
||||
dlistView.Add(cm);
|
||||
cm=new JObject();
|
||||
cm.fld="widgetname";
|
||||
dlistView.Add(cm);
|
||||
cm=new JObject();
|
||||
cm.fld="widgetname";
|
||||
dlistView.Add(cm);
|
||||
|
||||
// //name starts with filter to constrict to widgets that this test block created only
|
||||
// dynamic DataFilterNameStart = new JObject();
|
||||
// DataFilterNameStart.fld = "widgetname";
|
||||
// DataFilterNameStart.op = Util.OpStartsWith;
|
||||
// DataFilterNameStart.value = WidgetNameStart;
|
||||
// dfilter.Add(DataFilterNameStart);
|
||||
|
||||
|
||||
// DefaultDataListView = @"
|
||||
// {
|
||||
// [{key:""COLUMN UNIQUE KEY ID",sort:"-" or "+",filter:{any:true/false,items:[{FILTER OBJECT SEE BELOW}]} }, {key:"second column unique key"},{...etc...}]
|
||||
|
||||
// ""full"":[""widgetname"",""widgetserial"",""widgetdollaramount"",""widgetusertype"",""widgetstartdate"",""widgetactive"",""username""],
|
||||
|
||||
// }
|
||||
// ";
|
||||
|
||||
//NOTE: Due to the join, all the sql id and name fields that can conflict with the joined (in this case User) table need to be specified completely
|
||||
FieldDefinitions = new List<AyaDataListFieldDefinition>();
|
||||
|
||||
Reference in New Issue
Block a user