Browse Source

Add form schemas and form page support

Add schema definitions for forms (form-descriptor, form-field-descriptor, form-field-type, form-layout-descriptor, form-rule-descriptor) to describe named forms, fields, layouts and conditional rules. Update page-type to include a new "form" page type and extend page-descriptor with form-related properties (formName, createFormName, editFormName, createFormDisplay, editFormDisplay) and conditional validation (require formName for type 'form', keep kanban's required groupByProperty). Extend model.schema.json to include a top-level "forms" array referencing the new form definitions.
pull/25039/head
Halil İbrahim Kalkan 3 weeks ago
parent
commit
24dabd0a1c
  1. 38
      lowcode/schema/definitions/form-descriptor.schema.json
  2. 61
      lowcode/schema/definitions/form-field-descriptor.schema.json
  3. 18
      lowcode/schema/definitions/form-field-type.schema.json
  4. 105
      lowcode/schema/definitions/form-layout-descriptor.schema.json
  5. 71
      lowcode/schema/definitions/form-rule-descriptor.schema.json
  6. 49
      lowcode/schema/definitions/page-descriptor.schema.json
  7. 2
      lowcode/schema/definitions/page-type.schema.json
  8. 7
      lowcode/schema/model.schema.json

38
lowcode/schema/definitions/form-descriptor.schema.json

@ -0,0 +1,38 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "form-descriptor.schema.json",
"title": "FormDescriptor",
"description": "Describes a named form definition bound to an entity",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Unique identifier for the form",
"minLength": 1
},
"entityName": {
"type": "string",
"description": "Full name of the entity this form is bound to (e.g., 'Namespace.EntityName')",
"minLength": 1
},
"fields": {
"type": "array",
"description": "Flat list of all field definitions in this form",
"items": {
"$ref": "form-field-descriptor.schema.json"
}
},
"layout": {
"$ref": "form-layout-descriptor.schema.json"
},
"rules": {
"type": "array",
"description": "Conditional rules for field/group visibility and enabled state",
"items": {
"$ref": "form-rule-descriptor.schema.json"
}
}
},
"required": ["name", "entityName", "fields", "layout"],
"additionalProperties": false
}

61
lowcode/schema/definitions/form-field-descriptor.schema.json

@ -0,0 +1,61 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "form-field-descriptor.schema.json",
"title": "FormFieldDescriptor",
"description": "Describes a single field in a form",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for this field within the form",
"minLength": 1
},
"label": {
"type": "string",
"description": "Display label for the field",
"minLength": 1
},
"type": {
"$ref": "form-field-type.schema.json"
},
"binding": {
"type": ["string", "null"],
"description": "Entity property name to bind to, or null for unbound fields. Supports dotted paths like 'Parent.Name' for related entity display."
},
"enumType": {
"type": "string",
"description": "Full enum type name for select fields"
},
"defaultValue": {
"description": "Default value for the field"
},
"placeholder": {
"type": "string",
"description": "Placeholder text for the input"
},
"helpText": {
"type": "string",
"description": "Help text displayed below the field"
},
"readOnly": {
"type": "boolean",
"description": "Whether the field is read-only",
"default": false
},
"modeVisibility": {
"type": "string",
"enum": ["both", "createOnly", "editOnly"],
"description": "Controls in which form mode the field is visible",
"default": "both"
},
"validations": {
"type": "array",
"description": "Form-level validation rules (override or extend entity-level validators)",
"items": {
"$ref": "validator-descriptor.schema.json"
}
}
},
"required": ["id", "label", "type"],
"additionalProperties": false
}

18
lowcode/schema/definitions/form-field-type.schema.json

@ -0,0 +1,18 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "form-field-type.schema.json",
"title": "FormFieldType",
"description": "Available field types for form fields",
"type": "string",
"enum": [
"text",
"textarea",
"number",
"checkbox",
"date",
"select",
"lookup",
"guid",
"computed"
]
}

105
lowcode/schema/definitions/form-layout-descriptor.schema.json

@ -0,0 +1,105 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "form-layout-descriptor.schema.json",
"title": "FormLayoutDescriptor",
"description": "Describes the visual layout of a form (tabs > groups > field placements)",
"type": "object",
"properties": {
"tabs": {
"type": "array",
"description": "Ordered list of tabs in the form",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for this tab",
"minLength": 1
},
"title": {
"type": "string",
"description": "Display title for the tab",
"minLength": 1
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the default tab (cannot be deleted, receives orphaned fields)",
"default": false
},
"groups": {
"type": "array",
"description": "Ordered list of groups within this tab",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for this group",
"minLength": 1
},
"title": {
"type": ["string", "null"],
"description": "Optional display title for the group"
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the default group (cannot be deleted, receives orphaned fields)",
"default": false
},
"rows": {
"type": "array",
"description": "Ordered list of layout rows; each row contains one or more cells (fields placed side-by-side)",
"items": {
"type": "object",
"properties": {
"cells": {
"type": "array",
"description": "Fields placed side-by-side in this row (total colSpan should not exceed 4)",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"fieldId": {
"type": "string",
"description": "Reference to a field id in the form's fields array",
"minLength": 1
},
"colSpan": {
"type": "integer",
"description": "Number of grid columns this field spans (1-4)",
"minimum": 1,
"maximum": 4,
"default": 4
},
"colStart": {
"type": "integer",
"description": "Starting grid column (1-4). Omit or null to auto-place after the previous cell.",
"minimum": 1,
"maximum": 4
}
},
"required": ["fieldId"],
"additionalProperties": false
}
}
},
"required": ["cells"],
"additionalProperties": false
}
}
},
"required": ["id", "rows"],
"additionalProperties": false
}
}
},
"required": ["id", "title", "groups"],
"additionalProperties": false
}
}
},
"required": ["tabs"],
"additionalProperties": false
}

71
lowcode/schema/definitions/form-rule-descriptor.schema.json

@ -0,0 +1,71 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "form-rule-descriptor.schema.json",
"title": "FormRuleDescriptor",
"description": "Describes a conditional rule with one or more actions that execute when the condition is met",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for this rule",
"minLength": 1
},
"name": {
"type": "string",
"description": "Human-readable name for this rule (optional)"
},
"condition": {
"type": "object",
"description": "The condition that triggers this rule",
"properties": {
"fieldId": {
"type": "string",
"description": "The field whose value is evaluated",
"minLength": 1
},
"operator": {
"type": "string",
"enum": ["equals", "notEquals", "isEmpty", "isNotEmpty"],
"description": "Comparison operator"
},
"value": {
"description": "The value to compare against (not used for isEmpty/isNotEmpty)"
}
},
"required": ["fieldId", "operator"],
"additionalProperties": false
},
"actions": {
"type": "array",
"description": "Actions to perform when condition is met (executed in order)",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["hide", "show", "disable", "enable", "setValue"],
"description": "The action type"
},
"targetType": {
"type": "string",
"enum": ["field", "group"],
"description": "Whether the target is a field or a group"
},
"targetId": {
"type": "string",
"description": "The id of the target field or group",
"minLength": 1
},
"value": {
"description": "The value to set (only for setValue action)"
}
},
"required": ["type", "targetType", "targetId"],
"additionalProperties": false
}
}
},
"required": ["id", "condition", "actions"],
"additionalProperties": false
}

49
lowcode/schema/definitions/page-descriptor.schema.json

@ -36,14 +36,51 @@
"type": "integer",
"description": "Menu sort order (lower values appear first)",
"default": 0
},
"formName": {
"type": "string",
"description": "Name of the form to render (required when type is 'form')",
"minLength": 1
},
"createFormName": {
"type": "string",
"description": "Name of the form to use for creating entities (for dataGrid/kanban pages)"
},
"editFormName": {
"type": "string",
"description": "Name of the form to use for editing entities (for dataGrid/kanban pages)"
},
"createFormDisplay": {
"type": "string",
"enum": ["modal", "page"],
"description": "How to display the create form",
"default": "modal"
},
"editFormDisplay": {
"type": "string",
"enum": ["modal", "page"],
"description": "How to display the edit form",
"default": "modal"
}
},
"required": ["name", "title", "type", "entityName"],
"if": {
"properties": { "type": { "const": "kanban" } }
},
"then": {
"required": ["groupByProperty"]
},
"allOf": [
{
"if": {
"properties": { "type": { "const": "kanban" } }
},
"then": {
"required": ["groupByProperty"]
}
},
{
"if": {
"properties": { "type": { "const": "form" } }
},
"then": {
"required": ["formName"]
}
}
],
"additionalProperties": false
}

2
lowcode/schema/definitions/page-type.schema.json

@ -4,5 +4,5 @@
"title": "PageType",
"description": "The type of page to render",
"type": "string",
"enum": ["dataGrid", "kanban", "calendar"]
"enum": ["dataGrid", "kanban", "calendar", "form"]
}

7
lowcode/schema/model.schema.json

@ -36,6 +36,13 @@
"items": {
"$ref": "definitions/page-descriptor.schema.json"
}
},
"forms": {
"type": "array",
"description": "List of named form definitions for entity create/edit",
"items": {
"$ref": "definitions/form-descriptor.schema.json"
}
}
},
"additionalProperties": false

Loading…
Cancel
Save