AgentSkillsCN

nova-forms

创建并编辑NovaDB表单(typeForm)——通过UI布局定义,控制在编辑对象时显示哪些属性。当用户想要管理表单、增删字段、重新排序表单内容、设置条件可见性,或将表单与对象类型关联时,可使用此功能。

SKILL.md
--- frontmatter
name: nova-forms
description: Creates and edits NovaDB forms (typeForm) — UI layout definitions that control which attributes appear when editing objects. Use when the user wants to manage forms, add/remove fields, reorder form content, set up conditional visibility, or link forms to object types.

You have access to the NovaDB MCP server tools. This skill guides you through creating, editing, and managing forms via the CMS API.

Form Architecture

code
Object Type (root, ID 0)
├─ objectTypeCreateForm (5001) ──→ 1 Form     (shown when creating new objects)
└─ objectTypeDetailForms (5002) ──→ [Form, ...] (shown as tabs in detail view)

Form Definition (typeForm, ID 50)
├─ formContent (5053) ──→ Individual Attr Def entries (one per field, ordered by sortReverse)
├─ formConditionAttribute (5054) ──→ 1 Attr Def  (form visible only when this attr has a value)
├─ formConditionRefs (5055) ──→ [Condition, ...]  (all conditions must pass)
└─ formIsSingleEditor (5056) ──→ Boolean           (single code editor mode)
  • Each object type references one create form and one or more detail forms (tabs).
  • Each form contains an ordered list of attribute definitions (formContent) controlling which fields appear and in what order.
  • Conditional visibility: A form can be hidden based on formConditionAttribute (show only when a specific attribute has a value) and/or formConditionRefs (condition objects, all must pass).
  • Single editor mode (formIsSingleEditor): When true, renders a single code editor (CSS/JS/HTML) instead of individual fields.

CMS API Value Format

The CMS API uses normalized value tuples:

json
{ "values": [{ "attribute": 1000, "language": 201, "variant": 0, "value": "Example" }] }

Languages: 201=en-US, 202=de-DE. Use language: 0 for language-independent attributes.

Form Attribute Reference

IDapiIdentifierData TypeNotes
5053formContentObjRef (multi)Ordered list of attribute definitions to display
5054formConditionAttributeObjRefForm visible only when this attribute has a value
5055formConditionRefsObjRef (multi)Condition objects (types 170-176), all must pass
5056formIsSingleEditorBooleanSingle code editor mode (CSS/JS/HTML)

Object Type Form Attributes

IDapiIdentifierData TypeNotes
5001objectTypeCreateFormObjRefForm shown when creating new objects (single)
5002objectTypeDetailFormsObjRef (multi)Forms shown as tabs in detail view (array)

Workflows

Inspect Existing Forms

List all forms in a branch:

code
novadb_cms_get_typed_objects(branch="branchDefault", type="typeForm")

Get a form with its content:

code
# 1. Fetch the form
novadb_cms_get_object(branch, id=<formId>, inherited=true)
# 2. Find formContent (attribute 5053) — individual value entries, each with a single attribute def ID
# 3. Resolve the attribute definitions
novadb_cms_get_objects(branch, ids="<attrDefId1>,<attrDefId2>,...")

Get an object type's forms:

code
# 1. Fetch the type
novadb_cms_get_object(branch, id=<typeId>, inherited=true)
# 2. Find objectTypeCreateForm (5001) and objectTypeDetailForms (5002) values
# 3. Resolve the form references
novadb_cms_get_objects(branch, ids="<createFormId>,<detailFormId1>,...")

Create a New Form

json
novadb_cms_create_objects(branch="branchDefault", objects=[{
  "meta": { "typeRef": 50, "apiIdentifier": "myFormName" },
  "values": [
    { "attribute": 1000, "language": 201, "value": "My Form (EN)" },
    { "attribute": 1000, "language": 202, "value": "Mein Formular (DE)" },
    { "attribute": 5053, "value": <attrDefId1> },
    { "attribute": 5053, "value": <attrDefId2>, "sortReverse": 1 },
    { "attribute": 5053, "value": <attrDefId3>, "sortReverse": 2 },
    { "attribute": 5056, "value": false }
  ]
}])

Each formContent (5053) entry is a separate value tuple with a single attribute reference. Use sortReverse (0, 1, 2, ...) to control field order. Do not pass an array — it causes HTTP 400.

Add a Form to an Object Type

Important: objectTypeDetailForms (5002) is an array. Always read existing forms first, then append.

code
# 1. Read existing detail forms
novadb_cms_get_object(branch, id=<typeId>, inherited=true)
# Find the value for attribute 5002, e.g. [2098001, 2098002]

# 2. Append the new form
novadb_cms_update_objects(branch, objects=[{
  "meta": { "id": <typeId>, "typeRef": 0 },
  "values": [
    { "attribute": 5002, "value": [2098001, 2098002, <newFormId>] }
  ]
}])

For the create form (5001), it's a single reference:

json
novadb_cms_update_objects(branch, objects=[{
  "meta": { "id": <typeId>, "typeRef": 0 },
  "values": [
    { "attribute": 5001, "value": <createFormId> }
  ]
}])

Edit Form Content (Reorder/Add/Remove Fields)

To edit form content, read the current entries, then rebuild all formContent (5053) entries with the desired order:

code
# 1. Get current form content
novadb_cms_get_object(branch, id=<formId>, inherited=true)
# Find all value entries for attribute 5053 — each is a separate entry with a single attribute ref

# 2. Rebuild with new order/additions/removals (all entries for 5053 must be sent)
novadb_cms_update_objects(branch, objects=[{
  "meta": { "id": <formId>, "typeRef": 50 },
  "values": [
    { "attribute": 5053, "value": 2098502 },
    { "attribute": 5053, "value": 1000, "sortReverse": 1 },
    { "attribute": 5053, "value": 2098501, "sortReverse": 2 },
    { "attribute": 5053, "value": <newAttrId>, "sortReverse": 3 }
  ]
}])

Conditional Forms

Add a condition so a form tab only appears when a specific attribute has a value:

json
novadb_cms_update_objects(branch, objects=[{
  "meta": { "id": <formId>, "typeRef": 50 },
  "values": [
    { "attribute": 5054, "value": <conditionAttrId> }
  ]
}])

For more complex conditions, create condition objects and reference them:

json
novadb_cms_update_objects(branch, objects=[{
  "meta": { "id": <formId>, "typeRef": 50 },
  "values": [
    { "attribute": 5055, "value": [<conditionObjId1>, <conditionObjId2>] }
  ]
}])

Create Condition Objects

To create a typed condition and attach it to a form:

code
# 1. Discover the condition type's schema (e.g., String Condition)
novadb_cms_get_object(branch, id=173, inherited=true)
# Inspect its forms to understand which attributes it expects

# 2. Create the condition object
novadb_cms_create_objects(branch, objects=[{
  "meta": { "typeRef": 173 },
  "values": [
    { "attribute": 1000, "language": 201, "value": "Region is EMEA" },
    { "attribute": 1000, "language": 202, "value": "Region ist EMEA" },
    # ... condition-specific attributes (varies by type)
  ]
}])
# Returns the new condition object ID

# 3. Attach to a form via formConditionRefs (5055)
# First read the form to get existing conditions
novadb_cms_get_object(branch, id=<formId>, inherited=true)
# Then update with ALL condition refs (existing + new)
novadb_cms_update_objects(branch, objects=[{
  "meta": { "id": <formId>, "typeRef": 50 },
  "values": [
    { "attribute": 5055, "value": [<existingCondId>, <newCondId>] }
  ]
}])

Multi-Tab Management

Manage the detail form tabs of an object type (objectTypeDetailForms / 5002):

List all tabs for a type:

code
# 1. Fetch the type with inherited values
novadb_cms_get_object(branch, id=<typeId>, inherited=true)
# 2. Find all values for attribute 5002 — these are the detail form IDs
# 3. Resolve the form references to see names
novadb_cms_get_objects(branch, ids="<formId1>,<formId2>,...")

Reorder tabs:

code
# Send the full array with the new order
novadb_cms_update_objects(branch, objects=[{
  "meta": { "id": <typeId>, "typeRef": 0 },
  "values": [
    { "attribute": 5002, "value": [<formId3>, <formId1>, <formId2>] }
  ]
}])

Remove a tab:

code
# Send the full array without the removed form
novadb_cms_update_objects(branch, objects=[{
  "meta": { "id": <typeId>, "typeRef": 0 },
  "values": [
    { "attribute": 5002, "value": [<formId1>, <formId3>] }
  ]
}])

Clone a Form

Duplicate an existing form with all its fields:

code
# 1. Read the source form
novadb_cms_get_object(branch, id=<sourceFormId>, inherited=true)
# 2. Extract all formContent (5053) entries and other attributes

# 3. Create the new form with the same field list
novadb_cms_create_objects(branch, objects=[{
  "meta": { "typeRef": 50, "apiIdentifier": "clonedFormName" },
  "values": [
    { "attribute": 1000, "language": 201, "value": "Cloned Form (EN)" },
    { "attribute": 1000, "language": 202, "value": "Kopiertes Formular (DE)" },
    # Copy all 5053 entries from the source form with their sortReverse values
    { "attribute": 5053, "value": <attrDefId1> },
    { "attribute": 5053, "value": <attrDefId2>, "sortReverse": 1 },
    { "attribute": 5053, "value": <attrDefId3>, "sortReverse": 2 },
    # Optionally copy condition attributes (5054, 5055) and single editor mode (5056)
  ]
}])

Condition Types Reference

IDapiIdentifierName
170typeScriptedConditionScripted Condition
171typeObjectReferenceValueConditionObject Reference Condition
172typeUserNameValueConditionUser Name Condition
173typeStringValueConditionString Condition
174typeNumericValueConditionNumeric Condition
175typeTimestampValueConditionTimestamp Condition
176typeBooleanValueConditionBoolean Condition

Gotchas

  • objectTypeDetailForms (5002) is an array — Always read-then-append. Never overwrite with just a single new form ID, or you'll remove all existing tabs.
  • formContent (5053) uses individual entries, NOT arrays — Each attribute reference must be a separate value entry with "attribute": 5053 and a single "value". Use sortReverse (0, 1, 2, ...) to control field order. Passing an array like [id1, id2] causes HTTP 400.
  • apiIdentifier is immutable — Set in meta.apiIdentifier at creation time. Cannot be changed later (HTTP 403).
  • attributeName (1000) is language-dependent — Provide one value per language (201=en-US, 202=de-DE).
  • CMS uses numeric attribute IDs, not apiIdentifier strings.
  • Use inherited=true when reading objects to see all values including inherited ones.