From 445f3e5e4158fc9df0fe7fe93c8f20eb2decefb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Mon, 9 Mar 2026 04:18:00 +0300 Subject: [PATCH] Add dashboard schemas and page dashboard support Introduce a set of JSON Schema definitions to support dashboards and visualizations (aggregation, chart, chart-type, descriptor, filter, group, list, number, position, user-filter, visualization, visualization-type). Update page-descriptor.schema.json to include a dashboard property and a conditional requirement when page type is "dashboard", and extend page-type.schema.json enum to include "dashboard". These changes add schema-level validation for dashboard configuration, visualizations (number/chart/list), positioning, and filters. --- .../dashboard-aggregation-type.schema.json | 8 ++ .../dashboard-chart-descriptor.schema.json | 74 +++++++++++++++++++ .../dashboard-chart-type.schema.json | 8 ++ .../dashboard-descriptor.schema.json | 23 ++++++ .../dashboard-filter-descriptor.schema.json | 38 ++++++++++ .../dashboard-group-descriptor.schema.json | 54 ++++++++++++++ .../dashboard-list-descriptor.schema.json | 55 ++++++++++++++ .../dashboard-number-descriptor.schema.json | 48 ++++++++++++ .../dashboard-position-descriptor.schema.json | 29 ++++++++ ...shboard-user-filter-descriptor.schema.json | 21 ++++++ ...board-visualization-descriptor.schema.json | 65 ++++++++++++++++ .../dashboard-visualization-type.schema.json | 8 ++ .../definitions/page-descriptor.schema.json | 11 +++ .../schema/definitions/page-type.schema.json | 2 +- 14 files changed, 443 insertions(+), 1 deletion(-) create mode 100644 lowcode/schema/definitions/dashboard-aggregation-type.schema.json create mode 100644 lowcode/schema/definitions/dashboard-chart-descriptor.schema.json create mode 100644 lowcode/schema/definitions/dashboard-chart-type.schema.json create mode 100644 lowcode/schema/definitions/dashboard-descriptor.schema.json create mode 100644 lowcode/schema/definitions/dashboard-filter-descriptor.schema.json create mode 100644 lowcode/schema/definitions/dashboard-group-descriptor.schema.json create mode 100644 lowcode/schema/definitions/dashboard-list-descriptor.schema.json create mode 100644 lowcode/schema/definitions/dashboard-number-descriptor.schema.json create mode 100644 lowcode/schema/definitions/dashboard-position-descriptor.schema.json create mode 100644 lowcode/schema/definitions/dashboard-user-filter-descriptor.schema.json create mode 100644 lowcode/schema/definitions/dashboard-visualization-descriptor.schema.json create mode 100644 lowcode/schema/definitions/dashboard-visualization-type.schema.json diff --git a/lowcode/schema/definitions/dashboard-aggregation-type.schema.json b/lowcode/schema/definitions/dashboard-aggregation-type.schema.json new file mode 100644 index 0000000000..59294c051a --- /dev/null +++ b/lowcode/schema/definitions/dashboard-aggregation-type.schema.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-aggregation-type.schema.json", + "title": "DashboardAggregationType", + "description": "The type of aggregation to perform", + "type": "string", + "enum": ["count", "sum", "average", "min", "max", "percentFilled", "percentEmpty"] +} diff --git a/lowcode/schema/definitions/dashboard-chart-descriptor.schema.json b/lowcode/schema/definitions/dashboard-chart-descriptor.schema.json new file mode 100644 index 0000000000..f03fda2887 --- /dev/null +++ b/lowcode/schema/definitions/dashboard-chart-descriptor.schema.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-chart-descriptor.schema.json", + "title": "DashboardChartDescriptor", + "description": "Configuration for a chart visualization", + "type": "object", + "properties": { + "chartType": { + "$ref": "dashboard-chart-type.schema.json" + }, + "xAxis": { + "type": "object", + "properties": { + "property": { + "type": "string", + "description": "Property name to group by on the X-axis" + }, + "useForeignDisplay": { + "type": "boolean", + "description": "Show the FK display property instead of the raw ID", + "default": false + }, + "dateGrouping": { + "type": "string", + "enum": ["day", "week", "month", "quarter", "year"], + "description": "Grouping interval for DateTime properties" + } + }, + "required": ["property"], + "additionalProperties": false + }, + "yAxis": { + "type": "array", + "items": { + "type": "object", + "properties": { + "aggregation": { + "$ref": "dashboard-aggregation-type.schema.json" + }, + "property": { + "type": "string", + "description": "Property name for sum/average/min/max" + }, + "label": { + "type": "string", + "description": "Display label for this series" + }, + "color": { + "type": "string" + } + }, + "required": ["aggregation"], + "additionalProperties": false + }, + "minItems": 1 + }, + "size": { + "type": "string", + "enum": ["small", "medium", "large"], + "default": "medium" + }, + "barOrientation": { + "type": "string", + "enum": ["vertical", "horizontal"], + "default": "vertical" + }, + "showRecordCount": { + "type": "boolean", + "default": false + } + }, + "required": ["chartType", "xAxis", "yAxis"], + "additionalProperties": false +} diff --git a/lowcode/schema/definitions/dashboard-chart-type.schema.json b/lowcode/schema/definitions/dashboard-chart-type.schema.json new file mode 100644 index 0000000000..4e33a65841 --- /dev/null +++ b/lowcode/schema/definitions/dashboard-chart-type.schema.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-chart-type.schema.json", + "title": "DashboardChartType", + "description": "The type of chart", + "type": "string", + "enum": ["bar", "line", "pie", "donut"] +} diff --git a/lowcode/schema/definitions/dashboard-descriptor.schema.json b/lowcode/schema/definitions/dashboard-descriptor.schema.json new file mode 100644 index 0000000000..7b63da4cf0 --- /dev/null +++ b/lowcode/schema/definitions/dashboard-descriptor.schema.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-descriptor.schema.json", + "title": "DashboardDescriptor", + "description": "Describes a dashboard configuration with groups and visualizations", + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "Description text shown below the dashboard title" + }, + "groups": { + "type": "array", + "description": "Dashboard groups, each bound to a single entity", + "items": { + "$ref": "dashboard-group-descriptor.schema.json" + }, + "minItems": 1 + } + }, + "required": ["groups"], + "additionalProperties": false +} diff --git a/lowcode/schema/definitions/dashboard-filter-descriptor.schema.json b/lowcode/schema/definitions/dashboard-filter-descriptor.schema.json new file mode 100644 index 0000000000..1a5b7570e8 --- /dev/null +++ b/lowcode/schema/definitions/dashboard-filter-descriptor.schema.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-filter-descriptor.schema.json", + "title": "DashboardFilterDescriptor", + "description": "Static filter applied to a dashboard group or visualization", + "type": "object", + "properties": { + "operator": { + "type": "string", + "enum": ["and", "or"], + "default": "and" + }, + "conditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "property": { + "type": "string", + "description": "Property name to filter on" + }, + "filterType": { + "type": "string", + "enum": ["equal", "notEqual", "contains", "greaterThan", "lessThan", "isNull", "isNotNull"], + "default": "equal" + }, + "value": { + "description": "Filter value" + } + }, + "required": ["property", "filterType"], + "additionalProperties": false + } + } + }, + "required": ["conditions"], + "additionalProperties": false +} diff --git a/lowcode/schema/definitions/dashboard-group-descriptor.schema.json b/lowcode/schema/definitions/dashboard-group-descriptor.schema.json new file mode 100644 index 0000000000..2286c5ebc9 --- /dev/null +++ b/lowcode/schema/definitions/dashboard-group-descriptor.schema.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-group-descriptor.schema.json", + "title": "DashboardGroupDescriptor", + "description": "A dashboard group bound to a single entity, containing visualizations", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Unique identifier for this group within the dashboard", + "minLength": 1 + }, + "title": { + "type": "string", + "description": "Display title for the group section" + }, + "entityName": { + "type": "string", + "description": "Full entity name this group sources data from", + "minLength": 1 + }, + "filter": { + "$ref": "dashboard-filter-descriptor.schema.json" + }, + "userFilters": { + "type": "array", + "description": "Properties exposed as dynamic filters for end users", + "items": { + "$ref": "dashboard-user-filter-descriptor.schema.json" + } + }, + "appearance": { + "type": "object", + "properties": { + "useBackground": { + "type": "boolean", + "description": "Show light background color for this group", + "default": false + } + }, + "additionalProperties": false + }, + "visualizations": { + "type": "array", + "description": "Visualizations within this group", + "items": { + "$ref": "dashboard-visualization-descriptor.schema.json" + }, + "minItems": 1 + } + }, + "required": ["name", "entityName", "visualizations"], + "additionalProperties": false +} diff --git a/lowcode/schema/definitions/dashboard-list-descriptor.schema.json b/lowcode/schema/definitions/dashboard-list-descriptor.schema.json new file mode 100644 index 0000000000..6155142c30 --- /dev/null +++ b/lowcode/schema/definitions/dashboard-list-descriptor.schema.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-list-descriptor.schema.json", + "title": "DashboardListDescriptor", + "description": "Configuration for a list/table visualization", + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { "type": "string" }, + "description": "Property names to display as columns" + }, + "sortBy": { + "type": "object", + "properties": { + "property": { "type": "string" }, + "direction": { + "type": "string", + "enum": ["asc", "desc"], + "default": "asc" + } + }, + "required": ["property"], + "additionalProperties": false + }, + "maxRows": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + }, + "rowHeight": { + "type": "string", + "enum": ["compact", "normal", "tall"], + "default": "compact" + }, + "colorBy": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["property", "conditions"] + }, + "property": { + "type": "string", + "description": "Enum property name for automatic coloring" + } + }, + "required": ["type"], + "additionalProperties": false + } + }, + "required": ["fields"], + "additionalProperties": false +} diff --git a/lowcode/schema/definitions/dashboard-number-descriptor.schema.json b/lowcode/schema/definitions/dashboard-number-descriptor.schema.json new file mode 100644 index 0000000000..77d6815ed6 --- /dev/null +++ b/lowcode/schema/definitions/dashboard-number-descriptor.schema.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-number-descriptor.schema.json", + "title": "DashboardNumberDescriptor", + "description": "Configuration for a number/KPI visualization", + "type": "object", + "properties": { + "aggregation": { + "$ref": "dashboard-aggregation-type.schema.json" + }, + "aggregationProperty": { + "type": "string", + "description": "Property name for sum/average/min/max aggregations" + }, + "format": { + "type": "string", + "enum": ["number", "currency", "percentage"], + "default": "number" + }, + "color": { + "type": "string", + "description": "Display color name (blue, green, red, purple, orange, indigo, amber, teal)" + }, + "useBackgroundColor": { + "type": "boolean", + "default": false + }, + "conditionalColors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "operator": { + "type": "string", + "enum": ["greaterThan", "lessThan", "equals", "between"] + }, + "value": { "type": "number" }, + "valueTo": { "type": "number" }, + "color": { "type": "string" } + }, + "required": ["operator", "value", "color"], + "additionalProperties": false + } + } + }, + "required": ["aggregation"], + "additionalProperties": false +} diff --git a/lowcode/schema/definitions/dashboard-position-descriptor.schema.json b/lowcode/schema/definitions/dashboard-position-descriptor.schema.json new file mode 100644 index 0000000000..2148ecc59f --- /dev/null +++ b/lowcode/schema/definitions/dashboard-position-descriptor.schema.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-position-descriptor.schema.json", + "title": "DashboardPositionDescriptor", + "description": "Grid position for a visualization (4-column grid)", + "type": "object", + "properties": { + "row": { + "type": "integer", + "minimum": 0, + "description": "Row index (0-based)" + }, + "col": { + "type": "integer", + "minimum": 0, + "maximum": 3, + "description": "Column index (0-based, max 3)" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "default": 1, + "description": "Number of columns this visualization spans" + } + }, + "required": ["row", "col", "colSpan"], + "additionalProperties": false +} diff --git a/lowcode/schema/definitions/dashboard-user-filter-descriptor.schema.json b/lowcode/schema/definitions/dashboard-user-filter-descriptor.schema.json new file mode 100644 index 0000000000..d3a52f0edd --- /dev/null +++ b/lowcode/schema/definitions/dashboard-user-filter-descriptor.schema.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-user-filter-descriptor.schema.json", + "title": "DashboardUserFilterDescriptor", + "description": "An interactive filter exposed to end users as a dropdown or input", + "type": "object", + "properties": { + "property": { + "type": "string", + "description": "Property name to filter on", + "minLength": 1 + }, + "displayType": { + "type": "string", + "enum": ["dropdown", "dateRange", "text", "range"], + "default": "dropdown" + } + }, + "required": ["property"], + "additionalProperties": false +} diff --git a/lowcode/schema/definitions/dashboard-visualization-descriptor.schema.json b/lowcode/schema/definitions/dashboard-visualization-descriptor.schema.json new file mode 100644 index 0000000000..90f258a7f2 --- /dev/null +++ b/lowcode/schema/definitions/dashboard-visualization-descriptor.schema.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-visualization-descriptor.schema.json", + "title": "DashboardVisualizationDescriptor", + "description": "A single visualization element (number, chart, or list) within a dashboard group", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Unique identifier within the group", + "minLength": 1 + }, + "type": { + "$ref": "dashboard-visualization-type.schema.json" + }, + "title": { + "type": "string", + "description": "Display title for the visualization" + }, + "description": { + "type": "string", + "description": "Optional description text" + }, + "position": { + "$ref": "dashboard-position-descriptor.schema.json" + }, + "filter": { + "$ref": "dashboard-filter-descriptor.schema.json" + }, + "showDescriptionAsTooltip": { + "type": "boolean", + "default": false + }, + "clickToSeeRecords": { + "type": "boolean", + "description": "Allow users to click to see underlying records", + "default": false + }, + "number": { + "$ref": "dashboard-number-descriptor.schema.json" + }, + "chart": { + "$ref": "dashboard-chart-descriptor.schema.json" + }, + "list": { + "$ref": "dashboard-list-descriptor.schema.json" + } + }, + "required": ["name", "type", "title", "position"], + "allOf": [ + { + "if": { "properties": { "type": { "const": "number" } } }, + "then": { "required": ["number"] } + }, + { + "if": { "properties": { "type": { "const": "chart" } } }, + "then": { "required": ["chart"] } + }, + { + "if": { "properties": { "type": { "const": "list" } } }, + "then": { "required": ["list"] } + } + ], + "additionalProperties": false +} diff --git a/lowcode/schema/definitions/dashboard-visualization-type.schema.json b/lowcode/schema/definitions/dashboard-visualization-type.schema.json new file mode 100644 index 0000000000..ea316146ca --- /dev/null +++ b/lowcode/schema/definitions/dashboard-visualization-type.schema.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "dashboard-visualization-type.schema.json", + "title": "DashboardVisualizationType", + "description": "The type of dashboard visualization", + "type": "string", + "enum": ["number", "chart", "list"] +} diff --git a/lowcode/schema/definitions/page-descriptor.schema.json b/lowcode/schema/definitions/page-descriptor.schema.json index b328dbe073..7301334099 100644 --- a/lowcode/schema/definitions/page-descriptor.schema.json +++ b/lowcode/schema/definitions/page-descriptor.schema.json @@ -61,6 +61,9 @@ "enum": ["modal", "page"], "description": "How to display the edit form", "default": "modal" + }, + "dashboard": { + "$ref": "dashboard-descriptor.schema.json" } }, "required": ["name", "title", "type", "entityName"], @@ -80,6 +83,14 @@ "then": { "required": ["formName"] } + }, + { + "if": { + "properties": { "type": { "const": "dashboard" } } + }, + "then": { + "required": ["dashboard"] + } } ], "additionalProperties": false diff --git a/lowcode/schema/definitions/page-type.schema.json b/lowcode/schema/definitions/page-type.schema.json index 8a185619fe..e6f99465ac 100644 --- a/lowcode/schema/definitions/page-type.schema.json +++ b/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", "form"] + "enum": ["dataGrid", "kanban", "calendar", "form", "dashboard"] }