diff --git a/devdocs/todo.txt b/devdocs/todo.txt
index 163b9e73..2641676b 100644
--- a/devdocs/todo.txt
+++ b/devdocs/todo.txt
@@ -1,6 +1,6 @@
# SERVER TODO (J.F.C. - Just fucking code it already)
-Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNTQ0NTU5NzAwIiwiZXhwIjoiMTU0NzE1MTcwMCIsImlzcyI6ImF5YW5vdmEuY29tIiwiaWQiOiIxIiwiYXlhbm92YS9yb2xlcyI6IjMyNzY3In0.fMq_8Dvia63rzN_U2zjczPvUNM40OEAeI4VOeV6ulGw
+Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNTQ3NTgwMzg2IiwiZXhwIjoiMTU1MDE3MjM4NiIsImlzcyI6ImF5YW5vdmEuY29tIiwiaWQiOiIxIiwiYXlhbm92YS9yb2xlcyI6IjMyNzY3In0.duYSuTC2v9dCD7POPTvRNB2B4tGCkNQ1UDkgaSrNSYo
## IMMEDIATE ITEMS
diff --git a/server/AyaNova/Controllers/FormCustomController.cs b/server/AyaNova/Controllers/FormCustomController.cs
index 9afdc792..2ba54473 100644
--- a/server/AyaNova/Controllers/FormCustomController.cs
+++ b/server/AyaNova/Controllers/FormCustomController.cs
@@ -125,6 +125,53 @@ namespace AyaNova.Api.Controllers
}
}
+ ///
+ /// Get available types allowed for Custom fields
+ /// Used to build UI for customizing a form
+ ///
+ /// Required roles:
+ /// BizAdminFull only has rights to customize forms
+ ///
+ ///
+ /// A list of type string values valid for custom fields
+ [HttpGet("AvailableCustomTypes")]
+ public ActionResult GetAvailableCustomTypes()
+ {
+ if (serverState.IsClosed)
+ return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
+
+ if (!Authorized.IsAuthorizedToReadFullRecord(HttpContext.Items, AyaType.FormCustom))
+ return StatusCode(401, new ApiNotAuthorizedResponse());
+
+ if (!ModelState.IsValid)
+ return BadRequest(new ApiErrorResponse(ModelState));
+ return Ok(new ApiOkResponse(AyDataType.ValidCustomFieldTypes));
+ }
+
+
+ ///
+ /// Get a list of all customizable form keys
+ /// Used to build UI for customizing a form
+ ///
+ /// Required roles:
+ /// BizAdminFull only has rights to customize forms
+ ///
+ ///
+ /// A list of string formKey values valid for customization
+ [HttpGet("AvailableCustomizableFormKeys")]
+ public ActionResult GetAvailableCustomizableFormKeys()
+ {
+ if (serverState.IsClosed)
+ return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
+
+ if (!Authorized.IsAuthorizedToReadFullRecord(HttpContext.Items, AyaType.FormCustom))
+ return StatusCode(401, new ApiNotAuthorizedResponse());
+
+ if (!ModelState.IsValid)
+ return BadRequest(new ApiErrorResponse(ModelState));
+ return Ok(new ApiOkResponse(FormAvailableFields.AvailableFormKeys));
+ }
+
diff --git a/server/AyaNova/biz/AyDataType.cs b/server/AyaNova/biz/AyDataType.cs
index e1225030..d075d6e7 100644
--- a/server/AyaNova/biz/AyDataType.cs
+++ b/server/AyaNova/biz/AyDataType.cs
@@ -1,3 +1,5 @@
+using System.Collections.Generic;
+
namespace AyaNova.Biz
{
public static class AyDataType
@@ -10,5 +12,19 @@ namespace AyaNova.Biz
public const string Tags = "tags";
public const string Enum = "enum";//enums are just integers in the db so the sql code handles it like an int, but the client needs to know it's an enum
+ public static List ValidCustomFieldTypes
+ {
+ get
+ {
+ var ret = new List();
+ ret.Add(AyDataType.Date);
+ ret.Add(AyDataType.Text);
+ ret.Add(AyDataType.Integer);
+ ret.Add(AyDataType.Bool);
+ ret.Add(AyDataType.Decimal);
+ return ret;
+ }
+ }
+
}
}
diff --git a/server/AyaNova/biz/FormCustomBiz.cs b/server/AyaNova/biz/FormCustomBiz.cs
index 90d3b4c1..164d46b0 100644
--- a/server/AyaNova/biz/FormCustomBiz.cs
+++ b/server/AyaNova/biz/FormCustomBiz.cs
@@ -149,16 +149,23 @@ namespace AyaNova.Biz
// if (inObj.OwnerId != UserId)
// AddError(ValidationErrorType.InvalidValue, "OwnerId", "OwnerId must be current user Id");
- //FormKey required
+ //FormKey required and must be valid
if (string.IsNullOrWhiteSpace(inObj.FormKey))
AddError(ValidationErrorType.RequiredPropertyEmpty, "FormKey");
+ else
+ {
+ if (!FormAvailableFields.IsValidFormKey(inObj.FormKey))
+ {
+ AddError(ValidationErrorType.InvalidValue, "FormKey");
+ }
+ }
//FormKey must be less than 255 characters
if (inObj.FormKey.Length > 255)
AddError(ValidationErrorType.LengthExceeded, "FormKey", "255 max");
//If name is otherwise OK, check that name is unique
- if (!PropertyHasErrors("FormKey"))
+ if (!PropertyHasErrors("FormKey") && isNew)
{
//Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
if (ct.FormCustom.Any(m => m.FormKey == inObj.FormKey && m.Id != inObj.Id))
@@ -169,9 +176,12 @@ namespace AyaNova.Biz
+
//Template json must parse
- if (!string.IsNullOrWhiteSpace(inObj.Template))
+ if ((!PropertyHasErrors("FormKey") && !string.IsNullOrWhiteSpace(inObj.Template)))
{
+ var ValidCustomFieldTypes = AyDataType.ValidCustomFieldTypes;
+ var ValidFormFields = FormAvailableFields.FormFields(inObj.FormKey);
try
{
var v = JArray.Parse(inObj.Template);
@@ -182,7 +192,7 @@ namespace AyaNova.Biz
*/
//Validate the following:
- //FormKey is valid value
+
//All fields specified are valid values
//Field is allowed to be hidden if hidden
//Type is one of the valid types:
@@ -194,59 +204,90 @@ namespace AyaNova.Biz
public const string Decimal = "decimal";
*/
- TODO: validate the json
+ //TODO: validate the json
/*
- JSON FRAGMENT holds items that differ from stock, no "core" fields allowed
- FieldKey
- Hide
- Required
- Type (checkbox, date, date time, decimal, number, picklist(FUTURE), and text)
+
+ {[
+ {
+ "fld": "WidgetCustom1",
+ "hide": false,
+ "required": true,
+ "type": "date"
+ },
+ {
+ "fld": "WidgetCustom2",
+ "hide": true,
+ "required": false,
+ "type": "bool"
+ }
+]}
*/
- // for (int i = 0; i < v.Count; i++)
- // {
- // var filterItem = v[i];
- // if (filterItem["fld"] == null)
- // AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, object is missing required \"fld\" property ");
- // else
- // {
- // var fld = filterItem["fld"].Value();
- // if (string.IsNullOrWhiteSpace(fld))
- // AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, \"fld\" property is empty and required");
- // //validate the field name if we can
- // if (ListValidFilterOptions != null)
- // {
+ for (int i = 0; i < v.Count; i++)
+ {
+ FormField MasterFormField = null;
- // 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");
- // }
+ var formFieldItem = v[i];
+ if (formFieldItem["fld"] == null)
+ AddError(ValidationErrorType.RequiredPropertyEmpty, "Template", $"Template array item {i}, object is missing required \"fld\" property ");
+ else
+ {
+ var fldKey = formFieldItem["fld"].Value();
+ if (string.IsNullOrWhiteSpace(fldKey))
+ AddError(ValidationErrorType.RequiredPropertyEmpty, "Template", $"Template array item {i}, \"fld\" property is empty and required");
- // }
- // }
- // if (filterItem["op"] == null)
- // AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, object is missing required \"op\" property ");
- // else
- // {
- // var opType = filterItem["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");
- // }
+ //validate the field name if we can
+ if (ValidFormFields != null)
+ {
- // if (filterItem["value"] == null)
- // AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, object is missing or is empty the required \"value\" property ");
- // else
- // {
- // if (filterItem["value"].Type == JTokenType.String && string.IsNullOrWhiteSpace(filterItem["value"].Value()))
- // AddError(ValidationErrorType.RequiredPropertyEmpty, "Filter", $"Filter array item {i}, object is missing or is empty the required \"value\" property ");
+ if (!ValidFormFields.Exists(x => x.Key == fldKey))
+ {
+ AddError(ValidationErrorType.InvalidValue, "Template", $"Template array item {i}, fld property value \"{fldKey}\" is not a valid form field value for formKey specified");
+ }
+ else
+ {
+ MasterFormField = ValidFormFields.FirstOrDefault(x => x.Key == fldKey);
+ }
- // if (filterItem["value"].Type == JTokenType.Array && filterItem["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
- // }
+ if (MasterFormField != null)
+ {
+
+ if (formFieldItem["hide"] != null)
+ {
+ var fieldHideValue = formFieldItem["hide"].Value();
+ if (!MasterFormField.Hideable && fieldHideValue == true)
+ AddError(ValidationErrorType.InvalidValue, "Template", $"Template array item {i}, \"hide\" property value of \"{fieldHideValue}\" is not valid, this field is core and cannot be hidden");
+ }
+
+ if (formFieldItem["type"] != null)
+ {
+ if (!MasterFormField.Custom)
+ AddError(ValidationErrorType.InvalidValue, "Template", $"Template array item {i}, \"type\" property value is not valid, only Custom fields can have types specified");
+ else
+ {//It is a custom field, is it a valid type value
+ var templateFieldCustomTypeValue = formFieldItem["type"].Value();
+ if (!ValidCustomFieldTypes.Contains(templateFieldCustomTypeValue))
+ AddError(ValidationErrorType.InvalidValue, "Template", $"Template array item {i}, \"type\" property value of \"{templateFieldCustomTypeValue}\" is not a valid custom field type");
+ }
+ }
+
+ }
+
+ if (formFieldItem["required"] == null)
+ AddError(ValidationErrorType.RequiredPropertyEmpty, "Template", $"Template array item {i}, object is missing required \"required\" property ");
+
+
+ //NOTE: value of nothing, null or empty is a valid value so no checking for it here
+ }
}
catch (Newtonsoft.Json.JsonReaderException ex)
{