diff --git a/docs/01-builder-fields.md b/docs/01-builder-fields.md index 786b58a..6c90046 100644 --- a/docs/01-builder-fields.md +++ b/docs/01-builder-fields.md @@ -500,3 +500,4 @@ Valores comunes: `fade-up`, `fade-down`, `fade-left`, `fade-right`, `zoom-in`, ` 8. Checkbox guarda `1` o `0` (número), nunca `true`/`false`. 9. Evita Tailwind arbitrary-value en `index-base.tpl` — muévelos a `style.css`. 10. `script.js` y `style.css` son estáticos: NO uses sintaxis Twig dentro. Pasa valores dinámicos vía `data-*`. +11. Si el módulo lista registros de una tabla del CMS (`c-for` sobre ella, o su `hook.php` la consulta), declara esa tabla con `update_module_metadata({ cmsTables: [...] })`. No es un `data-field-*`: no se deduce del HTML, hay que declararla. Ver `03-modules-and-sections.md`. diff --git a/docs/03-modules-and-sections.md b/docs/03-modules-and-sections.md index 9eaa997..3b59cd5 100644 --- a/docs/03-modules-and-sections.md +++ b/docs/03-modules-and-sections.md @@ -28,6 +28,7 @@ Componentes visuales reutilizables. Viven en `template/estandar/modulos/` con lógica del módulo, **nunca** PHP. @@ -203,6 +204,32 @@ Acceso en Twig: Las variables son **propiedades del objeto iterado**, no variables sueltas. +## `cmsTables` — qué tablas del CMS muestra el módulo + +Un módulo puede pintar contenido que NO vive en sus variables: un listado de noticias, una parrilla de productos, un carrusel del blog. Esos registros están en tablas del CMS, y `cmsTables` es donde el módulo declara cuáles. + +```json +{ "label": "Listado de noticias", "cmsTables": ["noticias"] } +``` + +**No confundir con `tables`**, que también está en el `builder.json` y se parece demasiado: + +| Clave | Qué es | Quién la pone | +|-------|--------|---------------| +| `tables` | Dónde se guardan los VALORES de las variables del módulo. Siempre `["builder_custom"]` | El compilador. No la toques | +| `cmsTables` | Qué contenido MUESTRA el módulo | Una persona desde el editor, o tú con `update_module_metadata` | + +Para qué sirve: el editor pinta un acceso directo al CMS de cada tabla declarada desde cualquier página que incluya el módulo, para que quien edita esa página llegue al contenido sin buscarlo. + +Cuándo declararla: +- **Sí**: el módulo hace `c-for` sobre registros de una tabla, o su `hook.php` los consulta. +- **No**: el módulo solo muestra sus propias variables (un banner con título e imagen). Deja la lista vacía. + +Cómo usarla tú: +- Al crear un módulo que lista contenido, decláralas: `update_module_metadata({ module, cmsTables: ["noticias"] })`. +- Al recibirlas en `get_module_config_vars`, te dicen **dónde está de verdad el contenido visible**. Si el usuario pide cambiar lo que muestra un listado de noticias, los registros están en `noticias` — no en las variables del módulo. Ve a esa tabla con `list_table_records` / `create_or_update_record`. +- Pasar `cmsTables` reemplaza la lista entera: incluye las que quieras conservar. `[]` la vacía. + ## Traducir las variables de un módulo Los valores textuales de las variables de un módulo (títulos, descripciones, wysiwyg, etc.) NO se guardan en la fila de la página, sino en la tabla `builder_custom`. Por eso una traducción de módulo apunta siempre a `builder_custom`, no a `apartados` ni a la tabla de la página. diff --git a/docs/09-mcp-tools-reference.md b/docs/09-mcp-tools-reference.md index f747305..2e5f03f 100644 --- a/docs/09-mcp-tools-reference.md +++ b/docs/09-mcp-tools-reference.md @@ -37,6 +37,7 @@ Reglas: | `check_module_usage` | Lista páginas que usan el módulo | **OBLIGATORIO antes de `delete_module`** | | `delete_module` | Elimina la carpeta del módulo | Destructivo. Si `inUse=true`, deniega — el usuario debe quitarlo de las páginas primero | | `set_module_example_data` | Define datos de ejemplo para preview en el editor | Pasar valores para TODAS las variables del schema | +| `update_module_metadata` | Edita metadata del `builder.json` | `label`, `description`, `onlyAdminModule`, `MJMLModule`, `cmsTables`. NO renombra el módulo. Rechaza los módulos de layout (`custom-header/footer[-twig]`) | ### Registros (records) @@ -51,7 +52,7 @@ Reglas: | `remove_module_from_record` | Quita módulo de la página | Por `sectionId` (preferido) o `modulePosition` | | `reorder_module` | Mueve módulo a otra posición | `fromPosition` → `toPosition` | | `toggle_module_visibility` | Muestra/oculta sin borrar | Por `sectionId` | -| `get_module_config_vars` | Lee valores actuales de las variables | Por `tableName` + `recordNum` + `sectionId` | +| `get_module_config_vars` | Lee valores actuales de las variables | Por `tableName` + `recordNum` + `sectionId`. Devuelve además `cmsTables`: las tablas cuyo contenido MUESTRA el módulo (ahí están sus registros, no en las vars) | | `set_module_config_vars` | Escribe variables del módulo | Devuelve `uploadFields` con `recordNum`+`fieldName` listos para subir imágenes | ### Tablas y campos (schema) diff --git a/mcp-server/tools/modules/updateMetadata.js b/mcp-server/tools/modules/updateMetadata.js index e3a9495..890e852 100644 --- a/mcp-server/tools/modules/updateMetadata.js +++ b/mcp-server/tools/modules/updateMetadata.js @@ -7,22 +7,27 @@ import { getCurrentProjectInfo } from "../files/helpers.js"; // Tool: update_module_metadata // Edita la metadata de builder.json de un modulo (label, description, -// onlyAdminModule, MJMLModule) delegando en /api/modules/update-metadata. -// El id/carpeta del modulo NO se puede renombrar y el endpoint rechaza los -// modulos generados del layout (custom-header/footer[-twig]). +// onlyAdminModule, MJMLModule, cmsTables) delegando en +// /api/modules/update-metadata. El id/carpeta del modulo NO se puede renombrar +// y el endpoint rechaza los modulos generados del layout +// (custom-header/footer[-twig]). // Claves editables del builder.json. Se envian solo las que llegan definidas, // de modo que el endpoint hace un merge parcial y no pisa el resto. -const EDITABLE_KEYS = ["label", "description", "onlyAdminModule", "MJMLModule"]; +const EDITABLE_KEYS = ["label", "description", "onlyAdminModule", "MJMLModule", "cmsTables"]; export function registerUpdateModuleMetadataTool(server) { server.tool( "update_module_metadata", - `Edit a module's metadata in its builder.json: 'label' (display name shown in the visual builder), 'description' (short help text for editors), 'onlyAdminModule' (true = the module is only visible to admin users in the builder), 'MJMLModule' (true = the module is an email/MJML module). + `Edit a module's metadata in its builder.json: 'label' (display name shown in the visual builder), 'description' (short help text for editors), 'onlyAdminModule' (true = the module is only visible to admin users in the builder), 'MJMLModule' (true = the module is an email/MJML module), 'cmsTables' (CMS tables whose content this module displays). + +Use 'cmsTables' when the module renders records from a CMS table — a news list, a product grid, a blog carousel. Declare the tables it reads (e.g. ["noticias"]). The editor then shows a direct link to each of those tables from any page that includes the module, so whoever edits that page can reach the content without hunting for it. A module that only shows its own variables (a banner with a title and an image) needs no cmsTables. + +Do NOT confuse 'cmsTables' with the 'tables' key of builder.json: 'tables' is where the module's VARIABLE VALUES are stored (always builder_custom) and is managed by the compiler. 'cmsTables' is what content the module DISPLAYS, and is chosen by a human or by you. The module id (its folder name under template/estandar/modulos/) CANNOT be renamed with this tool — there is no rename option at all. Only the fields above change; everything else in builder.json is preserved. -At least one of label, description, onlyAdminModule or MJMLModule is required. Fields you omit are left untouched. +At least one of label, description, onlyAdminModule, MJMLModule or cmsTables is required. Fields you omit are left untouched. Passing cmsTables replaces the whole list, so include the tables you want to keep; pass [] to clear it. Not applicable to the generated layout modules (custom-header, custom-footer, custom-header-twig, custom-footer-twig): those are artifacts of the global layout and the request will be rejected — use set_layout_field for them.`, withAuthParams({ @@ -31,11 +36,12 @@ Not applicable to the generated layout modules (custom-header, custom-footer, cu description: z.string().optional().describe("Short description shown to editors in the builder"), onlyAdminModule: z.boolean().optional().describe("If true, the module is only visible to admin users in the builder"), MJMLModule: z.boolean().optional().describe("If true, the module is treated as an email (MJML) module"), + cmsTables: z.array(z.string()).optional().describe("CMS tables whose records this module displays, e.g. [\"noticias\"]. Replaces the whole list; [] clears it. Only real tables of the project — they become direct links to the CMS."), }), { readOnlyHint: false, destructiveHint: false }, - withAuth(async ({ module, label, description, onlyAdminModule, MJMLModule }, _extra) => { + withAuth(async ({ module, label, description, onlyAdminModule, MJMLModule, cmsTables }, _extra) => { try { - const provided = { label, description, onlyAdminModule, MJMLModule }; + const provided = { label, description, onlyAdminModule, MJMLModule, cmsTables }; // Validacion temprana: sin ninguna clave editable no tiene // sentido llamar al endpoint. Ojo con los booleanos false — diff --git a/mcp-server/tools/records/getModuleConfigVars.js b/mcp-server/tools/records/getModuleConfigVars.js index 0da2723..57e89da 100644 --- a/mcp-server/tools/records/getModuleConfigVars.js +++ b/mcp-server/tools/records/getModuleConfigVars.js @@ -22,6 +22,7 @@ export function registerGetModuleConfigVarsTool(server) { - vars: resolved values (text, HTML, etc.) for simple vars and arrays for multi/repeater vars - varsMeta: per-var physical location { tableName: 'builder_custom', recordNum, fieldName, type }. USE THIS to know exactly which row + column to update with create_or_update_record. The variable's display name (e.g. 'titulo') is NOT the same as the physical column name (e.g. 'title2'). Uploads inside a 'multi' var carry their labels in subFields..infoLabels. - uploadFields: per-var upload location for upload_record_image / replace_record_image / set_upload_info. Each entry includes infoLabels when the module defines them (array; position 0 = info1). +- cmsTables: CMS tables whose records this module DISPLAYS (e.g. ["noticias"]), or [] if it only shows its own variables. This is where the module's visible content really lives: if the user asks to change what a news-list module shows, the records are in those tables, NOT in the module's vars. Use list_table_records / create_or_update_record against them. Empty list means nothing to look up elsewhere. - moduleId, sectionId Required params: