From f11d47fe53558ed597610e5c074f31f84e427323 Mon Sep 17 00:00:00 2001 From: Santiago Alaniz Date: Thu, 12 Mar 2026 10:48:45 -0300 Subject: [PATCH 01/15] Feature ETP-3486: Color support documentation --- .../how-to-configure-color-system.md | 80 +++++++++++++++++++ .../how-to-configure-color-system.md | 80 +++++++++++++++++++ mkdocs.yml | 3 + 3 files changed, 163 insertions(+) create mode 100644 docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md create mode 100644 docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md diff --git a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md new file mode 100644 index 0000000000..a511396312 --- /dev/null +++ b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -0,0 +1,80 @@ +--- +tags: + - How to + - Color System + - UI + - Extensibility +--- + +# Cómo Configurar el Soporte al Sistema de Colores en la UI + +## Visión General + +El sistema de colores en Etendo permite asignar identificadores visuales (pastillas de color) a registros dentro de una grilla o formulario en Workspace UI, mejorando la experiencia del usuario al destacar información clave. Esta funcionalidad aprovecha el sistema de extensibilidad de Etendo para aplicarse transparentemente sin necesidad de alterar el código base de la interfaz gráfica. + +Un excelente caso de uso (y uno de los más visuales) es aplicarlo a tablas maestras como la **Categoría de Producto (M_Product_Category)** o el **Grupo de Terceros (C_BP_Group)**, ya que estas son muy utilizadas dentro de grillas principales (como la grilla de Productos o la de Terceros/Clientes). + +## ¿Cómo funciona la relación con la otra tabla? + +Para que el color se refleje en la UI, el campo en cuestión en la tabla principal debe apuntar a una tabla maestra a través de una Foreign Key (Referencia **TableDir** o **Table**). + +La implementación actual en Workspace UI y Etendo funciona de manera coordinada gracias a una simbiosis entre la metadata y el frontend de React: + +1. **Inyección de Metadata:** El backend deduce si una tabla hija necesita un color si nota que a lo que apunta contiene una propiedad cuya convención de nombre hace alusión a un color. De ser así, inyecta `colorFieldName` como metadato del campo a nivel del diccionario. +2. **Petición del lado del Front:** Los hooks de obtención de datos (Datasource) en NextJS revisan activamente cada columna definida. Si alguna especifica el metadata `colorFieldName`, el frontend añade al vuelo esa dependencia solicitada como `_extraProperties` en la Request a la API (ej: `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). Esto le fuerza al backend a hacer los JOIN correspondientes y volcar el valor final de color al formato JSON. +3. **Detección Dinámica de Interfaz:** Al momento de renderizar las celdas, el frontend es totalmente agnóstico e independiente: Escanea todas las claves (*keys*) de los registros recuperados y si alguna contiene dinámicamente la palabra `color` (o variables parecidas como `smfcolor`), le asigna automáticamente el componente visual en forma de 'Tag' envuelto, usando el valor hexa recuperado, su prefijo y deducido en un texto con buen contraste. + +Esta arquitectura explícita garantiza eficiencia sin corromper el payload estándar. De igual manera, se actualiza en tiempo real tanto en la **Vista de Formulario (Form View)**, en la **Vista de Grilla Principal (Grid View)**, y a la hora de mutar la información por medio de la **Edición en Línea (Inline Editing)** (donde el cliente vuelve a efectuar una petición del registro pidiendo los `_extraProperties` de colores al guardar exitosamente). + +## Paso a Paso: Configurar el Color en la Categoría de Productos + +A continuación, se detalla el procedimiento exacto para probar e implementar esto utilizando la tabla `M_Product_Category` como ejemplo: + +### 1. Agregar la columna de Color en el Diccionario de Datos + +1. Ingresa a tu entorno de **Etendo ERP Classic** con el rol de **System Administrator** (Administrador del Sistema). +2. Ve a la ventana **Tables and Columns** (Tablas y Columnas). +3. Busca la tabla maestra de interés, en este caso `M_Product_Category` (Categoría de Producto). +4. En la pestaña de *Columns*, crea una nueva columna utilizando tu prefijo de módulo (por ejemplo `EM_CRM_Color`, `EM_SMF_Color` o usar el prefijo de tu módulo de pruebas activo). +5. Configúrala como tipo **String** (cadena de texto) con una longitud de 7 o 10 caracteres; suficientes para guardar en su interior un código hexadecimal (`#FF0000`). + +!!!note "Nota clave" + Gracias a la lógica de resolución entre la metadata y cómo nuestro Frontend evalúa las claves JSON al renderizar ([extractColorContext]), Etendo auto-asignará a la paleta cualquier variable cuya convención incluya el sufijo de forma de la palabra "color". + +### 2. Aplicar la tabla en la BD y mostrar la columna + +Luego de definir la columna en el diccionario de datos, debes materializarla en la base de datos: +1. Aplica los cambios mediante el proceso clásico compilando en consola (ej. `gradlew smartbuild` o reconstruyendo de manera apropiada la base de datos). +2. Ve a la ventana **Window, Tab and Field** (Ventana, Pestaña y Campo) dentro del entorno Etendo. +3. Busca la ventana correspondiente, en este caso **Product Category**. +4. Asegúrate recargar la pestaña o cerciorarte de agregar/crear el registro para la pestaña central de **Field** respecto a esa nueva columna, logrando así que el campo esté listo para ser usado y se visualice en la interfaz del ERP clásico. + +### 3. Prueba de Fuego (¡La Magia Visual!) + +1. Abre la ventana **Product Category** (Categoría de Producto) en Etendo Classic. +2. Selecciona un registro existente, por ejemplo la categoría titulada "Standard" (o directamente sobre la que decidas usar). +3. Escribe un valor hexadecimal identificativo y bien llamativo sobre el nuevo campo de color. Por ejemplo: `#8E44AD` (Un color púrpura oscuro), y guarda finalmente el registro. +4. Ahora, ve a través del frontend de **NextJS de Workspace UI**. +5. Abre la ventana principal respectiva para **Products** (Productos o `M_Product`). +6. En aquella grilla resultante de productos, busca la columna "Categoría de Producto" (`M_Product_Category_ID`). +7. **¡Sorpresa!** Si esta categoría suele verse como un simple texto azul detallando el contenido "Standard", ahora notarás un cambio muy atractivo. Al pedirse los datos, el frontend detectará que hay una configuración para pedir metadatos de ese color (`_extraProperties`), inyectará la petición, la base de datos lo procesará en sus JOINs, Workspace captará la key "color" para esa columna y terminará pintándolo en una hermosa pastilla redondeada color púrpura. + +Lo genial de este diseño es que todo ha quedado **totalmente agnóstico de módulos**. Uno puede crear a la vez módulos independientes para sus clientes, agregando variables idénticas referidas como `EM_Cliente_Color` para tablas de Monedas, Métodos de Pago, Vendedores o Almacenes... e instantáneamente brotarán coloreadas en la grilla y formulario de la UI sin que se requiera programar ni un solo *if* auxiliar del lado visual. + +## Restricciones y Análisis de Alcance + +### ¿A qué campos afecta y permite intervenir? + +La lógica dinámica de inyección de metadata y renderizado de pastillas de color **solo afecta a campos (Fields) definidos como tipo de Referencia Foránea (Foreign Keys / TableDir / Table)** hacia la tabla maestra que ya cuenta con la columna de color configurada. Algunos ejemplos concisos incluyen: + +* `M_Product_Category_ID` apuntando en la tabla de Productos. +* `Priority_ID` reflejándose en la tabla de Tareas. +* `C_Currency_ID` visualizándose en la tabla de Facturas. + +### ¿A qué campos NO afecta o resultan omitidos? + +Su dinámica de control actual **NO afectará o incidirá bajo los elementos a continuación especificables**: + +* Campos de texto estáticos y regulares (Cadenas o *Strings* convencionales). +* Valores Numéricos, Fechas naturales o datos de tipo Booleanos. +* Listas estáticas predefinidas en el sistema (Es decir, menús desplegables del propio tipo *List* codificados de forma fija o *hardcodeada* bajo los dominios de las Listas de Referencia en el diccionario). diff --git a/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md new file mode 100644 index 0000000000..a511396312 --- /dev/null +++ b/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -0,0 +1,80 @@ +--- +tags: + - How to + - Color System + - UI + - Extensibility +--- + +# Cómo Configurar el Soporte al Sistema de Colores en la UI + +## Visión General + +El sistema de colores en Etendo permite asignar identificadores visuales (pastillas de color) a registros dentro de una grilla o formulario en Workspace UI, mejorando la experiencia del usuario al destacar información clave. Esta funcionalidad aprovecha el sistema de extensibilidad de Etendo para aplicarse transparentemente sin necesidad de alterar el código base de la interfaz gráfica. + +Un excelente caso de uso (y uno de los más visuales) es aplicarlo a tablas maestras como la **Categoría de Producto (M_Product_Category)** o el **Grupo de Terceros (C_BP_Group)**, ya que estas son muy utilizadas dentro de grillas principales (como la grilla de Productos o la de Terceros/Clientes). + +## ¿Cómo funciona la relación con la otra tabla? + +Para que el color se refleje en la UI, el campo en cuestión en la tabla principal debe apuntar a una tabla maestra a través de una Foreign Key (Referencia **TableDir** o **Table**). + +La implementación actual en Workspace UI y Etendo funciona de manera coordinada gracias a una simbiosis entre la metadata y el frontend de React: + +1. **Inyección de Metadata:** El backend deduce si una tabla hija necesita un color si nota que a lo que apunta contiene una propiedad cuya convención de nombre hace alusión a un color. De ser así, inyecta `colorFieldName` como metadato del campo a nivel del diccionario. +2. **Petición del lado del Front:** Los hooks de obtención de datos (Datasource) en NextJS revisan activamente cada columna definida. Si alguna especifica el metadata `colorFieldName`, el frontend añade al vuelo esa dependencia solicitada como `_extraProperties` en la Request a la API (ej: `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). Esto le fuerza al backend a hacer los JOIN correspondientes y volcar el valor final de color al formato JSON. +3. **Detección Dinámica de Interfaz:** Al momento de renderizar las celdas, el frontend es totalmente agnóstico e independiente: Escanea todas las claves (*keys*) de los registros recuperados y si alguna contiene dinámicamente la palabra `color` (o variables parecidas como `smfcolor`), le asigna automáticamente el componente visual en forma de 'Tag' envuelto, usando el valor hexa recuperado, su prefijo y deducido en un texto con buen contraste. + +Esta arquitectura explícita garantiza eficiencia sin corromper el payload estándar. De igual manera, se actualiza en tiempo real tanto en la **Vista de Formulario (Form View)**, en la **Vista de Grilla Principal (Grid View)**, y a la hora de mutar la información por medio de la **Edición en Línea (Inline Editing)** (donde el cliente vuelve a efectuar una petición del registro pidiendo los `_extraProperties` de colores al guardar exitosamente). + +## Paso a Paso: Configurar el Color en la Categoría de Productos + +A continuación, se detalla el procedimiento exacto para probar e implementar esto utilizando la tabla `M_Product_Category` como ejemplo: + +### 1. Agregar la columna de Color en el Diccionario de Datos + +1. Ingresa a tu entorno de **Etendo ERP Classic** con el rol de **System Administrator** (Administrador del Sistema). +2. Ve a la ventana **Tables and Columns** (Tablas y Columnas). +3. Busca la tabla maestra de interés, en este caso `M_Product_Category` (Categoría de Producto). +4. En la pestaña de *Columns*, crea una nueva columna utilizando tu prefijo de módulo (por ejemplo `EM_CRM_Color`, `EM_SMF_Color` o usar el prefijo de tu módulo de pruebas activo). +5. Configúrala como tipo **String** (cadena de texto) con una longitud de 7 o 10 caracteres; suficientes para guardar en su interior un código hexadecimal (`#FF0000`). + +!!!note "Nota clave" + Gracias a la lógica de resolución entre la metadata y cómo nuestro Frontend evalúa las claves JSON al renderizar ([extractColorContext]), Etendo auto-asignará a la paleta cualquier variable cuya convención incluya el sufijo de forma de la palabra "color". + +### 2. Aplicar la tabla en la BD y mostrar la columna + +Luego de definir la columna en el diccionario de datos, debes materializarla en la base de datos: +1. Aplica los cambios mediante el proceso clásico compilando en consola (ej. `gradlew smartbuild` o reconstruyendo de manera apropiada la base de datos). +2. Ve a la ventana **Window, Tab and Field** (Ventana, Pestaña y Campo) dentro del entorno Etendo. +3. Busca la ventana correspondiente, en este caso **Product Category**. +4. Asegúrate recargar la pestaña o cerciorarte de agregar/crear el registro para la pestaña central de **Field** respecto a esa nueva columna, logrando así que el campo esté listo para ser usado y se visualice en la interfaz del ERP clásico. + +### 3. Prueba de Fuego (¡La Magia Visual!) + +1. Abre la ventana **Product Category** (Categoría de Producto) en Etendo Classic. +2. Selecciona un registro existente, por ejemplo la categoría titulada "Standard" (o directamente sobre la que decidas usar). +3. Escribe un valor hexadecimal identificativo y bien llamativo sobre el nuevo campo de color. Por ejemplo: `#8E44AD` (Un color púrpura oscuro), y guarda finalmente el registro. +4. Ahora, ve a través del frontend de **NextJS de Workspace UI**. +5. Abre la ventana principal respectiva para **Products** (Productos o `M_Product`). +6. En aquella grilla resultante de productos, busca la columna "Categoría de Producto" (`M_Product_Category_ID`). +7. **¡Sorpresa!** Si esta categoría suele verse como un simple texto azul detallando el contenido "Standard", ahora notarás un cambio muy atractivo. Al pedirse los datos, el frontend detectará que hay una configuración para pedir metadatos de ese color (`_extraProperties`), inyectará la petición, la base de datos lo procesará en sus JOINs, Workspace captará la key "color" para esa columna y terminará pintándolo en una hermosa pastilla redondeada color púrpura. + +Lo genial de este diseño es que todo ha quedado **totalmente agnóstico de módulos**. Uno puede crear a la vez módulos independientes para sus clientes, agregando variables idénticas referidas como `EM_Cliente_Color` para tablas de Monedas, Métodos de Pago, Vendedores o Almacenes... e instantáneamente brotarán coloreadas en la grilla y formulario de la UI sin que se requiera programar ni un solo *if* auxiliar del lado visual. + +## Restricciones y Análisis de Alcance + +### ¿A qué campos afecta y permite intervenir? + +La lógica dinámica de inyección de metadata y renderizado de pastillas de color **solo afecta a campos (Fields) definidos como tipo de Referencia Foránea (Foreign Keys / TableDir / Table)** hacia la tabla maestra que ya cuenta con la columna de color configurada. Algunos ejemplos concisos incluyen: + +* `M_Product_Category_ID` apuntando en la tabla de Productos. +* `Priority_ID` reflejándose en la tabla de Tareas. +* `C_Currency_ID` visualizándose en la tabla de Facturas. + +### ¿A qué campos NO afecta o resultan omitidos? + +Su dinámica de control actual **NO afectará o incidirá bajo los elementos a continuación especificables**: + +* Campos de texto estáticos y regulares (Cadenas o *Strings* convencionales). +* Valores Numéricos, Fechas naturales o datos de tipo Booleanos. +* Listas estáticas predefinidas en el sistema (Es decir, menús desplegables del propio tipo *List* codificados de forma fija o *hardcodeada* bajo los dominios de las Listas de Referencia en el diccionario). diff --git a/mkdocs.yml b/mkdocs.yml index 3b7300ddf3..1353a06741 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -302,6 +302,7 @@ plugins: - SQL Expert: user-guide/etendo-copilot/bundles/sql-expert.md - New UI: - User Interface Improvements: user-guide/new-ui/ui-improvements.md + - How to Configure Color System Support: user-guide/new-ui/how-to-guides/how-to-configure-color-system.md - Developer Guide: - Overview: developer-guide/overview.md @@ -723,6 +724,7 @@ plugins: How to Change Fonts in Etendo Reports: Cómo Cambiar Fuentes en Informes de Etendo How to Change the Size of a Column: Cómo Cambiar el Tamaño de una Columna How to Configure API Tokens: Cómo Configurar Tokens de API + How to Configure Color System Support: Cómo Configurar el Soporte al Sistema de Colores How to Configure Etendo Copilot to Use a Proxy: Cómo Configurar Etendo Copilot para Usar un Proxy How to Configure Log: Cómo Configurar el Log How to Configure MCP Servers on a Etendo Agent: Cómo Configurar Servidores MCP en un Agente de Etendo @@ -1186,6 +1188,7 @@ nav: - SQL Expert: user-guide/etendo-copilot/bundles/sql-expert.md - New UI: - User Interface Improvements: user-guide/new-ui/ui-improvements.md + - How to Configure Color System Support: user-guide/new-ui/how-to-guides/how-to-configure-color-system.md - Developer Guide: - Overview: developer-guide/overview.md From ad97b3f09995fab13c02f7cddf037a31a115acde Mon Sep 17 00:00:00 2001 From: etendobot <108091082+etendobot@users.noreply.github.com> Date: Thu, 12 Mar 2026 10:50:40 -0300 Subject: [PATCH 02/15] Feature ETP-3486: Update ES translation --- .../new-ui/how-to-guides/how-to-configure-color-system.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md index a511396312..038150b308 100644 --- a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md +++ b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -77,4 +77,4 @@ Su dinámica de control actual **NO afectará o incidirá bajo los elementos a c * Campos de texto estáticos y regulares (Cadenas o *Strings* convencionales). * Valores Numéricos, Fechas naturales o datos de tipo Booleanos. -* Listas estáticas predefinidas en el sistema (Es decir, menús desplegables del propio tipo *List* codificados de forma fija o *hardcodeada* bajo los dominios de las Listas de Referencia en el diccionario). +* Listas estáticas predefinidas en el sistema (Es decir, menús desplegables del propio tipo *List* codificados de forma fija o *hardcodeada* bajo los dominios de las Listas de Referencia en el diccionario). \ No newline at end of file From 7ecc0414d145141919cafc74af5f315bc74074e4 Mon Sep 17 00:00:00 2001 From: etendobot <108091082+etendobot@users.noreply.github.com> Date: Thu, 12 Mar 2026 11:05:16 -0300 Subject: [PATCH 03/15] Feature ETP-3486: Update ES translation --- .../new-ui/how-to-guides/how-to-configure-color-system.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md index 038150b308..4e276249ce 100644 --- a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md +++ b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -77,4 +77,6 @@ Su dinámica de control actual **NO afectará o incidirá bajo los elementos a c * Campos de texto estáticos y regulares (Cadenas o *Strings* convencionales). * Valores Numéricos, Fechas naturales o datos de tipo Booleanos. -* Listas estáticas predefinidas en el sistema (Es decir, menús desplegables del propio tipo *List* codificados de forma fija o *hardcodeada* bajo los dominios de las Listas de Referencia en el diccionario). \ No newline at end of file +* Listas estáticas predefinidas en el sistema (Es decir, menús desplegables del propio tipo *List* codificados de forma fija o *hardcodeada* bajo los dominios de las Listas de Referencia en el diccionario). + +--- \ No newline at end of file From b34d9b0e010bbe166caea9929fcfd53995cdd236 Mon Sep 17 00:00:00 2001 From: etendobot <108091082+etendobot@users.noreply.github.com> Date: Thu, 12 Mar 2026 11:40:33 -0300 Subject: [PATCH 04/15] Feature ETP-3486: Update ES translation --- .../new-ui/how-to-guides/how-to-configure-color-system.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md index 4e276249ce..5aecce4d6f 100644 --- a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md +++ b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -79,4 +79,6 @@ Su dinámica de control actual **NO afectará o incidirá bajo los elementos a c * Valores Numéricos, Fechas naturales o datos de tipo Booleanos. * Listas estáticas predefinidas en el sistema (Es decir, menús desplegables del propio tipo *List* codificados de forma fija o *hardcodeada* bajo los dominios de las Listas de Referencia en el diccionario). +--- + --- \ No newline at end of file From 4c1c9346af884d858657ab0f8db774db44d2ff09 Mon Sep 17 00:00:00 2001 From: Santiago Alaniz Date: Thu, 12 Mar 2026 11:46:44 -0300 Subject: [PATCH 05/15] Feature ETP-3486: Update English doc --- .../how-to-configure-color-system.md | 96 ++++++++++--------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md index a511396312..b2f216ecb6 100644 --- a/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md +++ b/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -6,75 +6,77 @@ tags: - Extensibility --- -# Cómo Configurar el Soporte al Sistema de Colores en la UI +# How to Configure Color System Support in the UI -## Visión General +## Overview -El sistema de colores en Etendo permite asignar identificadores visuales (pastillas de color) a registros dentro de una grilla o formulario en Workspace UI, mejorando la experiencia del usuario al destacar información clave. Esta funcionalidad aprovecha el sistema de extensibilidad de Etendo para aplicarse transparentemente sin necesidad de alterar el código base de la interfaz gráfica. +The color system in Etendo allows you to assign visual identifiers (color badges) to records within a grid or form in the Workspace UI, enhancing the user experience by highlighting key information. This feature leverages Etendo's extensibility system, allowing it to be applied transparently without altering the core codebase of the graphical interface. -Un excelente caso de uso (y uno de los más visuales) es aplicarlo a tablas maestras como la **Categoría de Producto (M_Product_Category)** o el **Grupo de Terceros (C_BP_Group)**, ya que estas son muy utilizadas dentro de grillas principales (como la grilla de Productos o la de Terceros/Clientes). +An excellent (and highly visual) use case is applying it to master tables such as the **Product Category (M_Product_Category)** or **Business Partner Group (C_BP_Group)**, as these are heavily used within main grids (like the Products or Customers grid). -## ¿Cómo funciona la relación con la otra tabla? +## How does the relationship work? -Para que el color se refleje en la UI, el campo en cuestión en la tabla principal debe apuntar a una tabla maestra a través de una Foreign Key (Referencia **TableDir** o **Table**). +For the color to be reflected in the UI, the field in question within the main table must point to a master table via a Foreign Key (**TableDir** or **Table** Reference). -La implementación actual en Workspace UI y Etendo funciona de manera coordinada gracias a una simbiosis entre la metadata y el frontend de React: +The current implementation in Workspace UI and Etendo works in coordination through an interaction between the metadata and the React frontend: -1. **Inyección de Metadata:** El backend deduce si una tabla hija necesita un color si nota que a lo que apunta contiene una propiedad cuya convención de nombre hace alusión a un color. De ser así, inyecta `colorFieldName` como metadato del campo a nivel del diccionario. -2. **Petición del lado del Front:** Los hooks de obtención de datos (Datasource) en NextJS revisan activamente cada columna definida. Si alguna especifica el metadata `colorFieldName`, el frontend añade al vuelo esa dependencia solicitada como `_extraProperties` en la Request a la API (ej: `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). Esto le fuerza al backend a hacer los JOIN correspondientes y volcar el valor final de color al formato JSON. -3. **Detección Dinámica de Interfaz:** Al momento de renderizar las celdas, el frontend es totalmente agnóstico e independiente: Escanea todas las claves (*keys*) de los registros recuperados y si alguna contiene dinámicamente la palabra `color` (o variables parecidas como `smfcolor`), le asigna automáticamente el componente visual en forma de 'Tag' envuelto, usando el valor hexa recuperado, su prefijo y deducido en un texto con buen contraste. +1. **Metadata Injection:** The backend determines if a child table needs a color by checking if the table it points to has a property following a naming convention that implies a color. If so, it injects `colorFieldName` as the field metadata at the dictionary level. +2. **Frontend Request:** The data fetching hooks (Datasource) in NextJS actively evaluate each defined column. If any column specifies the `colorFieldName` metadata, the frontend adds this requested dependency on the fly as `_extraProperties` to the API Request (e.g., `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). This forces the backend to perform the corresponding JOINs and dump the final color value into the JSON response. +3. **Dynamic Interface Detection:** When rendering the cells, the frontend is completely agnostic and independent. It scans all the *keys* of the fetched records and if any key dynamically contains the word `color` (or similar variables like `smfcolor`), it automatically assigns the visual component in the form of a wrapped 'Tag', using the recovered hex value, its prefix, and deducting a text with good contrast. -Esta arquitectura explícita garantiza eficiencia sin corromper el payload estándar. De igual manera, se actualiza en tiempo real tanto en la **Vista de Formulario (Form View)**, en la **Vista de Grilla Principal (Grid View)**, y a la hora de mutar la información por medio de la **Edición en Línea (Inline Editing)** (donde el cliente vuelve a efectuar una petición del registro pidiendo los `_extraProperties` de colores al guardar exitosamente). +This explicit architecture ensures efficiency without corrupting the standard payload. Similarly, it updates in real time in the **Form View**, the **Main Grid View**, and when mutating information via **Inline Editing** (where the client fetches the record again requesting the color `_extraProperties` upon successful save). -## Paso a Paso: Configurar el Color en la Categoría de Productos +## Step-by-Step: Configuring Color in Product Category -A continuación, se detalla el procedimiento exacto para probar e implementar esto utilizando la tabla `M_Product_Category` como ejemplo: +Below is the exact procedure to test and implement this easily using the `M_Product_Category` table as an example: -### 1. Agregar la columna de Color en el Diccionario de Datos +### 1. Add the Color column in the Data Dictionary -1. Ingresa a tu entorno de **Etendo ERP Classic** con el rol de **System Administrator** (Administrador del Sistema). -2. Ve a la ventana **Tables and Columns** (Tablas y Columnas). -3. Busca la tabla maestra de interés, en este caso `M_Product_Category` (Categoría de Producto). -4. En la pestaña de *Columns*, crea una nueva columna utilizando tu prefijo de módulo (por ejemplo `EM_CRM_Color`, `EM_SMF_Color` o usar el prefijo de tu módulo de pruebas activo). -5. Configúrala como tipo **String** (cadena de texto) con una longitud de 7 o 10 caracteres; suficientes para guardar en su interior un código hexadecimal (`#FF0000`). +1. Log into your **Etendo ERP Classic** environment with the **System Administrator** role. +2. Go to the **Tables and Columns** window. +3. Search for the master table of interest, in this case, `M_Product_Category` (Product Category). +4. On the *Columns* tab, create a new column using your module prefix (for example, `EM_CRM_Color`, `EM_SMF_Color`, or your active testing module prefix). +5. Configure it as a **String** type with a length of 7 or 10 characters—enough to store a hex code like `#FF0000`. -!!!note "Nota clave" - Gracias a la lógica de resolución entre la metadata y cómo nuestro Frontend evalúa las claves JSON al renderizar ([extractColorContext]), Etendo auto-asignará a la paleta cualquier variable cuya convención incluya el sufijo de forma de la palabra "color". +!!!note "Key Note" + Thanks to the resolution logic between the metadata and how our Frontend evaluates the JSON keys when rendering ([extractColorContext]), Etendo will auto-assign to the palette any variable whose naming convention includes the "color" word suffix. -### 2. Aplicar la tabla en la BD y mostrar la columna +### 2. Apply DB changes and show the column in the window -Luego de definir la columna en el diccionario de datos, debes materializarla en la base de datos: -1. Aplica los cambios mediante el proceso clásico compilando en consola (ej. `gradlew smartbuild` o reconstruyendo de manera apropiada la base de datos). -2. Ve a la ventana **Window, Tab and Field** (Ventana, Pestaña y Campo) dentro del entorno Etendo. -3. Busca la ventana correspondiente, en este caso **Product Category**. -4. Asegúrate recargar la pestaña o cerciorarte de agregar/crear el registro para la pestaña central de **Field** respecto a esa nueva columna, logrando así que el campo esté listo para ser usado y se visualice en la interfaz del ERP clásico. +After defining the column in the data dictionary, you must materialize it in your database: +1. Apply the changes compiling the system via console (e.g., `gradlew smartbuild` or rebuilding the database appropriately). +2. Navigate to the **Window, Tab and Field** window within the Etendo environment. +3. Search for the corresponding window, in this case, **Product Category**. +4. Make sure to reload the tab or manually add/create the corresponding record in the **Field** tab for the new column, allowing it to appear in the classic ERP interface ready for use. -### 3. Prueba de Fuego (¡La Magia Visual!) +### 3. The Visual Test (The Visual Magic!) -1. Abre la ventana **Product Category** (Categoría de Producto) en Etendo Classic. -2. Selecciona un registro existente, por ejemplo la categoría titulada "Standard" (o directamente sobre la que decidas usar). -3. Escribe un valor hexadecimal identificativo y bien llamativo sobre el nuevo campo de color. Por ejemplo: `#8E44AD` (Un color púrpura oscuro), y guarda finalmente el registro. -4. Ahora, ve a través del frontend de **NextJS de Workspace UI**. -5. Abre la ventana principal respectiva para **Products** (Productos o `M_Product`). -6. En aquella grilla resultante de productos, busca la columna "Categoría de Producto" (`M_Product_Category_ID`). -7. **¡Sorpresa!** Si esta categoría suele verse como un simple texto azul detallando el contenido "Standard", ahora notarás un cambio muy atractivo. Al pedirse los datos, el frontend detectará que hay una configuración para pedir metadatos de ese color (`_extraProperties`), inyectará la petición, la base de datos lo procesará en sus JOINs, Workspace captará la key "color" para esa columna y terminará pintándolo en una hermosa pastilla redondeada color púrpura. +1. Open the **Product Category** window in Etendo Classic. +2. Select an existing record, for example, the category titled "Standard" (or whichever you decide to use). +3. Write an identifying and eye-catching hexadecimal value in the new assigned color field. For example: `#8E44AD` (a dark purple color), and hit save on the record. +4. Now, go to the **NextJS frontend of Workspace UI**. +5. Open the respective main window for **Products** (`M_Product`). +6. In the resulting products grid, search for the "Product Category" column (`M_Product_Category_ID`). +7. **Surprise!** If this category normally appeared as simple blue text detailing "Standard", you'll now witness an appealing change. When requesting the data, the frontend will detect the configuration to request metadata for that color (`_extraProperties`) and inject the request. The database will process it in its JOINs, Workspace will capture the "color" key for that column, and it will end up painting it in a beautiful rounded purple badge. -Lo genial de este diseño es que todo ha quedado **totalmente agnóstico de módulos**. Uno puede crear a la vez módulos independientes para sus clientes, agregando variables idénticas referidas como `EM_Cliente_Color` para tablas de Monedas, Métodos de Pago, Vendedores o Almacenes... e instantáneamente brotarán coloreadas en la grilla y formulario de la UI sin que se requiera programar ni un solo *if* auxiliar del lado visual. +The brilliance of this design is that everything is **completely module-agnostic**. You can create independent modules for your clients, adding exactly the same tracking variables referred to as `EM_Client_Color` to tables such as Currencies, Payment Methods, Sales Representatives, or Warehouses... and they will instantly pop up colored across the grid and form in the UI without needing a single additional *if* programmed on the frontend visual side. -## Restricciones y Análisis de Alcance +## Scope and Restrictions -### ¿A qué campos afecta y permite intervenir? +### What fields are affected? -La lógica dinámica de inyección de metadata y renderizado de pastillas de color **solo afecta a campos (Fields) definidos como tipo de Referencia Foránea (Foreign Keys / TableDir / Table)** hacia la tabla maestra que ya cuenta con la columna de color configurada. Algunos ejemplos concisos incluyen: +The dynamic logic for metadata injection and color badge rendering **only affects fields defined as Foreign Keys (TableDir / Table)** targeting a master table that already has the color column configured. Some concise examples include: -* `M_Product_Category_ID` apuntando en la tabla de Productos. -* `Priority_ID` reflejándose en la tabla de Tareas. -* `C_Currency_ID` visualizándose en la tabla de Facturas. +* `M_Product_Category_ID` pointing in the Products table. +* `Priority_ID` reflecting in the Tasks table. +* `C_Currency_ID` translating to the Invoices table. -### ¿A qué campos NO afecta o resultan omitidos? +### What is NOT affected? -Su dinámica de control actual **NO afectará o incidirá bajo los elementos a continuación especificables**: +This current control mechanism **DOES NOT affect or interfere with**: -* Campos de texto estáticos y regulares (Cadenas o *Strings* convencionales). -* Valores Numéricos, Fechas naturales o datos de tipo Booleanos. -* Listas estáticas predefinidas en el sistema (Es decir, menús desplegables del propio tipo *List* codificados de forma fija o *hardcodeada* bajo los dominios de las Listas de Referencia en el diccionario). +* Regular and simple static text fields (Strings). +* Numbers, Dates, or Boolean values. +* Hardcoded static lists in the dictionary (Dropdowns of type *List* defined fixedly within Reference lists domains in the system). + +--- From 6648755335b68b475c99f64d0e0a0bbb00391d89 Mon Sep 17 00:00:00 2001 From: Santiago Alaniz Date: Thu, 12 Mar 2026 12:08:20 -0300 Subject: [PATCH 06/15] Feature ETP-3486: Update Doc --- .../how-to-configure-color-system.md | 17 +++++++++-------- .../how-to-configure-color-system.md | 13 +++++++------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md index 5aecce4d6f..df6ec14057 100644 --- a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md +++ b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -20,9 +20,9 @@ Para que el color se refleje en la UI, el campo en cuestión en la tabla princip La implementación actual en Workspace UI y Etendo funciona de manera coordinada gracias a una simbiosis entre la metadata y el frontend de React: -1. **Inyección de Metadata:** El backend deduce si una tabla hija necesita un color si nota que a lo que apunta contiene una propiedad cuya convención de nombre hace alusión a un color. De ser así, inyecta `colorFieldName` como metadato del campo a nivel del diccionario. -2. **Petición del lado del Front:** Los hooks de obtención de datos (Datasource) en NextJS revisan activamente cada columna definida. Si alguna especifica el metadata `colorFieldName`, el frontend añade al vuelo esa dependencia solicitada como `_extraProperties` en la Request a la API (ej: `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). Esto le fuerza al backend a hacer los JOIN correspondientes y volcar el valor final de color al formato JSON. -3. **Detección Dinámica de Interfaz:** Al momento de renderizar las celdas, el frontend es totalmente agnóstico e independiente: Escanea todas las claves (*keys*) de los registros recuperados y si alguna contiene dinámicamente la palabra `color` (o variables parecidas como `smfcolor`), le asigna automáticamente el componente visual en forma de 'Tag' envuelto, usando el valor hexa recuperado, su prefijo y deducido en un texto con buen contraste. +1. **Inyección de Metadata:** El backend deduce si una tabla hija necesita mostrar un color verificando si el diccionario de datos tiene configurada la columna con la Referencia asignada al tipo "Color". De ser así, inyecta `colorFieldName` indicando cómo se llama esta propiedad hacia la metadata gráfica. +2. **Petición del lado del Front:** Los hooks de obtención de datos (Datasource) en NextJS revisan activamente cada columna definida. Si alguna especifica la metadata `colorFieldName`, el frontend añade al vuelo esa dependencia para solicitarla en la Request a la API (ej: `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). Esto le fuerza al backend a hacer los JOIN correspondientes y volcar el valor final del color al formato JSON. +3. **Renderizado en la Interfaz:** Al momento de procesar las celdas, el frontend comprueba si recibió esta propiedad vinculada al color y le asigna automáticamente el componente visual en forma de 'Tag' (pastilla envuelta), usando el valor hexa recuperado y calculando un texto con buen contraste de legibilidad. Esta arquitectura explícita garantiza eficiencia sin corromper el payload estándar. De igual manera, se actualiza en tiempo real tanto en la **Vista de Formulario (Form View)**, en la **Vista de Grilla Principal (Grid View)**, y a la hora de mutar la información por medio de la **Edición en Línea (Inline Editing)** (donde el cliente vuelve a efectuar una petición del registro pidiendo los `_extraProperties` de colores al guardar exitosamente). @@ -35,11 +35,12 @@ A continuación, se detalla el procedimiento exacto para probar e implementar es 1. Ingresa a tu entorno de **Etendo ERP Classic** con el rol de **System Administrator** (Administrador del Sistema). 2. Ve a la ventana **Tables and Columns** (Tablas y Columnas). 3. Busca la tabla maestra de interés, en este caso `M_Product_Category` (Categoría de Producto). -4. En la pestaña de *Columns*, crea una nueva columna utilizando tu prefijo de módulo (por ejemplo `EM_CRM_Color`, `EM_SMF_Color` o usar el prefijo de tu módulo de pruebas activo). -5. Configúrala como tipo **String** (cadena de texto) con una longitud de 7 o 10 caracteres; suficientes para guardar en su interior un código hexadecimal (`#FF0000`). +4. En la pestaña de *Columns*, crea una nueva columna utilizando tu prefijo de módulo (por ejemplo `EM_CRM_Color` o usar el prefijo de tu módulo de pruebas activo). +5. Asigna a esta nueva columna el tipo de referencia **Color**. Esta es la instrucción clave y mejor práctica para que el sistema reconozca oficial y estructuradamente que este campo soportará colores. +6. La longitud ideal es de 7 o 10 caracteres; suficientes para guardar en su interior un código hexadecimal (`#FF0000`). !!!note "Nota clave" - Gracias a la lógica de resolución entre la metadata y cómo nuestro Frontend evalúa las claves JSON al renderizar ([extractColorContext]), Etendo auto-asignará a la paleta cualquier variable cuya convención incluya el sufijo de forma de la palabra "color". + Al utilizar el Reference "Color", el backend detectará explícita y correctamente el propósito de tu columna sin depender del nombre exacto bajo el que la registres, integrándola transparentemente a la metadata que lee el frontend. ### 2. Aplicar la tabla en la BD y mostrar la columna @@ -57,9 +58,9 @@ Luego de definir la columna en el diccionario de datos, debes materializarla en 4. Ahora, ve a través del frontend de **NextJS de Workspace UI**. 5. Abre la ventana principal respectiva para **Products** (Productos o `M_Product`). 6. En aquella grilla resultante de productos, busca la columna "Categoría de Producto" (`M_Product_Category_ID`). -7. **¡Sorpresa!** Si esta categoría suele verse como un simple texto azul detallando el contenido "Standard", ahora notarás un cambio muy atractivo. Al pedirse los datos, el frontend detectará que hay una configuración para pedir metadatos de ese color (`_extraProperties`), inyectará la petición, la base de datos lo procesará en sus JOINs, Workspace captará la key "color" para esa columna y terminará pintándolo en una hermosa pastilla redondeada color púrpura. +7. **¡Sorpresa!** Si esta categoría suele verse como un simple texto azul detallando el contenido "Standard", ahora notarás un cambio muy atractivo. Al pedirse los datos, el frontend detectará que hay una configuración para pedir metadatos de ese color (`_extraProperties`), inyectará la petición extra, la base de datos lo procesará automáticamente por detrás y la UI terminará pintando el texto en una hermosa pastilla redondeada color púrpura. -Lo genial de este diseño es que todo ha quedado **totalmente agnóstico de módulos**. Uno puede crear a la vez módulos independientes para sus clientes, agregando variables idénticas referidas como `EM_Cliente_Color` para tablas de Monedas, Métodos de Pago, Vendedores o Almacenes... e instantáneamente brotarán coloreadas en la grilla y formulario de la UI sin que se requiera programar ni un solo *if* auxiliar del lado visual. +Lo genial de este diseño es que todo ha quedado **totalmente agnóstico de módulos y variables específicas**. Siempre que la tabla maestra cuente con una columna configurada con el Reference "Color", el componente subyacente de UI la aprovechará sin problemas. Uno puede aplicarlo a tablas de Monedas, Métodos de Pago, Vendedores o Almacenes... e instantáneamente brotarán coloreadas en la grilla y formulario sin que se requiera programar ni un solo componente auxiliar. ## Restricciones y Análisis de Alcance diff --git a/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md index b2f216ecb6..811175e13f 100644 --- a/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md +++ b/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -20,9 +20,9 @@ For the color to be reflected in the UI, the field in question within the main t The current implementation in Workspace UI and Etendo works in coordination through an interaction between the metadata and the React frontend: -1. **Metadata Injection:** The backend determines if a child table needs a color by checking if the table it points to has a property following a naming convention that implies a color. If so, it injects `colorFieldName` as the field metadata at the dictionary level. +1. **Metadata Injection:** The backend determines if a child table needs to display a color by checking if the data dictionary has the column configured with the "Color" Reference type. If so, it injects `colorFieldName` to indicate the property name into the graphical metadata. 2. **Frontend Request:** The data fetching hooks (Datasource) in NextJS actively evaluate each defined column. If any column specifies the `colorFieldName` metadata, the frontend adds this requested dependency on the fly as `_extraProperties` to the API Request (e.g., `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). This forces the backend to perform the corresponding JOINs and dump the final color value into the JSON response. -3. **Dynamic Interface Detection:** When rendering the cells, the frontend is completely agnostic and independent. It scans all the *keys* of the fetched records and if any key dynamically contains the word `color` (or similar variables like `smfcolor`), it automatically assigns the visual component in the form of a wrapped 'Tag', using the recovered hex value, its prefix, and deducting a text with good contrast. +3. **Interface Rendering:** When processing the cells, the frontend checks if it received this linked color property and automatically assigns the visual component in the form of a wrapped 'Tag' badge, using the recovered hex value and calculating a text with good contrast. This explicit architecture ensures efficiency without corrupting the standard payload. Similarly, it updates in real time in the **Form View**, the **Main Grid View**, and when mutating information via **Inline Editing** (where the client fetches the record again requesting the color `_extraProperties` upon successful save). @@ -36,10 +36,11 @@ Below is the exact procedure to test and implement this easily using the `M_Prod 2. Go to the **Tables and Columns** window. 3. Search for the master table of interest, in this case, `M_Product_Category` (Product Category). 4. On the *Columns* tab, create a new column using your module prefix (for example, `EM_CRM_Color`, `EM_SMF_Color`, or your active testing module prefix). -5. Configure it as a **String** type with a length of 7 or 10 characters—enough to store a hex code like `#FF0000`. +5. Assign this new column the **Color** Reference type. This is the key instruction and best practice so the system officially and structurally recognizes that this field will support colors. +6. The ideal size length is 7 or 10 characters—enough to store a hex code like `#FF0000`. !!!note "Key Note" - Thanks to the resolution logic between the metadata and how our Frontend evaluates the JSON keys when rendering ([extractColorContext]), Etendo will auto-assign to the palette any variable whose naming convention includes the "color" word suffix. + By using the "Color" Reference, the backend will explicitly and correctly detect the purpose of your column without depending on the exact name you register it under, transparently integrating it into the metadata read by the frontend. ### 2. Apply DB changes and show the column in the window @@ -57,9 +58,9 @@ After defining the column in the data dictionary, you must materialize it in you 4. Now, go to the **NextJS frontend of Workspace UI**. 5. Open the respective main window for **Products** (`M_Product`). 6. In the resulting products grid, search for the "Product Category" column (`M_Product_Category_ID`). -7. **Surprise!** If this category normally appeared as simple blue text detailing "Standard", you'll now witness an appealing change. When requesting the data, the frontend will detect the configuration to request metadata for that color (`_extraProperties`) and inject the request. The database will process it in its JOINs, Workspace will capture the "color" key for that column, and it will end up painting it in a beautiful rounded purple badge. +7. **Surprise!** If this category normally appeared as simple blue text detailing "Standard", you'll now witness an appealing change. When requesting the data, the frontend will detect the configuration to request metadata for that color (`_extraProperties`) and inject the extra request. The database will automatically process it behind the scenes, and the UI will end up painting the text in a beautiful rounded purple badge. -The brilliance of this design is that everything is **completely module-agnostic**. You can create independent modules for your clients, adding exactly the same tracking variables referred to as `EM_Client_Color` to tables such as Currencies, Payment Methods, Sales Representatives, or Warehouses... and they will instantly pop up colored across the grid and form in the UI without needing a single additional *if* programmed on the frontend visual side. +The brilliance of this design is that everything is **completely module-agnostic and variable-agnostic**. As long as the master table has a column configured with the "Color" Reference, the underlying UI component will take advantage of it seamlessly. You can apply it to tables such as Currencies, Payment Methods, Sales Representatives, or Warehouses... and they will instantly pop up colored across the grid and form without needing a single additional component programmed. ## Scope and Restrictions From b552c45c6bb8a40da2a6026884b4fdf99eb261b5 Mon Sep 17 00:00:00 2001 From: etendobot <108091082+etendobot@users.noreply.github.com> Date: Thu, 12 Mar 2026 12:16:43 -0300 Subject: [PATCH 07/15] Feature ETP-3486: Update ES translation From 3f4c90f687a3fcd4d33fa05eddcc91473ba2e3c6 Mon Sep 17 00:00:00 2001 From: Santiago Alaniz Date: Fri, 13 Mar 2026 09:18:38 -0300 Subject: [PATCH 08/15] Feature ETP-3486: Fix duplicated finisher --- .../new-ui/how-to-guides/how-to-configure-color-system.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md index df6ec14057..42fb9edec8 100644 --- a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md +++ b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -80,6 +80,4 @@ Su dinámica de control actual **NO afectará o incidirá bajo los elementos a c * Valores Numéricos, Fechas naturales o datos de tipo Booleanos. * Listas estáticas predefinidas en el sistema (Es decir, menús desplegables del propio tipo *List* codificados de forma fija o *hardcodeada* bajo los dominios de las Listas de Referencia en el diccionario). ---- - --- \ No newline at end of file From 926e8150fad5b7f31667e6625763c6c7f27c55ff Mon Sep 17 00:00:00 2001 From: Isaias Battaglia Date: Thu, 19 Mar 2026 12:48:07 -0300 Subject: [PATCH 09/15] Feature ETP-3486: Move color system doc to developer how-to-guides - Move how-to-configure-color-system.md from user-guide/new-ui to developer-guide/etendo-classic/how-to-guides - Fix style: remove informal tone, fix admonitions, add license footer - Add status: new to frontmatter - Update mkdocs.yml nav in both EN and ES blocks --- .../how-to-configure-color-system.md | 89 +++++++++++++++++++ .../how-to-configure-color-system.md | 83 ----------------- mkdocs.yml | 4 +- 3 files changed, 91 insertions(+), 85 deletions(-) create mode 100644 docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md delete mode 100644 docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md diff --git a/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md b/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md new file mode 100644 index 0000000000..7da164ab66 --- /dev/null +++ b/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md @@ -0,0 +1,89 @@ +--- +tags: + - How to + - Color System + - UI + - Extensibility + +status: new +--- + +# How to Configure Color System Support in the UI + +## Overview + +The color system in Etendo allows assigning visual identifiers (color badges) to records within a grid or form in the Workspace UI, enhancing the user experience by highlighting key information. This feature uses Etendo's extensibility system and can be applied without modifying the core codebase of the graphical interface. + +A common use case is applying it to master tables such as **Product Category** (`M_Product_Category`) or **Business Partner Group** (`C_BP_Group`), as these are frequently referenced in main grids like Products or Customers. + +## How the Color System Works + +For a color to appear in the UI, the field in the main table must reference a master table via a Foreign Key (**TableDir** or **Table** reference). The Workspace UI and Etendo coordinate through an interaction between the metadata and the React frontend: + +1. **Metadata injection**: the backend checks whether the data dictionary has the column configured with the **Color** reference type. If so, it injects `colorFieldName` into the graphical metadata to indicate the property name. +2. **Frontend request**: the data-fetching hooks (Datasource) in Next.js evaluate each defined column. If a column specifies `colorFieldName` metadata, the frontend adds the dependency as `_extraProperties` to the API request (e.g., `_extraProperties=M_Product_Category_ID$EM_SMF_Color`), which instructs the backend to perform the corresponding JOINs and return the color value in the JSON response. +3. **Interface rendering**: when processing cells, the frontend checks for the linked color property and renders a **Tag** badge using the hex value, calculating a text color with adequate contrast. + +This architecture ensures efficiency without modifying the standard payload. Color values update in real time in the **Form View**, the **Main Grid View**, and during **Inline Editing**. + +## Step-by-Step: Configuring Color in Product Category + +The following procedure uses `M_Product_Category` as an example. + +### 1. Add the Color Column in the Data Dictionary + +1. Access the Etendo ERP Classic environment with the **System Administrator** role. +2. Navigate to the **Tables and Columns** window. +3. Search for the master table — in this case, `M_Product_Category` (Product Category). +4. In the **Columns** tab, create a new column using the module prefix (e.g., `EM_CRM_Color` or `EM_SMF_Color`). +5. Assign the **Color** reference type to the new column. This is the key step that allows the system to recognize the column's purpose. +6. Set the length to 7 or 10 characters — sufficient to store a hex code such as `#FF0000`. + +!!! note + Using the **Color** reference type allows the backend to detect the column's purpose independently of its name, integrating it transparently into the metadata read by the frontend. + +### 2. Apply Database Changes and Show the Column + +1. Apply the changes by compiling the system: + + ```bash title="Terminal" + ./gradlew smartbuild + ``` + +2. Navigate to the **Window, Tab and Field** window in Etendo Classic. +3. Search for the **Product Category** window. +4. In the **Field** tab, add or reload the record for the new column so it appears in the classic ERP interface. + +### 3. Verify the Configuration + +1. Open the **Product Category** window in Etendo Classic. +2. Select an existing record (e.g., the category *Standard*). +3. Enter a hex color value in the new field (e.g., `#8E44AD`) and save. +4. Open the Workspace UI and navigate to the **Products** window (`M_Product`). +5. In the products grid, locate the **Product Category** column (`M_Product_Category_ID`). + +The frontend detects the color configuration, adds the `_extraProperties` request parameter, and renders the category value as a colored badge. + +!!! info + This behavior is module-agnostic and variable-agnostic. Any master table with a column configured with the **Color** reference type is automatically supported across grids and forms without additional development. + +## Scope and Restrictions + +### Affected Fields + +Color badge rendering applies only to **Foreign Key fields (TableDir / Table)** that reference a master table with a color column configured. Examples: + +- `M_Product_Category_ID` in the Products table. +- `Priority_ID` in the Tasks table. +- `C_Currency_ID` in the Invoices table. + +### Fields Not Affected + +This feature does not affect: + +- Plain text fields (Strings). +- Numeric, date, or boolean fields. +- Static list dropdowns (*List* reference type) defined in Reference domains. + +--- +This work is licensed under :material-creative-commons: :fontawesome-brands-creative-commons-by: :fontawesome-brands-creative-commons-sa: [ CC BY-SA 2.5 ES](https://creativecommons.org/licenses/by-sa/2.5/es/){target="_blank"} by [Futit Services S.L](https://etendo.software){target="_blank"}. diff --git a/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md deleted file mode 100644 index 811175e13f..0000000000 --- a/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -tags: - - How to - - Color System - - UI - - Extensibility ---- - -# How to Configure Color System Support in the UI - -## Overview - -The color system in Etendo allows you to assign visual identifiers (color badges) to records within a grid or form in the Workspace UI, enhancing the user experience by highlighting key information. This feature leverages Etendo's extensibility system, allowing it to be applied transparently without altering the core codebase of the graphical interface. - -An excellent (and highly visual) use case is applying it to master tables such as the **Product Category (M_Product_Category)** or **Business Partner Group (C_BP_Group)**, as these are heavily used within main grids (like the Products or Customers grid). - -## How does the relationship work? - -For the color to be reflected in the UI, the field in question within the main table must point to a master table via a Foreign Key (**TableDir** or **Table** Reference). - -The current implementation in Workspace UI and Etendo works in coordination through an interaction between the metadata and the React frontend: - -1. **Metadata Injection:** The backend determines if a child table needs to display a color by checking if the data dictionary has the column configured with the "Color" Reference type. If so, it injects `colorFieldName` to indicate the property name into the graphical metadata. -2. **Frontend Request:** The data fetching hooks (Datasource) in NextJS actively evaluate each defined column. If any column specifies the `colorFieldName` metadata, the frontend adds this requested dependency on the fly as `_extraProperties` to the API Request (e.g., `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). This forces the backend to perform the corresponding JOINs and dump the final color value into the JSON response. -3. **Interface Rendering:** When processing the cells, the frontend checks if it received this linked color property and automatically assigns the visual component in the form of a wrapped 'Tag' badge, using the recovered hex value and calculating a text with good contrast. - -This explicit architecture ensures efficiency without corrupting the standard payload. Similarly, it updates in real time in the **Form View**, the **Main Grid View**, and when mutating information via **Inline Editing** (where the client fetches the record again requesting the color `_extraProperties` upon successful save). - -## Step-by-Step: Configuring Color in Product Category - -Below is the exact procedure to test and implement this easily using the `M_Product_Category` table as an example: - -### 1. Add the Color column in the Data Dictionary - -1. Log into your **Etendo ERP Classic** environment with the **System Administrator** role. -2. Go to the **Tables and Columns** window. -3. Search for the master table of interest, in this case, `M_Product_Category` (Product Category). -4. On the *Columns* tab, create a new column using your module prefix (for example, `EM_CRM_Color`, `EM_SMF_Color`, or your active testing module prefix). -5. Assign this new column the **Color** Reference type. This is the key instruction and best practice so the system officially and structurally recognizes that this field will support colors. -6. The ideal size length is 7 or 10 characters—enough to store a hex code like `#FF0000`. - -!!!note "Key Note" - By using the "Color" Reference, the backend will explicitly and correctly detect the purpose of your column without depending on the exact name you register it under, transparently integrating it into the metadata read by the frontend. - -### 2. Apply DB changes and show the column in the window - -After defining the column in the data dictionary, you must materialize it in your database: -1. Apply the changes compiling the system via console (e.g., `gradlew smartbuild` or rebuilding the database appropriately). -2. Navigate to the **Window, Tab and Field** window within the Etendo environment. -3. Search for the corresponding window, in this case, **Product Category**. -4. Make sure to reload the tab or manually add/create the corresponding record in the **Field** tab for the new column, allowing it to appear in the classic ERP interface ready for use. - -### 3. The Visual Test (The Visual Magic!) - -1. Open the **Product Category** window in Etendo Classic. -2. Select an existing record, for example, the category titled "Standard" (or whichever you decide to use). -3. Write an identifying and eye-catching hexadecimal value in the new assigned color field. For example: `#8E44AD` (a dark purple color), and hit save on the record. -4. Now, go to the **NextJS frontend of Workspace UI**. -5. Open the respective main window for **Products** (`M_Product`). -6. In the resulting products grid, search for the "Product Category" column (`M_Product_Category_ID`). -7. **Surprise!** If this category normally appeared as simple blue text detailing "Standard", you'll now witness an appealing change. When requesting the data, the frontend will detect the configuration to request metadata for that color (`_extraProperties`) and inject the extra request. The database will automatically process it behind the scenes, and the UI will end up painting the text in a beautiful rounded purple badge. - -The brilliance of this design is that everything is **completely module-agnostic and variable-agnostic**. As long as the master table has a column configured with the "Color" Reference, the underlying UI component will take advantage of it seamlessly. You can apply it to tables such as Currencies, Payment Methods, Sales Representatives, or Warehouses... and they will instantly pop up colored across the grid and form without needing a single additional component programmed. - -## Scope and Restrictions - -### What fields are affected? - -The dynamic logic for metadata injection and color badge rendering **only affects fields defined as Foreign Keys (TableDir / Table)** targeting a master table that already has the color column configured. Some concise examples include: - -* `M_Product_Category_ID` pointing in the Products table. -* `Priority_ID` reflecting in the Tasks table. -* `C_Currency_ID` translating to the Invoices table. - -### What is NOT affected? - -This current control mechanism **DOES NOT affect or interfere with**: - -* Regular and simple static text fields (Strings). -* Numbers, Dates, or Boolean values. -* Hardcoded static lists in the dictionary (Dropdowns of type *List* defined fixedly within Reference lists domains in the system). - ---- diff --git a/mkdocs.yml b/mkdocs.yml index 1353a06741..e85a66d8d3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -302,7 +302,6 @@ plugins: - SQL Expert: user-guide/etendo-copilot/bundles/sql-expert.md - New UI: - User Interface Improvements: user-guide/new-ui/ui-improvements.md - - How to Configure Color System Support: user-guide/new-ui/how-to-guides/how-to-configure-color-system.md - Developer Guide: - Overview: developer-guide/overview.md @@ -383,6 +382,7 @@ plugins: - How to Change an Existing Window: developer-guide/etendo-classic/how-to-guides/how-to-change-an-existing-window.md - How to Change Fonts in Etendo Reports: developer-guide/etendo-classic/how-to-guides/how-to-change-fonts-in-etendo-reports.md - How to Change the Size of a Column: developer-guide/etendo-classic/how-to-guides/how-to-change-the-size-of-a-column.md + - How to Configure Color System Support: developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md - How to Configure Log: developer-guide/etendo-classic/how-to-guides/how-to-configure-log.md - How to Configure Session Timeout: developer-guide/etendo-classic/how-to-guides/how-to-configure-session-timeout.md - How to Copy and Paste Images in Etendo: developer-guide/etendo-classic/how-to-guides/how-to-copy-and-paste-images-in-etendo.md @@ -1188,7 +1188,6 @@ nav: - SQL Expert: user-guide/etendo-copilot/bundles/sql-expert.md - New UI: - User Interface Improvements: user-guide/new-ui/ui-improvements.md - - How to Configure Color System Support: user-guide/new-ui/how-to-guides/how-to-configure-color-system.md - Developer Guide: - Overview: developer-guide/overview.md @@ -1269,6 +1268,7 @@ nav: - How to Change an Existing Window: developer-guide/etendo-classic/how-to-guides/how-to-change-an-existing-window.md - How to Change Fonts in Etendo Reports: developer-guide/etendo-classic/how-to-guides/how-to-change-fonts-in-etendo-reports.md - How to Change the Size of a Column: developer-guide/etendo-classic/how-to-guides/how-to-change-the-size-of-a-column.md + - How to Configure Color System Support: developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md - How to Configure Log: developer-guide/etendo-classic/how-to-guides/how-to-configure-log.md - How to Configure Session Timeout: developer-guide/etendo-classic/how-to-guides/how-to-configure-session-timeout.md - How to Copy and Paste Images in Etendo: developer-guide/etendo-classic/how-to-guides/how-to-copy-and-paste-images-in-etendo.md From c2811baea457c79e03b0cdad593c934dd7e9c605 Mon Sep 17 00:00:00 2001 From: etendobot <108091082+etendobot@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:50:08 -0300 Subject: [PATCH 10/15] Feature ETP-3486: Update ES translation --- .../how-to-configure-color-system.md | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md diff --git a/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md b/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md new file mode 100644 index 0000000000..0faca4d03f --- /dev/null +++ b/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md @@ -0,0 +1,89 @@ +--- +tags: + - How to + - Color System + - UI + - Extensibility + +status: new +--- + +# Cómo configurar el soporte del sistema de color en la UI + +## Visión general + +El sistema de color en Etendo permite asignar identificadores visuales (etiquetas de color) a registros dentro de una rejilla o formulario en la UI de Workspace, mejorando la experiencia de usuario al resaltar información clave. Esta funcionalidad utiliza el sistema de extensibilidad de Etendo y puede aplicarse sin modificar el código base de la interfaz gráfica. + +Un caso de uso común es aplicarlo a tablas maestras como **Categoría de producto** (`M_Product_Category`) o **Grupo de terceros** (`C_BP_Group`), ya que se referencian con frecuencia en rejillas principales como Productos o Clientes. + +## Cómo funciona el sistema de color + +Para que un color aparezca en la UI, el campo en la tabla principal debe referenciar una tabla maestra mediante una clave foránea (referencia **TableDir** o **Tabla**). La UI de Workspace y Etendo se coordinan mediante una interacción entre los metadatos y el frontend en React: + +1. **Inyección de metadatos**: el backend comprueba si el diccionario de datos tiene la columna configurada con el tipo de referencia **Color**. Si es así, inyecta `colorFieldName` en los metadatos gráficos para indicar el nombre de la propiedad. +2. **Petición del frontend**: los hooks de obtención de datos (Datasource) en Next.js evalúan cada columna definida. Si una columna especifica metadatos `colorFieldName`, el frontend añade la dependencia como `_extraProperties` a la petición de la API (p. ej., `_extraProperties=M_Product_Category_ID$EM_SMF_Color`), lo que indica al backend que realice los JOIN correspondientes y devuelva el valor de color en la respuesta JSON. +3. **Renderizado de la interfaz**: al procesar las celdas, el frontend comprueba la propiedad de color enlazada y renderiza una insignia **Tag** usando el valor hex, calculando un color de texto con contraste adecuado. + +Esta arquitectura garantiza eficiencia sin modificar el payload estándar. Los valores de color se actualizan en tiempo real en la **Vista de formulario**, la **Vista principal de rejilla** y durante la **edición en línea**. + +## Paso a paso: configurar Color en Categoría de producto + +El siguiente procedimiento usa `M_Product_Category` como ejemplo. + +### 1. Añadir la columna Color en el diccionario de datos + +1. Accede al entorno Etendo ERP Classic con el rol **Administrador del sistema**. +2. Navega a la ventana **Tablas y columnas**. +3. Busca la tabla maestra — en este caso, `M_Product_Category` (Categoría de producto). +4. En la pestaña **Columnas**, crea una nueva columna usando el prefijo del módulo (p. ej., `EM_CRM_Color` o `EM_SMF_Color`). +5. Asigna el tipo de referencia **Color** a la nueva columna. Este es el paso clave que permite al sistema reconocer el propósito de la columna. +6. Establece la longitud en 7 o 10 caracteres — suficiente para almacenar un código hex como `#FF0000`. + +!!! note + Usar el tipo de referencia **Color** permite al backend detectar el propósito de la columna independientemente de su nombre, integrándola de forma transparente en los metadatos leídos por el frontend. + +### 2. Aplicar cambios en base de datos y mostrar la columna + +1. Aplica los cambios compilando el sistema: + + ```bash title="Terminal" + ./gradlew smartbuild + ``` + +2. Navega a la ventana **Ventana, pestaña y campo** en Etendo Classic. +3. Busca la ventana **Categoría de producto**. +4. En la pestaña **Campo**, añade o recarga el registro de la nueva columna para que aparezca en la interfaz del ERP Classic. + +### 3. Verificar la configuración + +1. Abre la ventana **Categoría de producto** en Etendo Classic. +2. Selecciona un registro existente (p. ej., la categoría *Standard*). +3. Introduce un valor de color hex en el nuevo campo (p. ej., `#8E44AD`) y guarda. +4. Abre la UI de Workspace y navega a la ventana **Productos** (`M_Product`). +5. En la rejilla de productos, localiza la columna **Categoría de producto** (`M_Product_Category_ID`). + +El frontend detecta la configuración de color, añade el parámetro de petición `_extraProperties` y renderiza el valor de la categoría como una insignia coloreada. + +!!! info + Este comportamiento es agnóstico al módulo y agnóstico a la variable. Cualquier tabla maestra con una columna configurada con el tipo de referencia **Color** se soporta automáticamente en rejillas y formularios sin desarrollo adicional. + +## Alcance y restricciones + +### Campos afectados + +El renderizado de insignias de color se aplica solo a **campos de clave foránea (TableDir / Tabla)** que referencian una tabla maestra con una columna de color configurada. Ejemplos: + +- `M_Product_Category_ID` en la tabla Productos. +- `Priority_ID` en la tabla Tareas. +- `C_Currency_ID` en la tabla Facturas. + +### Campos no afectados + +Esta funcionalidad no afecta a: + +- Campos de texto plano (Strings). +- Campos numéricos, de fecha o booleanos. +- Desplegables de lista estática (tipo de referencia *List*) definidos en dominios de referencia. + +--- +This work is licensed under :material-creative-commons: :fontawesome-brands-creative-commons-by: :fontawesome-brands-creative-commons-sa: [ CC BY-SA 2.5 ES](https://creativecommons.org/licenses/by-sa/2.5/es/){target="_blank"} by [Futit Services S.L](https://etendo.software){target="_blank"}. \ No newline at end of file From ee7a2efb8b25021c2a7b727f5c153b3b38cdf4f9 Mon Sep 17 00:00:00 2001 From: Santiago Alaniz Date: Fri, 20 Mar 2026 11:03:56 -0300 Subject: [PATCH 11/15] Hotfix ETP-3486: Fix comments --- .../overview-color-badges-grid.png | Bin 0 -> 20428 bytes .../color-system/step2-color-field-form.png | Bin 0 -> 4276 bytes .../color-system/step3-colored-badge-grid.png | Bin 0 -> 3366 bytes .../how-to-configure-color-system.md | 11 ++- .../how-to-configure-color-system.md | 8 +-- .../how-to-configure-color-system.md | 63 ++++++++++++++++++ mkdocs.yml | 4 ++ 7 files changed, 76 insertions(+), 10 deletions(-) create mode 100644 docs/assets/user-guide/newui/how-to-guides/color-system/overview-color-badges-grid.png create mode 100644 docs/assets/user-guide/newui/how-to-guides/color-system/step2-color-field-form.png create mode 100644 docs/assets/user-guide/newui/how-to-guides/color-system/step3-colored-badge-grid.png create mode 100644 docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md diff --git a/docs/assets/user-guide/newui/how-to-guides/color-system/overview-color-badges-grid.png b/docs/assets/user-guide/newui/how-to-guides/color-system/overview-color-badges-grid.png new file mode 100644 index 0000000000000000000000000000000000000000..274527ecd09f67ea2ab9adfe0f652d4834cbe4e5 GIT binary patch literal 20428 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 UBo?Ai&JN02YWnap)jQ$;0acXu(EtDd literal 0 HcmV?d00001 diff --git a/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md b/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md index 7da164ab66..e089d6eb62 100644 --- a/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md +++ b/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md @@ -34,7 +34,7 @@ The following procedure uses `M_Product_Category` as an example. 1. Access the Etendo ERP Classic environment with the **System Administrator** role. 2. Navigate to the **Tables and Columns** window. -3. Search for the master table — in this case, `M_Product_Category` (Product Category). +3. Search for the master table — in this case, `M_Product_Category` (Product Category). This is the table **being referenced** by the foreign key (e.g., the table that other tables point to via `M_Product_Category_ID`). The color column must be added here, not in the referencing table. 4. In the **Columns** tab, create a new column using the module prefix (e.g., `EM_CRM_Color` or `EM_SMF_Color`). 5. Assign the **Color** reference type to the new column. This is the key step that allows the system to recognize the column's purpose. 6. Set the length to 7 or 10 characters — sufficient to store a hex code such as `#FF0000`. @@ -52,7 +52,7 @@ The following procedure uses `M_Product_Category` as an example. 2. Navigate to the **Window, Tab and Field** window in Etendo Classic. 3. Search for the **Product Category** window. -4. In the **Field** tab, add or reload the record for the new column so it appears in the classic ERP interface. +4. In the **Field** tab, check if the new column already appears. If it does not, use the **Create Fields from Application Dictionary** process (available in the tab toolbar) to synchronize the window fields with the updated column definition. This step makes the field visible in the Classic ERP interface. ### 3. Verify the Configuration @@ -62,7 +62,7 @@ The following procedure uses `M_Product_Category` as an example. 4. Open the Workspace UI and navigate to the **Products** window (`M_Product`). 5. In the products grid, locate the **Product Category** column (`M_Product_Category_ID`). -The frontend detects the color configuration, adds the `_extraProperties` request parameter, and renders the category value as a colored badge. +If the configuration is correct, the **Product Category** value will be rendered as a colored **Tag** badge instead of plain text, using the hex color you assigned in the previous step. The badge will automatically calculate a contrasting text color for readability. !!! info This behavior is module-agnostic and variable-agnostic. Any master table with a column configured with the **Color** reference type is automatically supported across grids and forms without additional development. @@ -73,9 +73,8 @@ The frontend detects the color configuration, adds the `_extraProperties` reques Color badge rendering applies only to **Foreign Key fields (TableDir / Table)** that reference a master table with a color column configured. Examples: -- `M_Product_Category_ID` in the Products table. -- `Priority_ID` in the Tasks table. -- `C_Currency_ID` in the Invoices table. +- `M_Product_Category_ID` in the Products table — the reference used throughout this guide. +- Any other foreign key column pointing to a master table that has a column with the **Color** reference type configured. ### Fields Not Affected diff --git a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md index 42fb9edec8..5c0fc1971d 100644 --- a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md +++ b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -21,7 +21,7 @@ Para que el color se refleje en la UI, el campo en cuestión en la tabla princip La implementación actual en Workspace UI y Etendo funciona de manera coordinada gracias a una simbiosis entre la metadata y el frontend de React: 1. **Inyección de Metadata:** El backend deduce si una tabla hija necesita mostrar un color verificando si el diccionario de datos tiene configurada la columna con la Referencia asignada al tipo "Color". De ser así, inyecta `colorFieldName` indicando cómo se llama esta propiedad hacia la metadata gráfica. -2. **Petición del lado del Front:** Los hooks de obtención de datos (Datasource) en NextJS revisan activamente cada columna definida. Si alguna especifica la metadata `colorFieldName`, el frontend añade al vuelo esa dependencia para solicitarla en la Request a la API (ej: `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). Esto le fuerza al backend a hacer los JOIN correspondientes y volcar el valor final del color al formato JSON. +2. **Petición del lado del Front:** Los hooks de obtención de datos (Datasource) en Next.js revisan activamente cada columna definida. Si alguna especifica la metadata `colorFieldName`, el frontend añade al vuelo esa dependencia para solicitarla en la Request a la API (ej: `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). Esto le fuerza al backend a hacer los JOIN correspondientes y volcar el valor final del color al formato JSON. 3. **Renderizado en la Interfaz:** Al momento de procesar las celdas, el frontend comprueba si recibió esta propiedad vinculada al color y le asigna automáticamente el componente visual en forma de 'Tag' (pastilla envuelta), usando el valor hexa recuperado y calculando un texto con buen contraste de legibilidad. Esta arquitectura explícita garantiza eficiencia sin corromper el payload estándar. De igual manera, se actualiza en tiempo real tanto en la **Vista de Formulario (Form View)**, en la **Vista de Grilla Principal (Grid View)**, y a la hora de mutar la información por medio de la **Edición en Línea (Inline Editing)** (donde el cliente vuelve a efectuar una petición del registro pidiendo los `_extraProperties` de colores al guardar exitosamente). @@ -45,17 +45,17 @@ A continuación, se detalla el procedimiento exacto para probar e implementar es ### 2. Aplicar la tabla en la BD y mostrar la columna Luego de definir la columna en el diccionario de datos, debes materializarla en la base de datos: -1. Aplica los cambios mediante el proceso clásico compilando en consola (ej. `gradlew smartbuild` o reconstruyendo de manera apropiada la base de datos). +1. Aplica los cambios mediante el proceso clásico compilando en consola (ej. `./gradlew smartbuild` o reconstruyendo de manera apropiada la base de datos). 2. Ve a la ventana **Window, Tab and Field** (Ventana, Pestaña y Campo) dentro del entorno Etendo. 3. Busca la ventana correspondiente, en este caso **Product Category**. -4. Asegúrate recargar la pestaña o cerciorarte de agregar/crear el registro para la pestaña central de **Field** respecto a esa nueva columna, logrando así que el campo esté listo para ser usado y se visualice en la interfaz del ERP clásico. +4. Asegúrate de recargar la pestaña o cerciorarte de agregar/crear el registro para la pestaña central de **Field** respecto a esa nueva columna, logrando así que el campo esté listo para ser usado y se visualice en la interfaz del ERP clásico. ### 3. Prueba de Fuego (¡La Magia Visual!) 1. Abre la ventana **Product Category** (Categoría de Producto) en Etendo Classic. 2. Selecciona un registro existente, por ejemplo la categoría titulada "Standard" (o directamente sobre la que decidas usar). 3. Escribe un valor hexadecimal identificativo y bien llamativo sobre el nuevo campo de color. Por ejemplo: `#8E44AD` (Un color púrpura oscuro), y guarda finalmente el registro. -4. Ahora, ve a través del frontend de **NextJS de Workspace UI**. +4. Ahora, ve a través del frontend de **Next.js de Workspace UI**. 5. Abre la ventana principal respectiva para **Products** (Productos o `M_Product`). 6. En aquella grilla resultante de productos, busca la columna "Categoría de Producto" (`M_Product_Category_ID`). 7. **¡Sorpresa!** Si esta categoría suele verse como un simple texto azul detallando el contenido "Standard", ahora notarás un cambio muy atractivo. Al pedirse los datos, el frontend detectará que hay una configuración para pedir metadatos de ese color (`_extraProperties`), inyectará la petición extra, la base de datos lo procesará automáticamente por detrás y la UI terminará pintando el texto en una hermosa pastilla redondeada color púrpura. diff --git a/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md new file mode 100644 index 0000000000..134c7b3904 --- /dev/null +++ b/docs/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -0,0 +1,63 @@ +--- +tags: + - How to + - Color System + - UI + +status: new +--- + +# How to Use the Color System in Workspace UI + +## Overview + +The color system lets you assign a visual color badge to records in a master window. Once a color is assigned, every grid in Workspace UI that references that window will automatically display a colored tag instead of plain text — making it easier to scan and identify records at a glance. + +![Overview of color badges in a grid](../../../assets/user-guide/newui/how-to-guides/color-system/overview-color-badges-grid.png) + +!!! info "Prerequisite" + A developer must first configure the **Color** column in the data dictionary for the master window. If the color field is not visible in the form, contact your system administrator or follow the [developer guide](../../../developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md). + +--- + +## Step 1 — Open the Master Record + +1. Log in to **Etendo Classic** with a role that has access to the master window. +2. Navigate to the master window configured with a color column. +3. Open an existing record or create a new one. + + +--- + +## Step 2 — Assign a Color + +1. Locate the **Color** field in the form. It accepts a hexadecimal color code (e.g., `#8E44AD`). +2. Enter the desired hex color value directly, or use the color picker if available. +3. Click **Save**. + +![Color field in the form with a hex value entered](../../../assets/user-guide/newui/how-to-guides/color-system/step2-color-field-form.png) + +!!! tip + The UI calculates a contrasting text color automatically, but choosing a mid-range color (not too light, not too dark) gives the best visual result. + +--- + +## Step 3 — Verify the Color Badge in Workspace UI + +1. Open **Workspace UI** (the Next.js frontend). +2. Navigate to the window that contains a foreign key column referencing the master window. +3. In the grid, locate the column that points to the master window. + +The value now appears as a **colored badge** instead of plain text, reflecting the hex color you assigned. + +![Grid showing a colored badge in the referencing column](../../../assets/user-guide/newui/how-to-guides/color-system/step3-colored-badge-grid.png) + +--- + +## Changing or Removing a Color + +- To **change** the color: open the master record, enter a new hex value, and save. +- To **remove** the color: clear the color field and save. The column will revert to plain text in all grids. + +--- +This work is licensed under :material-creative-commons: :fontawesome-brands-creative-commons-by: :fontawesome-brands-creative-commons-sa: [ CC BY-SA 2.5 ES](https://creativecommons.org/licenses/by-sa/2.5/es/){target="_blank"} by [Futit Services S.L](https://etendo.software){target="_blank"}. diff --git a/mkdocs.yml b/mkdocs.yml index e85a66d8d3..5dedcc1733 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -302,6 +302,8 @@ plugins: - SQL Expert: user-guide/etendo-copilot/bundles/sql-expert.md - New UI: - User Interface Improvements: user-guide/new-ui/ui-improvements.md + - How-To Guides: + - How to Use the Color System: user-guide/new-ui/how-to-guides/how-to-configure-color-system.md - Developer Guide: - Overview: developer-guide/overview.md @@ -1188,6 +1190,8 @@ nav: - SQL Expert: user-guide/etendo-copilot/bundles/sql-expert.md - New UI: - User Interface Improvements: user-guide/new-ui/ui-improvements.md + - How-To Guides: + - How to Use the Color System: user-guide/new-ui/how-to-guides/how-to-configure-color-system.md - Developer Guide: - Overview: developer-guide/overview.md From b6a7646603a4007eab3ff125ca9817b5fb3837dd Mon Sep 17 00:00:00 2001 From: etendobot <108091082+etendobot@users.noreply.github.com> Date: Fri, 20 Mar 2026 11:05:51 -0300 Subject: [PATCH 12/15] Feature ETP-3486: Update ES translation --- .../how-to-configure-color-system.md | 16 ++-- .../how-to-configure-color-system.md | 87 +++++++------------ 2 files changed, 41 insertions(+), 62 deletions(-) diff --git a/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md b/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md index 0faca4d03f..d020fb697c 100644 --- a/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md +++ b/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md @@ -14,7 +14,7 @@ status: new El sistema de color en Etendo permite asignar identificadores visuales (etiquetas de color) a registros dentro de una rejilla o formulario en la UI de Workspace, mejorando la experiencia de usuario al resaltar información clave. Esta funcionalidad utiliza el sistema de extensibilidad de Etendo y puede aplicarse sin modificar el código base de la interfaz gráfica. -Un caso de uso común es aplicarlo a tablas maestras como **Categoría de producto** (`M_Product_Category`) o **Grupo de terceros** (`C_BP_Group`), ya que se referencian con frecuencia en rejillas principales como Productos o Clientes. +Un caso de uso común es aplicarlo a tablas maestras como **Categoría de producto** (`M_Product_Category`) o **Oferta grupo terceros** (`C_BP_Group`), ya que se referencian con frecuencia en rejillas principales como Productos o Clientes. ## Cómo funciona el sistema de color @@ -34,7 +34,7 @@ El siguiente procedimiento usa `M_Product_Category` como ejemplo. 1. Accede al entorno Etendo ERP Classic con el rol **Administrador del sistema**. 2. Navega a la ventana **Tablas y columnas**. -3. Busca la tabla maestra — en este caso, `M_Product_Category` (Categoría de producto). +3. Busca la tabla maestra — en este caso, `M_Product_Category` (Categoría de producto). Esta es la tabla que está **siendo referenciada** por la clave foránea (p. ej., la tabla a la que otras tablas apuntan mediante `M_Product_Category_ID`). La columna de color debe añadirse aquí, no en la tabla que referencia. 4. En la pestaña **Columnas**, crea una nueva columna usando el prefijo del módulo (p. ej., `EM_CRM_Color` o `EM_SMF_Color`). 5. Asigna el tipo de referencia **Color** a la nueva columna. Este es el paso clave que permite al sistema reconocer el propósito de la columna. 6. Establece la longitud en 7 o 10 caracteres — suficiente para almacenar un código hex como `#FF0000`. @@ -52,7 +52,7 @@ El siguiente procedimiento usa `M_Product_Category` como ejemplo. 2. Navega a la ventana **Ventana, pestaña y campo** en Etendo Classic. 3. Busca la ventana **Categoría de producto**. -4. En la pestaña **Campo**, añade o recarga el registro de la nueva columna para que aparezca en la interfaz del ERP Classic. +4. En la pestaña **Campo**, comprueba si la nueva columna ya aparece. Si no aparece, usa el proceso **Crear campos desde el Diccionario de Aplicación** (disponible en la barra de herramientas de la pestaña) para sincronizar los campos de la ventana con la definición de columna actualizada. Este paso hace que el campo sea visible en la interfaz del ERP Classic. ### 3. Verificar la configuración @@ -62,7 +62,7 @@ El siguiente procedimiento usa `M_Product_Category` como ejemplo. 4. Abre la UI de Workspace y navega a la ventana **Productos** (`M_Product`). 5. En la rejilla de productos, localiza la columna **Categoría de producto** (`M_Product_Category_ID`). -El frontend detecta la configuración de color, añade el parámetro de petición `_extraProperties` y renderiza el valor de la categoría como una insignia coloreada. +Si la configuración es correcta, el valor de **Categoría de producto** se renderizará como una insignia **Tag** coloreada en lugar de texto plano, usando el color hex que asignaste en el paso anterior. La insignia calculará automáticamente un color de texto con contraste para mejorar la legibilidad. !!! info Este comportamiento es agnóstico al módulo y agnóstico a la variable. Cualquier tabla maestra con una columna configurada con el tipo de referencia **Color** se soporta automáticamente en rejillas y formularios sin desarrollo adicional. @@ -73,9 +73,8 @@ El frontend detecta la configuración de color, añade el parámetro de petició El renderizado de insignias de color se aplica solo a **campos de clave foránea (TableDir / Tabla)** que referencian una tabla maestra con una columna de color configurada. Ejemplos: -- `M_Product_Category_ID` en la tabla Productos. -- `Priority_ID` en la tabla Tareas. -- `C_Currency_ID` en la tabla Facturas. +- `M_Product_Category_ID` en la tabla Productos — la referencia usada a lo largo de esta guía. +- Cualquier otra columna de clave foránea que apunte a una tabla maestra que tenga una columna configurada con el tipo de referencia **Color**. ### Campos no afectados @@ -86,4 +85,5 @@ Esta funcionalidad no afecta a: - Desplegables de lista estática (tipo de referencia *List*) definidos en dominios de referencia. --- -This work is licensed under :material-creative-commons: :fontawesome-brands-creative-commons-by: :fontawesome-brands-creative-commons-sa: [ CC BY-SA 2.5 ES](https://creativecommons.org/licenses/by-sa/2.5/es/){target="_blank"} by [Futit Services S.L](https://etendo.software){target="_blank"}. \ No newline at end of file +This work is licensed under :material-creative-commons: :fontawesome-brands-creative-commons-by: :fontawesome-brands-creative-commons-sa: [ CC BY-SA 2.5 ES](https://creativecommons.org/licenses/by-sa/2.5/es/){target="_blank"} by [Futit Services S.L](https://etendo.software){target="_blank"}. +--- \ No newline at end of file diff --git a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md index 5c0fc1971d..08d03a2817 100644 --- a/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md +++ b/docs/es/user-guide/new-ui/how-to-guides/how-to-configure-color-system.md @@ -3,81 +3,60 @@ tags: - How to - Color System - UI - - Extensibility + +status: new --- -# Cómo Configurar el Soporte al Sistema de Colores en la UI +# Cómo Usar el Sistema de Colores en Workspace UI ## Visión General -El sistema de colores en Etendo permite asignar identificadores visuales (pastillas de color) a registros dentro de una grilla o formulario en Workspace UI, mejorando la experiencia del usuario al destacar información clave. Esta funcionalidad aprovecha el sistema de extensibilidad de Etendo para aplicarse transparentemente sin necesidad de alterar el código base de la interfaz gráfica. - -Un excelente caso de uso (y uno de los más visuales) es aplicarlo a tablas maestras como la **Categoría de Producto (M_Product_Category)** o el **Grupo de Terceros (C_BP_Group)**, ya que estas son muy utilizadas dentro de grillas principales (como la grilla de Productos o la de Terceros/Clientes). - -## ¿Cómo funciona la relación con la otra tabla? - -Para que el color se refleje en la UI, el campo en cuestión en la tabla principal debe apuntar a una tabla maestra a través de una Foreign Key (Referencia **TableDir** o **Table**). - -La implementación actual en Workspace UI y Etendo funciona de manera coordinada gracias a una simbiosis entre la metadata y el frontend de React: - -1. **Inyección de Metadata:** El backend deduce si una tabla hija necesita mostrar un color verificando si el diccionario de datos tiene configurada la columna con la Referencia asignada al tipo "Color". De ser así, inyecta `colorFieldName` indicando cómo se llama esta propiedad hacia la metadata gráfica. -2. **Petición del lado del Front:** Los hooks de obtención de datos (Datasource) en Next.js revisan activamente cada columna definida. Si alguna especifica la metadata `colorFieldName`, el frontend añade al vuelo esa dependencia para solicitarla en la Request a la API (ej: `_extraProperties=M_Product_Category_ID$EM_SMF_Color`). Esto le fuerza al backend a hacer los JOIN correspondientes y volcar el valor final del color al formato JSON. -3. **Renderizado en la Interfaz:** Al momento de procesar las celdas, el frontend comprueba si recibió esta propiedad vinculada al color y le asigna automáticamente el componente visual en forma de 'Tag' (pastilla envuelta), usando el valor hexa recuperado y calculando un texto con buen contraste de legibilidad. +El sistema de colores permite asignar una pastilla de color visual a los registros en una ventana maestra. Una vez asignado un color, cada grilla en Workspace UI que referencie esa ventana mostrará automáticamente una etiqueta coloreada en lugar de texto plano, facilitando el escaneo e identificación de registros de un vistazo. -Esta arquitectura explícita garantiza eficiencia sin corromper el payload estándar. De igual manera, se actualiza en tiempo real tanto en la **Vista de Formulario (Form View)**, en la **Vista de Grilla Principal (Grid View)**, y a la hora de mutar la información por medio de la **Edición en Línea (Inline Editing)** (donde el cliente vuelve a efectuar una petición del registro pidiendo los `_extraProperties` de colores al guardar exitosamente). +![Visión general de pastillas de color en una grilla](../../../assets/user-guide/newui/how-to-guides/color-system/overview-color-badges-grid.png) -## Paso a Paso: Configurar el Color en la Categoría de Productos +!!! info "Prerequisite" + Un desarrollador debe configurar primero la columna **Color** en el diccionario de datos para la ventana maestra. Si el campo de color no es visible en el formulario, contacta con tu administrador del sistema o sigue la [developer guide](../../../developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md). -A continuación, se detalla el procedimiento exacto para probar e implementar esto utilizando la tabla `M_Product_Category` como ejemplo: +--- -### 1. Agregar la columna de Color en el Diccionario de Datos +## Step 1 — Open the Master Record -1. Ingresa a tu entorno de **Etendo ERP Classic** con el rol de **System Administrator** (Administrador del Sistema). -2. Ve a la ventana **Tables and Columns** (Tablas y Columnas). -3. Busca la tabla maestra de interés, en este caso `M_Product_Category` (Categoría de Producto). -4. En la pestaña de *Columns*, crea una nueva columna utilizando tu prefijo de módulo (por ejemplo `EM_CRM_Color` o usar el prefijo de tu módulo de pruebas activo). -5. Asigna a esta nueva columna el tipo de referencia **Color**. Esta es la instrucción clave y mejor práctica para que el sistema reconozca oficial y estructuradamente que este campo soportará colores. -6. La longitud ideal es de 7 o 10 caracteres; suficientes para guardar en su interior un código hexadecimal (`#FF0000`). +1. Inicia sesión en **Etendo Classic** con un rol que tenga acceso a la ventana maestra. +2. Navega a la ventana maestra configurada con una columna de color. +3. Abre un registro existente o crea uno nuevo. -!!!note "Nota clave" - Al utilizar el Reference "Color", el backend detectará explícita y correctamente el propósito de tu columna sin depender del nombre exacto bajo el que la registres, integrándola transparentemente a la metadata que lee el frontend. +--- -### 2. Aplicar la tabla en la BD y mostrar la columna +## Step 2 — Assign a Color -Luego de definir la columna en el diccionario de datos, debes materializarla en la base de datos: -1. Aplica los cambios mediante el proceso clásico compilando en consola (ej. `./gradlew smartbuild` o reconstruyendo de manera apropiada la base de datos). -2. Ve a la ventana **Window, Tab and Field** (Ventana, Pestaña y Campo) dentro del entorno Etendo. -3. Busca la ventana correspondiente, en este caso **Product Category**. -4. Asegúrate de recargar la pestaña o cerciorarte de agregar/crear el registro para la pestaña central de **Field** respecto a esa nueva columna, logrando así que el campo esté listo para ser usado y se visualice en la interfaz del ERP clásico. +1. Localiza el campo **Color** en el formulario. Acepta un código de color hexadecimal (por ejemplo, `#8E44AD`). +2. Introduce directamente el valor hexadecimal deseado o utiliza el selector de color si está disponible. +3. Haz clic en **Save**. -### 3. Prueba de Fuego (¡La Magia Visual!) +![Campo Color en el formulario con un valor hexadecimal introducido](../../../assets/user-guide/newui/how-to-guides/color-system/step2-color-field-form.png) -1. Abre la ventana **Product Category** (Categoría de Producto) en Etendo Classic. -2. Selecciona un registro existente, por ejemplo la categoría titulada "Standard" (o directamente sobre la que decidas usar). -3. Escribe un valor hexadecimal identificativo y bien llamativo sobre el nuevo campo de color. Por ejemplo: `#8E44AD` (Un color púrpura oscuro), y guarda finalmente el registro. -4. Ahora, ve a través del frontend de **Next.js de Workspace UI**. -5. Abre la ventana principal respectiva para **Products** (Productos o `M_Product`). -6. En aquella grilla resultante de productos, busca la columna "Categoría de Producto" (`M_Product_Category_ID`). -7. **¡Sorpresa!** Si esta categoría suele verse como un simple texto azul detallando el contenido "Standard", ahora notarás un cambio muy atractivo. Al pedirse los datos, el frontend detectará que hay una configuración para pedir metadatos de ese color (`_extraProperties`), inyectará la petición extra, la base de datos lo procesará automáticamente por detrás y la UI terminará pintando el texto en una hermosa pastilla redondeada color púrpura. +!!! tip + La UI calcula automáticamente un color de texto con contraste, pero elegir un color de rango medio (ni demasiado claro ni demasiado oscuro) ofrece el mejor resultado visual. -Lo genial de este diseño es que todo ha quedado **totalmente agnóstico de módulos y variables específicas**. Siempre que la tabla maestra cuente con una columna configurada con el Reference "Color", el componente subyacente de UI la aprovechará sin problemas. Uno puede aplicarlo a tablas de Monedas, Métodos de Pago, Vendedores o Almacenes... e instantáneamente brotarán coloreadas en la grilla y formulario sin que se requiera programar ni un solo componente auxiliar. +--- -## Restricciones y Análisis de Alcance +## Step 3 — Verify the Color Badge in Workspace UI -### ¿A qué campos afecta y permite intervenir? +1. Abre **Workspace UI** (el frontend de Next.js). +2. Navega a la ventana que contiene una columna de clave foránea que referencia la ventana maestra. +3. En la grilla, localiza la columna que apunta a la ventana maestra. -La lógica dinámica de inyección de metadata y renderizado de pastillas de color **solo afecta a campos (Fields) definidos como tipo de Referencia Foránea (Foreign Keys / TableDir / Table)** hacia la tabla maestra que ya cuenta con la columna de color configurada. Algunos ejemplos concisos incluyen: +El valor ahora aparece como una **pastilla de color** en lugar de texto plano, reflejando el color hexadecimal que asignaste. -* `M_Product_Category_ID` apuntando en la tabla de Productos. -* `Priority_ID` reflejándose en la tabla de Tareas. -* `C_Currency_ID` visualizándose en la tabla de Facturas. +![Grilla mostrando una pastilla de color en la columna referenciada](../../../assets/user-guide/newui/how-to-guides/color-system/step3-colored-badge-grid.png) -### ¿A qué campos NO afecta o resultan omitidos? +--- -Su dinámica de control actual **NO afectará o incidirá bajo los elementos a continuación especificables**: +## Changing or Removing a Color -* Campos de texto estáticos y regulares (Cadenas o *Strings* convencionales). -* Valores Numéricos, Fechas naturales o datos de tipo Booleanos. -* Listas estáticas predefinidas en el sistema (Es decir, menús desplegables del propio tipo *List* codificados de forma fija o *hardcodeada* bajo los dominios de las Listas de Referencia en el diccionario). +- Para **change** el color: abre el registro maestro, introduce un nuevo valor hexadecimal y guarda. +- Para **remove** el color: limpia el campo de color y guarda. La columna volverá a mostrarse como texto plano en todas las grillas. ---- \ No newline at end of file +--- +This work is licensed under :material-creative-commons: :fontawesome-brands-creative-commons-by: :fontawesome-brands-creative-commons-sa: [ CC BY-SA 2.5 ES](https://creativecommons.org/licenses/by-sa/2.5/es/){target="_blank"} by [Futit Services S.L](https://etendo.software){target="_blank"}. \ No newline at end of file From cfa063c67ee9bd7f06d181a170c1d36f7f71d316 Mon Sep 17 00:00:00 2001 From: Valeria Garcia Date: Wed, 1 Apr 2026 16:08:33 -0300 Subject: [PATCH 13/15] Feature ETP-3486: Update status of color system guide to beta --- .../how-to-guides/how-to-configure-color-system.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md b/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md index e089d6eb62..f82016512c 100644 --- a/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md +++ b/docs/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md @@ -5,7 +5,7 @@ tags: - UI - Extensibility -status: new +status: beta --- # How to Configure Color System Support in the UI From b1a2f48201f75f8b896fbc0b02fae15e8c52f9cc Mon Sep 17 00:00:00 2001 From: etendobot <108091082+etendobot@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:09:35 -0300 Subject: [PATCH 14/15] Feature ETP-3486: Update ES translation --- .../how-to-guides/how-to-configure-color-system.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md b/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md index d020fb697c..70067554ce 100644 --- a/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md +++ b/docs/es/developer-guide/etendo-classic/how-to-guides/how-to-configure-color-system.md @@ -5,7 +5,7 @@ tags: - UI - Extensibility -status: new +status: beta --- # Cómo configurar el soporte del sistema de color en la UI From f81b771ebe92f1043262f86f6939f0057d353355 Mon Sep 17 00:00:00 2001 From: Valeria Garcia Date: Wed, 1 Apr 2026 16:14:03 -0300 Subject: [PATCH 15/15] Feature ETP-3486: Update color badge grid image for user guide --- .../overview-color-badges-grid.png | Bin 20428 -> 29651 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/assets/user-guide/newui/how-to-guides/color-system/overview-color-badges-grid.png b/docs/assets/user-guide/newui/how-to-guides/color-system/overview-color-badges-grid.png index 274527ecd09f67ea2ab9adfe0f652d4834cbe4e5..90c70de8b651d101fbd51d5061044129d4614457 100644 GIT binary patch literal 29651 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