From cc0b6c11f09bc465115628f61c35bd4ecdf3560c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 26 Aug 2026 16:56:04 +0300 Subject: [PATCH] docs(low-code): document 10.7 feature workflows --- docs/en/docs-nav.json | 12 ++ docs/en/low-code/custom-endpoints.md | 11 +- docs/en/low-code/data-import.md | 116 +++++++++++++ docs/en/low-code/data-modeling.md | 248 +++++++++++++++++++++++++++ docs/en/low-code/designer.md | 24 ++- docs/en/low-code/foreign-access.md | 7 + docs/en/low-code/health.md | 7 + docs/en/low-code/index.md | 13 +- docs/en/low-code/mcp.md | 2 + docs/en/low-code/model-history.md | 111 ++++++++++++ docs/en/low-code/model-json.md | 19 +- docs/en/low-code/react-runtime.md | 13 ++ 12 files changed, 573 insertions(+), 10 deletions(-) create mode 100644 docs/en/low-code/data-import.md create mode 100644 docs/en/low-code/data-modeling.md create mode 100644 docs/en/low-code/model-history.md diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 567ea6f387..0b79368bae 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -2153,6 +2153,18 @@ "text": "Low-Code Designer", "path": "low-code/designer.md" }, + { + "text": "Data Modeling and Page Behavior", + "path": "low-code/data-modeling.md" + }, + { + "text": "Data Import", + "path": "low-code/data-import.md" + }, + { + "text": "Model History and Recovery", + "path": "low-code/model-history.md" + }, { "text": "Calculated and Rollup Properties", "path": "low-code/formula-properties.md" diff --git a/docs/en/low-code/custom-endpoints.md b/docs/en/low-code/custom-endpoints.md index c75f92461f..c3fe842f10 100644 --- a/docs/en/low-code/custom-endpoints.md +++ b/docs/en/low-code/custom-endpoints.md @@ -41,9 +41,16 @@ Custom endpoints are defined in JSON descriptor files or through the Low-Code De | `javascript` | string | Required | JavaScript handler code | | `description` | string | null | Optional designer/documentation text | | `requireAuthentication` | bool | `true` | Whether the caller must be authenticated | +| `useResourceAuthorization` | bool | `false` | Whether execution is granted per endpoint name through ABP resource permissions | | `requiredPermissions` | string[] | null | Permission names required to call the endpoint | -Permission checks require an authorized user even when `requireAuthentication` is set to `false`. Keep endpoints authenticated by default and use `requireAuthentication: false` only for intentionally public APIs without `requiredPermissions`. +Authorization is resolved in this order: + +1. When `requiredPermissions` contains values, every named permission is required. +2. Otherwise, `useResourceAuthorization: true` requires the endpoint execute resource permission scoped to the endpoint name, with the global Low-Code endpoint permission as fallback. +3. Otherwise, `requireAuthentication` selects authenticated or public access. + +Permission checks require an authorized user even when `requireAuthentication` is set to `false`. Keep endpoints authenticated by default and use `requireAuthentication: false` only for intentionally public APIs without named or resource authorization. ## Route and Request Data @@ -223,7 +230,7 @@ Default blocked headers also include hop-by-hop headers such as `Connection`, `T ## Security Notes * Prefer authenticated endpoints with explicit `requiredPermissions`. -* Treat endpoints with `requireAuthentication: false` and no `requiredPermissions` as public API surface. +* Treat endpoints with `requireAuthentication: false`, no `requiredPermissions`, and `useResourceAuthorization: false` as public API surface. * Keep endpoint scripts small and focused. * Validate route, query, and body input before using it. * Use `take()` for list queries. diff --git a/docs/en/low-code/data-import.md b/docs/en/low-code/data-import.md new file mode 100644 index 0000000000..de4120749a --- /dev/null +++ b/docs/en/low-code/data-import.md @@ -0,0 +1,116 @@ +```json +//[doc-seo] +{ + "Description": "Import Excel or CSV data into ABP Low-Code pages with guided mapping, append or merge behavior, foreign-key matching, remote files, and invalid-row downloads." +} +``` + +# Data Import + +The React Low-Code runtime can import Excel and CSV files into a dynamic page. The import wizard previews the file in the browser, maps source columns to entity properties, reviews the operation, and sends the file plus the confirmed mapping to the backend. + +Import is enabled by default for pages and can be disabled per page with `importEnabled: false`. + +## Import Workflow + +1. Open a dynamic data page and select **Import**. +2. Upload an Excel or CSV file, or download a sample file for the page. +3. Review the detected columns and map each source column to one target property. +4. Choose **Append** or **Merge**. +5. Review required fields, conversions, relation matching, and file/image sources. +6. Run the import and download the invalid-row file if any rows fail. + +Column names are matched automatically when a source header equals a property name or display label after normalizing spaces, underscores, hyphens, dots, and letter casing. Review every automatic mapping before import. + +The wizard reports mappings as compatible, convertible, warning, or incompatible. The backend remains authoritative and validates each converted value, entity rule, and mapped property. + +## Append and Merge + +**Append** creates a new record for every valid row. The `Id` column is not accepted in append mode. + +**Merge** uses one mapped property as the match key: + +* A matching record is updated. +* A non-matching row creates a record. +* The match property must be included in the column mapping. +* When the selected property can match multiple records, choose either **Error** or **Use first**. **Use first** also requires a deterministic sort property and direction. + +Use an ID or unique business key whenever possible. A non-unique merge key makes the result depend on the selected multiple-match rule. + +## Foreign-Key Mapping + +A foreign-key column can contain the related record ID or another allowed match property such as a unique username or code. The wizard exposes the supported related-entity match fields for that property. + +If a foreign-key lookup can return multiple records, the same rules apply: + +* **Error** rejects the row. +* **Use first** requires an explicit sort property and direction. + +This decision is per mapped foreign-key column, independent of the main append or merge mode. + +## Value Extraction + +Use a source-value regular expression when a cell contains extra text around the value that should be imported. The expression must contain a named `value` capture group: + +```text +Order: (?[A-Z]+-\d+) +``` + +The server compiles and executes the expression with bounded input, evaluation count, and elapsed-time budgets. A structurally valid client preview does not replace server validation. + +## File and Image URLs + +File and image properties can import remote files referenced by spreadsheet text. Source modes are: + +| Mode | Use it when | +|------|-------------| +| `auto` | The runtime should detect a supported URL shape | +| `fullUrl` | The whole cell is the URL | +| `fileNameAndUrl` | The cell contains a file name and URL | +| `extractUrlFromText` | The URL is embedded in surrounding text | +| `customRegex` | A custom expression extracts a named `url` group | + +Remote downloads are performed by the backend, not by the browser. The verified defaults require HTTPS on port `443`, allow only public network destinations, follow at most three redirects, and reject private, link-local, multicast, and loopback destinations. Development loopback HTTP is available only when both the environment is Development and `AllowLoopbackHttpInDevelopment` is enabled. + +Restrict production destinations with `LowCode:Import:RemoteFiles:AllowedHosts` when imports should fetch only from known hosts. Download count, per-file bytes, aggregate bytes, concurrency, redirects, and timeout are all bounded by `LowCode:Import:RemoteFiles` options. + +Remote files are staged before row persistence. A failed row or failed merge does not replace an existing stored file with an incomplete download. + +## Partial Failures + +Import continues after row-scoped validation or conversion failures. The result reports: + +* Total rows +* Succeeded and failed rows +* Created and updated records +* A short-lived invalid-row download token when failures exist + +The invalid-row file contains the original row values plus failure details so the rows can be corrected and imported again. The verified default token lifetime is 600 seconds. + +Failures that make the whole request unsafe, such as an invalid archive, exceeded global file budget, or blocked remote destination, stop the import before normal row processing. + +## Limits and Configuration + +Important verified defaults are: + +| Setting | Default | +|---------|---------| +| `LowCode:Import:MaxRows` | `10000` | +| `LowCode:Import:MaxColumns` | `256` | +| `LowCode:Import:InvalidRowsTokenLifetimeSeconds` | `600` | +| `LowCode:Import:RemoteFiles:Enabled` | `true` | +| `LowCode:Import:RemoteFiles:RequestTimeoutSeconds` | `15` | +| `LowCode:Import:RemoteFiles:MaxConcurrentDownloads` | `4` | +| `LowCode:Import:RemoteFiles:MaxFilesPerImport` | `500` | +| `LowCode:Import:RemoteFiles:MaxFileBytes` | `10485760` | +| `LowCode:Import:RemoteFiles:MaxTotalBytesPerImport` | `104857600` | +| `LowCode:Import:RemoteFiles:AllowedPorts` | `[443]` | + +The options validators reject non-positive, inconsistent, or above-ceiling values. Keep imports page-scoped and use the existing limits instead of accepting arbitrary workbook sizes. + +## See Also + +* [React Runtime](react-runtime.md) +* [Data Modeling and Page Behavior](data-modeling.md) +* [Model Descriptor Files](model-json.md) +* [Foreign Access](foreign-access.md) diff --git a/docs/en/low-code/data-modeling.md b/docs/en/low-code/data-modeling.md new file mode 100644 index 0000000000..073eb680a4 --- /dev/null +++ b/docs/en/low-code/data-modeling.md @@ -0,0 +1,248 @@ +```json +//[doc-seo] +{ + "Description": "Model Low-Code property storage, primitive collections, related fields, presentations, backend filters, and page or relationship permissions." +} +``` + +# Data Modeling and Page Behavior + +The Low-Code Designer can model more than scalar fields and basic CRUD pages. This page covers the data and page features that affect storage, queries, presentation, and authorization. + +## Property Storage + +Scalar properties use one of two storage shapes: + +* `isMappedToDbField: true` maps the property to its own physical column. +* An omitted or `false` `isMappedToDbField` stores the property through the entity's dynamic data mapping. + +By default, dynamic data mapping uses the entity's JSON `Data` column. Applications that need individual columns for those properties can disable JSON data storage while configuring EF Core: + +```csharp +builder.ConfigureDynamicEntities(useJsonDataStorage: false); +``` + +The equivalent module option is `AbpLowCodeEntityFrameworkCoreOptions.UseJsonDataStorage`. Its verified default is `true`. + +Changing the storage mode or `isMappedToDbField` affects the physical schema. Decide the storage strategy before creating production tables, then use the normal migration or runtime schema workflow for later changes. Formulas and rollups are virtual and do not create physical scalar columns. + +Source-model and runtime-model dynamic tables can use separate prefixes: + +```csharp +LowCodeDbProperties.JsonModelTablePrefix = "Src_"; +LowCodeDbProperties.RuntimeTablePrefix = "Runtime_"; +``` + +Configure prefixes before the dynamic model is initialized. Changing a prefix after tables exist requires renaming or migrating those tables. + +## Primitive Collections + +A primitive collection keeps an ordered list of values on one property. Supported element types are `string`, `int`, `long`, `decimal`, `dateTime`, `boolean`, `guid`, `enum`, `date`, `time`, `money`, `file`, and `image`. + +```json +{ + "name": "Tags", + "type": "string", + "collection": { + "maxCount": 25, + "uniqueItems": true, + "storageKey": "b7db3ad2-3452-511b-b9b7-cc11d2db6dcb" + } +} +``` + +Collection rules: + +* `maxCount` is optional, but must be greater than zero when supplied. +* `uniqueItems` is required and controls duplicate-value validation. +* The effective item limit is the lower of `maxCount` and `LowCode:PrimitiveCollections:MaximumItemsPerProperty`. The verified global default is `1000`. +* `storageKey` is a stable internal identity used by the normalized collection table. Let the Designer generate it and do not change it after data exists. +* A collection property cannot also be a foreign key, formula, or rollup. + +Collections are stored in normalized rows rather than inside the owner JSON payload. The React runtime returns them as ordered arrays and uses collection-aware controls for scalar, enum, file, and image values. + +## Related Fields and Self-Relations + +Page columns and filters can follow foreign keys by using dot-separated property paths: + +```json +{ + "columns": [ + { "propertyName": "CustomerId.Name", "label": "Customer" }, + { "propertyName": "CustomerId.CountryId.Name", "label": "Country" } + ], + "filters": [ + { "propertyName": "CustomerId.CountryId.RegionId.Name" } + ] +} +``` + +Only requested related fields are projected into the response. The same paths can be used by page filtering and export, including registered reference entities. + +Self-relations are supported. For example, an employee page can use `ManagerId.ManagerId.Name` to follow the same relation more than once. Every path is still limited by the configured maximum foreign-key depth exposed by the Low-Code query capabilities. + +## Reverse Relationships + +A foreign key defines the schema direction. A page relationship defines how records that point back to the host record are shown and edited: + +```json +{ + "name": "Authors", + "entityName": "Acme.Authors.Author", + "relationships": [ + { + "id": "author-books", + "sourceEntityName": "Acme.Books.Book", + "sourcePropertyName": "AuthorId", + "access": "edit", + "relatedPageMode": "page", + "relatedPageName": "Books", + "createFormMode": "generated", + "editFormMode": "form", + "editFormName": "BookEditForAuthor" + } + ] +} +``` + +`access` can be `none`, `view`, or `edit`. The generated modes build the related page or form from the source entity; the explicit modes reuse named page and form descriptors. + +See [Foreign Access](foreign-access.md) for the runtime APIs and UI behavior used by these relationships. + +## Enum and Boolean Presentation + +Enum values can define reusable display metadata: + +```json +{ + "name": "Acme.Orders.OrderStatus", + "values": [ + { + "name": "Pending", + "value": 10, + "displayName": "Waiting", + "presentation": "badge", + "color": "#F59E0B" + } + ] +} +``` + +Enum presentation supports `text`, `badge`, and `iconOnly`. Pages can override the display name, presentation, color, or icon for one property without changing the shared enum: + +```json +{ + "enumPresentations": [ + { + "propertyName": "Status", + "values": [ + { "value": 10, "displayName": "Awaiting review", "presentation": "badge", "color": "#F59E0B" } + ] + } + ] +} +``` + +Boolean columns support `text`, `checkbox`, `badge`, and `iconOnly`, with separate metadata for `true`, `false`, and `null`: + +```json +{ + "propertyName": "IsActive", + "booleanPresentation": "badge", + "booleanValues": { + "true": { "displayName": "Active", "color": "#16A34A" }, + "false": { "displayName": "Inactive", "color": "#DC2626" }, + "null": { "displayName": "Not set", "color": "#6B7280" } + } +} +``` + +Icons can reference a CSS class, stored blob, data URL, or application path. Runtime-layer writes apply stricter icon validation than source-controlled descriptors. + +## Backend Filters + +Visible page filters are controlled by the user. A backend filter is always applied by the server and is useful for tenant, ownership, role, or workflow scoping. + +```json +{ + "backendFilter": { + "items": [ + { + "propertyName": "Status", + "operator": "equal", + "value": "Active" + }, + { + "logic": "or", + "items": [ + { + "propertyName": "CreatorId", + "operator": "equal", + "valueProvider": "CurrentUserId" + }, + { + "logic": "and", + "propertyName": "AllowedRole", + "operator": "in", + "valueProvider": "CurrentUserRoles" + } + ] + } + ] + } +} +``` + +A filter value can be: + +* Static through `value`. +* Resolved by JavaScript through `javaScript`. +* Resolved by a registered provider through `valueProvider`. + +Built-in providers cover the current user ID, username, first name, surname, email, email verification, phone number, phone verification, roles, and current tenant ID. Applications can register additional typed providers with `AbpLowCodePageBackendFilterOptions`. + +Backend filters are combined with search and user-selected filters. They are not sent as editable client state, so do not replace them with a hidden React filter when the rule is security-sensitive. + +## Page and Relationship Permissions + +Pages use resource-based authorization by default. `permissionConfig` can keep that generated default, require a named permission, allow any authenticated user, or make an operation public: + +```json +{ + "permissionConfig": { + "view": "default", + "create": "Acme.Orders.Create", + "update": "authenticated", + "delete": "Acme.Orders.Delete" + } +} +``` + +For generated reverse relationships, enable separate authorization when child access must not inherit the host page decision: + +```json +{ + "id": "author-books", + "sourceEntityName": "Acme.Books.Book", + "sourcePropertyName": "AuthorId", + "access": "edit", + "useSeparatePermission": true, + "permissionConfig": { + "view": "default", + "create": "Acme.Books.Create", + "update": "Acme.Books.Update", + "delete": "Acme.Books.Delete" + } +} +``` + +When `useSeparatePermission` is `true`, generated relationship permissions are scoped to the host page and relationship ID. Create, update, and delete also require relationship view access. + +## See Also + +* [Low-Code Designer](designer.md) +* [Model Descriptor Files](model-json.md) +* [Calculated and Rollup Properties](formula-properties.md) +* [Data Import](data-import.md) +* [Foreign Access](foreign-access.md) +* [React Runtime](react-runtime.md) diff --git a/docs/en/low-code/designer.md b/docs/en/low-code/designer.md index ad3e9f5aaf..c1ea0fa6cb 100644 --- a/docs/en/low-code/designer.md +++ b/docs/en/low-code/designer.md @@ -40,9 +40,9 @@ The selected layer controls whether the designer can save changes. Read-only lay Use **Data** to define the domain model. -Entities contain properties, display names, display property configuration, inherited audit fields, relations, and optional interceptors. Enums are created once and then used by enum properties. +Entities contain properties, display names, display property configuration, inherited audit fields, relations, primitive collections, and optional interceptors. Enums are created once and then used by enum properties. Enum and boolean values can also carry text, badge, color, and icon presentation metadata. -For virtual fields derived from the current record or related records, see [Calculated and Rollup Properties](formula-properties.md). For the supported scalar formula syntax, see the [Low-Code Expression Language](expression-language.md) reference. +For storage choices, primitive collections, related-field paths, presentations, and backend filters, see [Data Modeling and Page Behavior](data-modeling.md). For virtual fields derived from the current record or related records, see [Calculated and Rollup Properties](formula-properties.md). For the supported scalar formula syntax, see the [Low-Code Expression Language](expression-language.md) reference. ![Entity summary in the designer](images/designer-entity.png) @@ -50,7 +50,7 @@ For virtual fields derived from the current record or related records, see [Calc ### Relations -Relations are driven by foreign key properties. The designer shows direct N to 1 relations and many-to-many relations that are modeled through junction entities. +Relations are driven by foreign key properties. The designer shows direct N to 1 relations, self-relations, and many-to-many relations that are modeled through junction entities. Page columns, filters, and exports can select related fields through foreign-key paths, and reverse page relationships can use generated or named pages/forms with view or edit access. ![Relation overview](images/designer-relations.png) @@ -73,6 +73,8 @@ Pages can define data grid, kanban, calendar, gallery, standalone form, and dash * Field labels and column widths * Default sorting * Filter fields and defaults +* Always-on backend filters with static, JavaScript, or registered-provider values +* Guided Excel and CSV import, including append or merge behavior * File/image export defaults when the page has exportable file fields * Whether file bundle ZIP export is allowed @@ -86,6 +88,8 @@ The **View Fields** section controls what users see in the runtime view. The sep Open **Export Fields > More settings** only when you need custom export details. If **Use default export settings** is enabled, export uses display labels, the view field order, file name output, and file bundle export enabled. Turn it off to customize export labels, assign a separate export order, choose **Default File/Image Output**, or disable **Allow file bundle export**. File/image output controls appear only when the page has file or image fields, and they stay inactive until at least one file/image field is exportable. +Use [Data Import](data-import.md) for the runtime import wizard, column mapping, merge keys, foreign-key matching, remote file/image sources, and invalid-row downloads. + ## Forms Use **Forms** to define create and edit experiences. @@ -147,12 +151,16 @@ Filters are configured per page and rendered by the React runtime. The runtime u The URL query parameter keeps the existing `lcFilters` format, so bookmarked filtered pages continue to work. +Backend filters are different from the visible filters above: the server always combines them with the user's query. Use them for ownership, tenant, role, and workflow scopes that must not be removable from the client. See [Data Modeling and Page Behavior](data-modeling.md#backend-filters). + ## Permissions -Dynamic permissions are generated for entities and pages. Use the **Permissions** section to review names and grant access through the normal ABP permission management UI. +Dynamic permissions are generated for entities, pages, custom endpoints, and optionally individual page relationships. Use the **Permissions** section to review names and grant access through the normal ABP permission management UI. Generated pages and menus are permission-aware. If a user cannot access a page, the runtime does not show the menu item and API calls remain protected by backend authorization. +Pages use resource permissions by default and can override each operation with `default`, `public`, `authenticated`, or a named permission. Generated reverse relationships can enable separate view/create/update/delete authorization. See [Data Modeling and Page Behavior](data-modeling.md#page-and-relationship-permissions). + ## Actions and Scripts Use **Actions** only when descriptor metadata and standard CRUD behavior are not enough. The scripting surface can define custom HTTP endpoints, distributed event handlers, background jobs, and scheduled background workers. Scripts run server-side and use the [Scripting API](scripting-api.md). @@ -165,9 +173,15 @@ Endpoint and event handler editors include **Test JavaScript**. Dry-run executio Use **Health** before shipping changes. It helps catch missing display properties, invalid relation targets, form/page references, script problems, and other model issues that would otherwise surface at runtime. See [Health](health.md) for the selected-layer snapshot scope and the typical problem classes it helps you review. +## History and Recovery + +When **Runtime JSON** is selected, the Designer exposes runtime model undo, redo, history details, comparisons, and save points. History actions are previewed against a concurrency stamp and require explicit confirmation before destructive physical schema changes. + +Entity deletion also uses a reviewed plan. You must resolve dependent relationships and choose whether Designer-managed physical data is kept or deleted. An entity deleted with retained physical data can be restored only from a fresh schema and concurrency preview. See [Model History and Recovery](model-history.md). + ## MCP Integration -The Designer and the low-code MCP surface overlap when the selected layer is **Runtime JSON**, but they are not the same editing surface. The Designer can inspect source-controlled and runtime layers, while [MCP Integration](mcp.md) is a remote HTTP MCP endpoint that is intentionally runtime-only and targets the database-backed model. Use the Designer when you want interactive editing and visual feedback. Use MCP when an authenticated agent or script needs repeatable runtime automation. +The Designer and the low-code MCP surface overlap when the selected layer is **Runtime JSON**, but they are not the same editing surface. The Designer can inspect source-controlled and runtime layers, while [MCP Integration](mcp.md) is a remote HTTP MCP endpoint that is intentionally runtime-only and targets the database-backed model. MCP exposes the same model-management semantics documented in the general Low-Code feature pages; it is not a separate feature model. Use the Designer when you want interactive editing and visual feedback. Use MCP when an authenticated agent or script needs repeatable runtime automation. After MCP-driven changes, reopen the relevant Designer section or review [Health](health.md) before reporting the model as ready. diff --git a/docs/en/low-code/foreign-access.md b/docs/en/low-code/foreign-access.md index 4c6f87e956..44b04e9584 100644 --- a/docs/en/low-code/foreign-access.md +++ b/docs/en/low-code/foreign-access.md @@ -13,6 +13,8 @@ Use the [Low-Code Designer](designer.md) to review relation metadata visually. T Foreign Access controls how related **dynamic entities** can be accessed through foreign key relationships. It determines whether users can view or manage related data directly from the **target entity's** UI. +The foreign key defines the schema relation and default reverse-access level. A page can additionally define a page-specific relationship that selects generated or named related pages/forms and separate authorization. See [Data Modeling and Page Behavior](data-modeling.md#reverse-relationships). + > **Important:** Foreign Access only works between **dynamic entities**. It does not apply to [reference entities](reference-entities.md) because they are read-only and don't have UI pages. ## Access Levels @@ -126,10 +128,14 @@ An **action menu item** appears on the target entity's data grid row (e.g., an " No action menu item is added. The foreign key exists only for data integrity and lookup display. +Self-relations are supported. For example, an `Employee.ManagerId` foreign key can expose direct reports on the employee page, while page columns and filters can follow paths such as `ManagerId.ManagerId.Name` within the configured query-depth limit. + ## Permission Control Foreign access actions respect the **entity permissions** of the source entity (the entity with the foreign key). For example, if a user does not have the `Delete` permission for `Order`, the delete button will not appear in the foreign access modal, even if the access level is `Edit`. +A generated page relationship can set `useSeparatePermission: true`. In that mode, view/create/update/delete access is resolved for the host page and relationship ID instead of relying only on the source entity permission. Relationship create, update, and delete also require relationship view access. + ## How It Works The `ForeignAccessRelation` class stores the relationship metadata: @@ -146,5 +152,6 @@ The `DynamicEntityAppService` checks these relations when building entity action ## See Also * [Model Descriptor Files](model-json.md) +* [Data Modeling and Page Behavior](data-modeling.md) * [Reference Entities](reference-entities.md) * [Attributes & Fluent API](fluent-api.md) diff --git a/docs/en/low-code/health.md b/docs/en/low-code/health.md index dd209d3b7a..03a57de3c7 100644 --- a/docs/en/low-code/health.md +++ b/docs/en/low-code/health.md @@ -41,20 +41,26 @@ Typical problem classes include: * Form layout issues where fields exist but valid placements do not * Permission and page configuration mismatches that would affect runtime visibility or access * Script assets that exist in the model but still need review in the broader context of entities, pages, and permissions +* Orphaned upper-layer descriptors whose lower-layer base was removed or disabled Some of these issues are also enforced by runtime validation and mutation rules. Health gives you a selected-layer review point before users discover the problem in the runtime UI. +When orphan warnings are present, preview the matching inactive-override or disabled-override cleanup before applying it. Cleanup removes only the affected authored deltas from the selected writable layer; review the preview because enabled sibling deltas on the same descriptor are preserved. + ## Use It When Use Health in these moments: * After changing entities, pages, forms, page groups, or permissions in the Designer * After applying MCP-driven runtime mutations +* After undo, redo, save-point restore, retained-entity restore, or override cleanup * Before publishing a set of runtime changes * After copying or importing source-controlled descriptors into an application If you automate low-code changes through [MCP Integration](mcp.md), re-read the health snapshot after apply and treat that review as part of the success criteria. +For runtime history, safe entity deletion, and retained-data restoration, see [Model History and Recovery](model-history.md). + ## Health and Source-Controlled Models Health is not a replacement for source-controlled file validation. @@ -78,6 +84,7 @@ A useful example is form layout drift: a descriptor can still pass `--check-lowc * [Low-Code Designer](designer.md) * [MCP Integration](mcp.md) +* [Model History and Recovery](model-history.md) * [Model Descriptor Files](model-json.md) * [Dashboards](dashboards.md) * [Page Groups](page-groups.md) diff --git a/docs/en/low-code/index.md b/docs/en/low-code/index.md index 11bda617d9..c84d696679 100644 --- a/docs/en/low-code/index.md +++ b/docs/en/low-code/index.md @@ -22,6 +22,7 @@ Use the designer to model entities, enums, properties, relations, pages, forms, * React data grid, kanban, calendar, gallery, form, and dashboard pages * Create and edit forms * Advanced filters +* Guided Excel and CSV import with append or merge behavior * Excel, CSV, and file bundle export No DTO, repository, application service, controller, or React CRUD page is required for the standard flow. @@ -98,13 +99,15 @@ The generated startup project accepts `--model-directory