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
|
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
|
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:
|
If the client isn't using a particular dataListView it MUST send the ListView json as empty string or omit it entirely.
|
||||||
{default:"PickList"} or {default:"DataTable"}
|
|
||||||
This will instruct the server to use the pre-defined format instead
|
This will instruct the server to use the pre-defined format instead
|
||||||
|
|
||||||
JSON DataListView format:
|
JSON DataListView format:
|
||||||
@@ -47,6 +46,10 @@ Example:
|
|||||||
DataListView JSON:
|
DataListView JSON:
|
||||||
[{key:"COLUMN UNIQUE KEY ID",sort:"-" or "+",filter:{any:true/false,items:[{FILTER OBJECT SEE BELOW}]} }, {key:"second column unique key"},{...etc...}]
|
[{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:
|
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)
|
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;
|
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)
|
if (!ModelState.IsValid)
|
||||||
return BadRequest(new ApiErrorResponse(ModelState));
|
return BadRequest(new ApiErrorResponse(ModelState));
|
||||||
|
|||||||
@@ -20,107 +20,103 @@ namespace AyaNova.DataList
|
|||||||
|
|
||||||
public string SQLFrom { get; set; }
|
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 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 AllowedRoles { get; set; }
|
||||||
public AuthorizationRoles MiniListAllowedRoles { get; set; }
|
|
||||||
public AyaType DefaultListObjectType { 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}}}]";
|
throw new System.NotImplementedException("AyaDataList:GenerateListColumnsJSONFromListView not coded yet ");
|
||||||
return JArray.Parse($"[ {{\"cm\":\"df\",\"dt\":0,\"ay\":{(int)DefaultListObjectType}}},{{\"cm\":\"Widget\",\"dt\":{(int)UiFieldDataType.Text},\"ay\":{(int)DefaultListObjectType}}}]");
|
// //parse the template
|
||||||
}
|
// var jtemplate = JObject.Parse(listView);
|
||||||
|
|
||||||
public Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromTemplate(string template)
|
|
||||||
{
|
|
||||||
//parse the template
|
|
||||||
var jtemplate = JObject.Parse(template);
|
|
||||||
|
|
||||||
|
|
||||||
//convert to strings (https://stackoverflow.com/a/33836599/8939)
|
// //convert to strings (https://stackoverflow.com/a/33836599/8939)
|
||||||
var fullFields = ((JArray)jtemplate["full"]).ToObject<string[]>();
|
// var fullFields = ((JArray)jtemplate["full"]).ToObject<string[]>();
|
||||||
|
|
||||||
//Generate JSON fragment to return with column definitions
|
// //Generate JSON fragment to return with column definitions
|
||||||
StringBuilder sb = new StringBuilder();
|
// StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
sb.Append("[");
|
// sb.Append("[");
|
||||||
//df First column is always the df column
|
// //df First column is always the df column
|
||||||
sb.Append($"{{\"cm\":\"df\",\"dt\":0,\"ay\":{(int)DefaultListObjectType}}}");
|
// sb.Append($"{{\"cm\":\"df\",\"dt\":0,\"ay\":{(int)DefaultListObjectType}}}");
|
||||||
|
|
||||||
foreach (string s in fullFields)
|
// foreach (string s in fullFields)
|
||||||
{
|
// {
|
||||||
AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
// AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
||||||
#if (DEBUG)
|
// #if (DEBUG)
|
||||||
//Developers little helper
|
// //Developers little helper
|
||||||
if (o == null)
|
// if (o == null)
|
||||||
{
|
// {
|
||||||
throw new System.ArgumentNullException($"DEV ERROR in AyaDataList::GenerateListColumnsJSONFromTemplate - field {s} specified in template was NOT found in ObjectFields list");
|
// throw new System.ArgumentNullException($"DEV ERROR in AyaDataList::GenerateListColumnsJSONFromTemplate - field {s} specified in template was NOT found in ObjectFields list");
|
||||||
}
|
// }
|
||||||
#endif
|
// #endif
|
||||||
|
|
||||||
if (o != null)
|
// 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
|
// {//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(",");
|
||||||
sb.Append("{");
|
// sb.Append("{");
|
||||||
//Build required part of column definition
|
// //Build required part of column definition
|
||||||
sb.Append($"\"cm\":\"{o.LtKey}\",\"dt\":{(int)o.UiFieldDataType}");
|
// sb.Append($"\"cm\":\"{o.LtKey}\",\"dt\":{(int)o.UiFieldDataType}");
|
||||||
|
|
||||||
//Has a AyObjectType? (linkable / openable)
|
// //Has a AyObjectType? (linkable / openable)
|
||||||
if (o.AyaObjectType != 0)
|
// if (o.AyaObjectType != 0)
|
||||||
sb.Append($",\"ay\":{(int)o.AyaObjectType}");
|
// sb.Append($",\"ay\":{(int)o.AyaObjectType}");
|
||||||
|
|
||||||
//Has a Enumtype?
|
// //Has a Enumtype?
|
||||||
if (!string.IsNullOrEmpty(o.EnumType))
|
// if (!string.IsNullOrEmpty(o.EnumType))
|
||||||
sb.Append($",\"et\":\"{AyaNova.Util.StringUtil.TrimTypeName(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
|
// //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
|
// //this is more for dev errors or api users becuase the client shouldn't generate bad templates
|
||||||
public bool ValidateTemplate(string template)
|
// public bool ValidateTemplate(string template)
|
||||||
{
|
// {
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
//parse the template
|
// //parse the template
|
||||||
var jtemplate = JObject.Parse(template);
|
// var jtemplate = JObject.Parse(template);
|
||||||
var fullFields = ((JArray)jtemplate["full"]).ToObject<string[]>();
|
// var fullFields = ((JArray)jtemplate["full"]).ToObject<string[]>();
|
||||||
var miniFields = ((JArray)jtemplate["mini"]).ToObject<string[]>();
|
// var miniFields = ((JArray)jtemplate["mini"]).ToObject<string[]>();
|
||||||
|
|
||||||
foreach (string s in fullFields)
|
// foreach (string s in fullFields)
|
||||||
{
|
// {
|
||||||
AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
// AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
||||||
if (o == null)
|
// if (o == null)
|
||||||
{
|
// {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
foreach (string s in miniFields)
|
// foreach (string s in miniFields)
|
||||||
{
|
// {
|
||||||
AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
// AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
|
||||||
if (o == null)
|
// if (o == null)
|
||||||
{
|
// {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
catch
|
// catch
|
||||||
{
|
// {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
}//eoc
|
}//eoc
|
||||||
|
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ namespace AyaNova.DataList
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ColumnsJSON = DataList.GenerateListColumnsJSONFromTemplate(JSONDataListTemplate);
|
ColumnsJSON = DataList.GenerateListColumnsJSONFromListView(JSONDataListTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,34 +4,25 @@ namespace AyaNova.DataList
|
|||||||
{
|
{
|
||||||
internal interface IAyaDataList
|
internal interface IAyaDataList
|
||||||
{
|
{
|
||||||
//Unique key to identify this list
|
|
||||||
string ListKey { get; set; }
|
|
||||||
|
|
||||||
//sql query from fragment with table joins et
|
//sql query from fragment with table joins et
|
||||||
string SQLFrom { get; set; }
|
string SQLFrom { get; set; }
|
||||||
|
|
||||||
//List of fields for this object
|
//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
|
List<AyaDataListFieldDefinition> FieldDefinitions { get; set; }
|
||||||
|
|
||||||
//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; }
|
|
||||||
|
|
||||||
|
|
||||||
|
//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)
|
//Default object type to open for rows of this list (use no object if no)
|
||||||
AyaType DefaultListObjectType { get; set; }
|
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
|
//Default / STOCK DataListView when none is specified
|
||||||
string DefaultDataListDisplayTemplate { get; set; }
|
string DefaultListView { get; set; }
|
||||||
|
|
||||||
|
Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromListView(string template);
|
||||||
|
|
||||||
Newtonsoft.Json.Linq.JArray GenerateMINIListColumnsJSON();
|
// bool ValidateTemplate(string template);
|
||||||
Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromTemplate(string template);
|
|
||||||
|
|
||||||
bool ValidateTemplate(string template);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace AyaNova.Api.ControllerHelpers
|
namespace AyaNova.DataList
|
||||||
{
|
{
|
||||||
|
|
||||||
public sealed class ListOptions
|
public sealed class ListOptions
|
||||||
@@ -15,23 +15,15 @@ namespace AyaNova.Api.ControllerHelpers
|
|||||||
|
|
||||||
[FromBody]
|
[FromBody]
|
||||||
public int? Limit { get; set; }
|
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]
|
[FromBody, Required]
|
||||||
public string DataListKey { get; set; }
|
public string DataListKey { get; set; }
|
||||||
|
|
||||||
[FromBody]
|
[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 System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using AyaNova.Biz;
|
using AyaNova.Biz;
|
||||||
namespace AyaNova.DataList
|
namespace AyaNova.DataList
|
||||||
{
|
{
|
||||||
@@ -7,18 +8,52 @@ namespace AyaNova.DataList
|
|||||||
//No JOINS just straight up widgets
|
//No JOINS just straight up widgets
|
||||||
public TestWidgetDataList()
|
public TestWidgetDataList()
|
||||||
{
|
{
|
||||||
ListKey = nameof(TestWidgetDataList);
|
|
||||||
DefaultListObjectType = AyaType.Widget;
|
DefaultListObjectType = AyaType.Widget;
|
||||||
SQLFrom = "from awidget left outer join auser on (awidget.userid=auser.id)";
|
SQLFrom = "from awidget left outer join auser on (awidget.userid=auser.id)";
|
||||||
FullListAllowedRoles = BizRoles.GetRoleSet(DefaultListObjectType).ReadFullRecord;
|
AllowedRoles = BizRoles.GetRoleSet(DefaultListObjectType).ReadFullRecord;
|
||||||
MiniListAllowedRoles = AuthorizationRoles.All;//anyone (so can select on forms)
|
|
||||||
|
|
||||||
DefaultDataListDisplayTemplate = @"
|
//Default ListView
|
||||||
{
|
dynamic dlistView = new JArray();
|
||||||
""full"":[""widgetname"",""widgetserial"",""widgetdollaramount"",""widgetusertype"",""widgetstartdate"",""widgetactive"",""username""],
|
dynamic cm=new JObject();
|
||||||
""mini"":[""widgetname"",""widgetserial""]
|
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
|
//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>();
|
FieldDefinitions = new List<AyaDataListFieldDefinition>();
|
||||||
|
|||||||
Reference in New Issue
Block a user