metis-desk/docs/patron-de-listados-de-entidades.md
2026-10-25 01:19:17 +02:00

38 KiB
Raw Blame History

Patrón de listados de entidades

Estándar de Metis Desk. Fuente funcional: patrón acordado con el usuario en esta conversación. La referencia de Activos conserva el estilo Vega, los tokens semánticos y la ficha lateral real de la aplicación.

Dos patrones de presentación de colecciones — v2

Desde el 22 de octubre de 2026 se distinguen dos patrones oficiales:

  • Listado de entidades (Entity Listing): exploración y gestión de colecciones completas. Este documento sigue siendo su fuente normativa; conserva las cuatro bandas, controles, estados y contratos de contexto existentes.
  • Listado compacto (Compact List): consulta rápida de relaciones en dashboards, fichas y paneles. Su fuente normativa complementaria es el patrón de listados compactos, que contiene la comparación, criterios de selección y contrato visual y funcional.

El objetivo de la tarea, los atributos y las capacidades necesarias determinan la elección; ni el número de filas ni estar dentro de una tarjeta bastan. Las reglas de estructura y herramientas siguientes corresponden al listado de entidades, con sus excepciones explícitas de selectores. No se trasladan automáticamente al listado compacto. Las reglas transversales de valores ausentes, permisos, navegación real, acciones accesibles y conservación de contexto siguen siendo aplicables a ambos patrones.

El patrón compacto es normativo para diseño y dispone de componentes compartidos en rdx-ui, adoptados inicialmente en el dashboard de puesto. La normalización v2 original fue documental; esta primera adopción conserva el contrato por defecto de EntityTable. layout="fill" es la composición de selectores existente y DetailPanel density="compact" compacta la tarjeta; ninguno implementa el nuevo patrón. La auditoría v2 registra fuentes, discrepancias, candidatos y decisiones pendientes sin alterar las verificaciones históricas de este documento.

Los listados nuevos y sus operaciones deben aplicar la estructura web por entidades y operaciones. El listado pertenece a <entity>/list/ui; sus altas, detalles e historiales a sus operaciones respectivas. Los formularios y diálogos comunes de alta y edición pertenecen a <entity>/shared/ui, no al fichero del listado ni a un directorio global de componentes.

Estructura obligatoria

La pantalla se divide en cabecera, contenido y pie opcional. La cabecera muestra título y subtítulo breve a la izquierda y acciones globales a la derecha. El alta es la acción primaria, normalmente «+ Añadir [entidad]», y abre un modal; se conservan las etiquetas actuales cuando ya describen una operación concreta. Nunca mostrar el formulario junto al listado.

El título y el botón de alta muestran el mismo icono de entidad antes del texto, tomado del catálogo @repo/rdx-ui/lib/icons y coherente con la navegación. Activos utiliza BoxIcon, Recursos LayersIcon, Personas PersonIcon, Perfiles de usuario WorkProfileIcon y Puestos MonitorIcon. EntityListHeader.icon presenta el icono del título a 24 px, sin encogerse; el botón reutiliza el tamaño de icono de Button. Ambos son decorativos (aria-hidden), conservando el texto y el nombre accesible. No sustituir el icono de entidad por un signo «+» ni añadir ambos. Esta pauta se aplica también a catálogos, configuraciones y sublistados con alta propia; las demás acciones conservan su representación.

El contenido contiene una tabla y cuatro bandas, en este orden:

  1. Búsqueda rápida a la izquierda y filtros propios de la entidad a la derecha. El texto indica los campos buscables. Cuando hay criterios aplicados, Limpiar filtros restaura los valores predeterminados de los criterios de consulta; no cambia el ámbito de compañía ni el perfil desde el que se ha navegado. Una preselección recibida por navegación no se convierte por ello en valor predeterminado del filtro.
  2. Información «Mostrando X-Y de N [entidades]» a la izquierda; Columnas y Ordenar por a la derecha. Estos controles cambian la representación, no los filtros ni los datos.
  3. Cabeceras y filas de la tabla, con densidad uniforme. Los estados vacíos siguen dentro de esta banda.
  4. Información del mismo rango repetida a la izquierda; anterior, páginas, siguiente y elementos por página a la derecha.

El pie opcional está fuera de la tabla y solo aparece cuando existe contenido complementario útil. No añadir estadísticas ni decoración sin una necesidad funcional.

Reglas de interacción

  • Búsqueda y filtros se combinan; filtrar o cambiar tamaño de página vuelve a la primera página. Si una actualización reduce resultados, se ajusta la página para no mostrar un rango inexistente.
  • Contar los resultados filtrados antes de paginar. Cero resultados se expresa como 0-0 de 0. La ordenación actúa sobre todos los resultados filtrados antes de paginar y mantiene un orden estable para empates.
  • Columnas configurables mediante controles con etiquetas; identificación y acciones no se ocultan. No se pierde acceso a una acción por ocultar otra columna. La configuración es local a la vista y no se guarda en datos de negocio. El inventario de activos persiste la visibilidad en localStorage; los demás listados solo lo hacen cuando habilitan explícitamente una clave propia.
  • Solo ofrecer ordenación para valores con significado comparable. Todo listado ordenable comienza con una columna ordenada e indicada mediante aria-sort y el selector de ordenación. El criterio común es Nombre en ascendente cuando existe una columna ordenable con identificador name, aunque no sea la primera columna. Su comparación utiliza el idioma de la interfaz, ignora tildes y mayúsculas y compara numéricamente las cifras dentro del nombre; la ñ conserva su posición propia en español. Los nombres equivalentes mantienen el orden recibido. Si no existe Nombre, se utiliza la primera columna ordenable en ascendente: Persona en teletrabajo y accesos remotos; Departamento en asignaciones. Cada listado puede declarar un criterio propio mediante defaultSort. Las cabeceras alternan ascendente/descendente y «Orden inicial» restaura el criterio del listado.
  • El identificador principal abre la ficha existente si hay una. Usar enlace si existe una ruta real; botón si abre diálogo, detalle en memoria o panel. No inventar rutas.
  • Representar estados mediante indicador visual y texto, nunca solo color. Mantener los avisos de revisión e información contextual.
  • Las relaciones son navegables cuando el destino ya ofrece navegación adecuada; no introducir enlaces ficticios ni nuevas rutas.
  • Acciones de fila siempre al final, con cabecera y celdas alineadas a la derecha y columna anclada al borde derecho durante el desplazamiento horizontal. La columna actions no se oculta ni se ordena. La acción principal se presenta como botón de icono con tooltip y nombre accesible, antes del menú de tres puntos. Usar el lápiz para Editar y el ojo para Abrir o Ver; elegir la operación según la finalidad de cada listado. La principal no se repite en el menú. Las acciones secundarias, incluidas las destructivas, permanecen en el desplegable, cuyo disparador muestra únicamente los tres puntos y conserva etiqueta accesible y título. Si no hay secundarias, no mostrar el desplegable. Conservar las restricciones y los estados deshabilitados existentes. Reutilizar EntityRowActions.primaryAction; el consumidor aporta el icono, el texto traducido y el callback. No convertir acciones de negocio en acciones masivas.
  • Selección múltiple solo cuando una operación real la necesita. No añadir casillas sin consumidor. Mantener separada la selección del activo para su panel lateral.
  • Los diálogos PickerList mantienen una altura estable mediante FormDialog layout="picker" y llenan el área de resultados con EntityTable layout="fill". Buscar, paginar, cargar o quedarse sin resultados no cambia la altura del diálogo. Búsqueda, filtros, paginación y acciones permanecen fuera del desplazamiento de resultados; el cuerpo permite desplazamiento adicional si la ventana es demasiado pequeña.
  • En diálogos PickerList, la selección ocupa siempre la primera columna, con identificador selection, sin ordenación ni ocultación y sin anclaje a la derecha. Toda fila disponible permite activar/desactivar su checkbox o seleccionar su radio mediante onRowClick. Las filas deshabilitadas no cambian la selección; los controles internos conservan su interacción y el teclado, sin un segundo cambio por propagación del clic.
  • Cancelar un modal conserva búsqueda, filtros, página y selección de la lista. Las actualizaciones continúan invalidando las consultas actuales.
  • Las consultas que alimentan un listado usan useListQuery: se vuelven a consultar cada 60 segundos mientras la pestaña está visible y también al recuperar foco o conexión. No se consulta en segundo plano ni se aplica este intervalo a formularios, sesión u otras consultas que no presenten un listado.

Cuando un listado filtra familias mediante pestañas, utilizar ScrollableTabsList de @repo/rdx-ui dentro de Tabs. La barra mantiene una sola fila limitada al ancho del listado, con desplazamiento horizontal, controles laterales solo cuando sean necesarios y la pestaña activa visible. Mantener min-w-0 en la raíz y el contenido para que ni las etiquetas ni la tabla ensanchen la página. La selección conserva las reglas de URL, filtros y paginación del listado. Véase pestañas horizontales desplazables.

Configuración de columnas

EntityTable reutiliza el diálogo de L02.2: búsqueda por etiqueta/keywords, contador de visibilidad efectiva y Restaurar columnas, con aplicación inmediata y Cerrar. La búsqueda solo filtra opciones; no modifica columnas, filtros de datos ni ordenación. Se limpia al terminar la interacción.

El consumidor puede aportar EntityColumn.groupId, keywords y columnGroups (id, label, description?), en orden de presentación y con textos traducidos. No imponer grupos a listados sencillos ni duplicar un campo compartido. Conservar IDs estables y definir un grupo principal determinista; contextos alternativos pueden ser keywords.

Restaurar recupera los defaults actuales del consumidor, no todas las columnas; respeta hideable:false y persiste mediante la clave propia existente, sin afectar otras tablas. Las obligatorias muestran estado deshabilitado e indicación accesible. El resumen cuenta columnas expuestas, incluidas obligatorias/acciones, pero excluye selection, control interno del picker. Usar altura estable, búsqueda y cierre accesibles y scroll interno de opciones; comprobar la superficie operativa en móvil. No se incluye reordenación ni densidad.

Celdas sin valor

En cualquier listado, tabla, sublistado o PickerList, una celda sin valor muestra exclusivamente un guion largo (—, U+2014), cualquiera que sea la causa de la ausencia. No mostrar «Sin indicar», «Sin valor», «Sin especificar», «Sin asignación», «Sin fecha», «Sin logotipo» ni equivalentes en otros idiomas. El signo es común a es/en y no requiere traducción.

EntityTable aplica este criterio cuando render devuelve null, undefined, un booleano sin representación visual, una cadena vacía o formada solo por espacios, un array vacío o un fragmento sin contenido. Los consumidores deben devolver ausencia directamente en lugar de envolverla en componentes vacíos o convertirla en textos sustitutorios. Los renderizadores de contenido compuesto son responsables de aplicar el mismo criterio a sus valores opcionales.

El cero y los valores reales permanecen visibles; los booleanos de negocio se presentan con sus etiquetas o estados correspondientes. Se mantienen los estados de negocio explícitos, por ejemplo «Inactivo» o «Abierto». Esta pauta se refiere a celdas de datos y no sustituye los mensajes de carga, error, ausencia de registros o búsqueda sin resultados, ni los placeholders de formularios.

Común y específico

En selectores locales, EntityTable layout="fill" utiliza la composición compacta de L02.1: búsqueda/configuración agrupadas, un rango en el pie y paginación con anterior/siguiente, página actual y tamaño etiquetado. En cajas estrechas se ordena mediante las cabeceras; el selector adicional de orden aparece cuando hay capacidad. Esta excepción no modifica las bandas de los listados generales. entityLabel admite una cadena o función del total filtrado para que el consumidor aporte singular/plural traducidos. La identidad mínima se protege por columna con hideable:false; no se obliga a mostrar todas las columnas ni se borran preferencias.

Común: distribución, cabecera, cuatro bandas, márgenes, altura base de filas, búsqueda, limpieza, contador, columnas, ordenación, paginación, accesibilidad y estados.

Específico: título, subtítulo, ámbito, alta y acciones globales, campos buscables, filtros, columnas, formatos, acciones de fila, avisos y destino de ficha. Las columnas conservan la información funcional de cada pantalla. Licencias y aplicaciones continúan dentro del listado Recursos; no crear pantallas para entidades que no existen.

Responsive, accesibilidad y estados

Cabecera y bandas se apilan en anchuras pequeñas. Los filtros ajustan sus controles, la tabla permite desplazamiento horizontal dentro de su contenedor y las celdas largas pueden partir texto. El inventario de activos decide panel o diálogo por el content box exterior estable, según V01.3: mínimo 1144 px, con 800 de tabla, 24 de separación y 320–400 de panel. No medir la columna que encoge ni decidir por viewport. Una pérdida de capacidad conserva selección, cierra el panel y ofrece reapertura explícita; nunca abre un modal por resize. El detalle abierto pasa de diálogo a panel al ganar capacidad, con transferencia de foco y liberación de modalidad. Mantener una sola tabla y una sola presentación interactiva del detalle. Recursos aplica V01.4: 640 px de tabla, 24 de separación y panel 320–400, con mínimo W=984. Ambos utilizan useContextualDetail de rdx-ui, sin duplicar observers ni políticas CSS/React. La selección, rutas y operaciones pertenecen a cada módulo: el nombre de recurso conserva selección en URL y su ficha explícita es un diálogo; no copiar la navegación a página de activos. No generalizar estos presupuestos a otros listados.

Usar tabla semántica con nombre accesible, th con scope, controles etiquetados, foco visible, acciones por teclado y página actual con aria-current. Los elementos decorativos se ocultan al lector. Los menús y modales conservan manejo de foco de Base UI. No depender del color para comunicar información.

Carga inicial y errores se presentan dentro del contenido sin afirmar que no hay registros. El vacío distingue ausencia de datos y búsqueda sin resultados. Mantener el mensaje y la recuperación de errores de cada consulta; no inventar resultados ni endpoints. Las recargas conservan datos y controles cuando la integración existente lo permite.

L02.3 define el estado explícito de Activos y Recursos: loading, ready, refreshing, unavailable y stale. Mantener la instancia de tabla, búsqueda, cabeceras conocidas y espacio de paginación desde el GET inicial. Skeletons decorativos sin acciones, nombres ni totales inventados; controles dependientes de datos pendientes deshabilitados con explicación. Separar errores del inventario, catálogo y referencias accesorias. Una dependencia de red pendiente no bloquea todas las filas.

En refetch conservar la caché y el contexto sin copiar DTO a estado React. El fallo posterior debe indicar «últimos datos disponibles» y ofrecer reintento dirigido. Situar error y Reintentar fuera del ancho desplazable de las columnas; no esconderlos en una celda ancha. Al reintentar, enfocar la búsqueda persistente para evitar que la desaparición del botón deje el foco en el documento. Las denegaciones explícitas siguen el contrato de permisos del módulo y no se representan como vacío ni como una copia consultable sin autorización.

Limpieza de criterios — L03.3

Antes de conectar filtros, distinguir criterios de datos, preferencias, ámbito y estado provisional. Cada consumidor define sus defaults, incluyendo controles que amplían el conjunto, como archivadas o cerradas. Declarar filtersApplied, filterKey y onClearFilters cuando exista un criterio propio de la tabla.

  • Limpiar vacía búsqueda y restablece exclusivamente criterios propios; conserva compañía, perfil/persona/activo de origen, tipo de colección y selección contextual de ruta.
  • Cambiar criterios reajusta página, conservando ordenación válida, tamaño y columnas. Con navegación controlada, el consumidor usa sus setters existentes para ajustar URL/página.
  • Categoría/entorno/recurso de accesos y tabs de tipos de catálogo conservan sus controles específicos; no borrar todos los parámetros de URL para limpiar una búsqueda.
  • Mantener visible el estado de los controles y el contador; no añadir barras o chips por rutina. El botón Limpiar filtros debe funcionar también si solo hay un checkbox activo.
  • La tabla enfoca búsqueda al limpiar con preventScroll. No borrar selección provisional del picker ni crear nuevas regiones de anuncios por este motivo.
  • Una consulta de espacios conserva su texto y puede limpiarse; al elegir el mensaje de vacío se evalúa la búsqueda efectiva. Un ámbito sin coincidencia tampoco debe anunciar que no existe ningún registro global.
  • Durante carga/refetch o error conservar los estados de L02.3 y los criterios del usuario; no interpretar datos provisionales como conjunto definitivo.

Matriz de consumidores, defaults y comprobaciones: L03.3. No requiere un motor universal ni nuevas props de entidad en rdx-ui.

Comparación textual local — L03.2

La comparación textual local sigue L03.2: reutilizar createTextMatcher de @repo/rdx-ui/lib/text-search para búsquedas parciales sin acentos vocálicos ordinarios ni caja y con trim exterior. Conservar ñ, puntuación técnica, consulta visible/URL y campos buscables del consumidor. No filtrar de nuevo una página remota ni alterar la ordenación con Collator. El helper no sustituye los filtros de negocio.

Contexto navegable y retorno — L03.1

Activos, Recursos y Personas, y desde L04.1 Puestos, Perfiles y el directorio de Compañías, habilitan EntityTable.navigation explícitamente. Búsqueda, filtros, plantilla, sort/direction y página pertenecen a la URL; tamaño y columnas conservan sus preferencias existentes. useListLocation de core enlaza parámetros elegidos por el consumidor; rdx-ui valida columnas ordenables, dirección y página, sin conocer rutas o DTO. La normalización espera datos/metadatos válidos; una carga provisional no fuerza página 1.

Los cambios de consulta usan replace; fichas/secciones usan push. useListReturn conserva coordenadas y origen de foco por entrada de History, fuera de la caché de datos. Restaurar solo con geometría disponible, limitar scroll y enfocar el mismo registro verificado o la búsqueda; nunca seleccionar otra fila arbitraria. Respetar interacción en curso y finalFocus de Base UI. Un refetch no reinicia el contexto ni vuelve a aplicar el foco inicial.

La adopción no es automática. Los pickers mantienen un borrador local durante su apertura. Los sublistados mantienen criterios independientes del padre; las composiciones adoptadas en L04.3 conservan ese estado de lectura por colección y entrada de History, sin convertirlo en parámetros del listado padre. No heredar su búsqueda, orden ni página. Véase el inventario de cierre L04.4 para distinguir consumidores comprobados, excepciones y cobertura pendiente. Los informes L02–L04.3 conservan sus resultados históricos; no acreditan automáticamente otros consumidores.

Si búsqueda y filtros son externos, navigation.onClearFilters puede realizar la limpieza atómica de criterios y página mediante un único replace. Conserva ordenación, ámbito y preferencias; EntityTable devuelve el foco a búsqueda. Sin este callback opcional se conserva el comportamiento previo de los consumidores locales y pilotos.

Inventario de listados y ubicaciones actuales

La tabla siguiente identifica composiciones, no una certificación de todas sus capacidades. La matriz L04.4 distingue cobertura actual, excepciones y pendientes por consumidor y capacidad.

La aplicación navega por espacios y secciones mediante rutas URL independientes, según Rutas del cliente. Los componentes siguientes se componen desde CompaniesWorkspace, CompanyDetail o IdentityWorkspace; altas, ediciones e historiales conservan sus modales.

Listado / ámbito Componente y ubicación actual Aplicación
Compañías CompaniesPage Sí
Personas/contactos PeopleSection Sí
Departamentos DepartmentSection Sí
Sedes SiteSection Sí
Usuarios internos UserManagement Sí
Activos AssetInventoryPage Sí; conserva panel lateral
Puestos de trabajo WorkstationsPage Sí
Recursos, incluidas aplicaciones y licencias ResourcesPage Sí; pestañas por plantilla y «Todo», panel lateral y ficha modal móvil
Campos y plantillas de recursos, global/compañía ResourceCatalogPage Sí; dos secciones
Campos, plantillas y relaciones de activos, global/compañía AssetCatalogPage Sí; tres secciones
Cuentas y accesos / catálogos informáticos AccessWorkspacePage Sí; cuenta, titularidad, grupo, pertenencia, autorización, necesidad, cobertura, entorno, sistema, tipo, permiso y plantilla
Perfiles de usuario WorkProfilesPage Sí
Correo por perfil MailConfigurationsPage Sí, también entrada desde perfil
Carpetas por perfil FolderMappingsPage Sí, también entrada desde perfil
Impresoras por perfil PrinterConfigurationsPage Sí, también entrada desde perfil
Aplicaciones por perfil ApplicationConfigurationsPage Sí, también entrada desde perfil
Certificados por perfil CertificateConfigurationsPage Sí, también entrada desde perfil
Teletrabajo TeleworkAuthorizationsPage Sí, conserva ámbito de persona
Accesos remotos RemoteConnectionsPage Sí, conserva ámbito de persona
Procesos de personas ProcessesPage Sí; su detalle es excepción
Plantillas de procesos ProcessTemplatesPage Sí
Marcas globales BrandCatalogPage Sí; EntityListHeader y EntityTable, filtro de estado y modales
Asignaciones departamentales PeopleSection → PersonDetails Sublistado de ficha; conserva sus operaciones y adopta tabla común

Los enlaces apuntan a las ubicaciones actuales bajo modules/<module>/src/web/<entity>/. No hay listados separados de equipos, software, incidencias o ubicaciones adicionales: corresponden a Activos, Recursos o Sedes.

Excepciones justificadas

No son pantallas de listado sencillo: HomePage (estado técnico), WorkEnvironmentPage (resumen de preparación), fichas CompanyDetail/PersonDetails/AssetDetail/ResourceDetail, historiales y revisiones, pasos/instrucciones de plantillas, tareas de ProcessDetail y selectores de formularios.

AssetRelationships, AssetSupport, MailboxRelations son bloques contextuales de ficha, sin gestión independiente de un conjunto; mantienen su presentación contextual. CompanyInventory es un adaptador de consultas, no un listado adicional. Las barras laterales, navegación, formulario de acceso y cambio de contraseña tampoco adoptan el patrón.

Las instrucciones/historiales que antes estaban expandidos dentro de catálogos se mantienen accesibles desde cada fila; no desaparecen por pasar a tabla.

Implementación y verificación

Se reutilizan los componentes propios de @repo/rdx-ui, incluidos SelectWithAction y EntityTable, sobre Table, Button, Input, Dialog y los tokens existentes de @repo/shadcn-ui. Las consultas, DTO, endpoints, permisos y mutaciones permanecen en sus módulos. Los componentes comunes no conocen entidades ni invocan API.

La validación debe incluir tipos, estilo, pruebas y compilación, además de interacción real para búsqueda/limpieza, columnas, ordenación, cambios de página/tamaño, apertura/cancelación de fichas y panel de activos. Verificar español e inglés y una anchura móvil.

Migración realizada

Se han adaptado las 25 familias de listados del inventario y el sublistado de asignaciones departamentales. Los catálogos y accesos reutilizan sus componentes para las distintas secciones y ámbitos; las rutas distinguen el ámbito sin crear nuevas entidades. El inventario conserva la ficha lateral y su modal móvil. Las fichas, historiales y bloques contextuales de las excepciones mantienen su función.

Componentes compartidos: EntityListHeader y EntityTable; EntityTableConfiguration para columnas y orden; EntityTableContent para tabla semántica; EntityListPagination, EntityRowActions, EntityAction y EntityStatus para controles. useEntityTable concentra filtros locales, ordenación estable, columnas visibles y paginación. entity-list.ts contiene textos es/en y cálculo de rangos. No se añade selección masiva sin una operación que la consuma.

La primera columna tiene anchura mínima para evitar nombres ilegibles. El desplazamiento horizontal permanece dentro de la tabla. El panel de activos ajusta su contenido y sus botones a la anchura disponible.

Verificación de la entrega (7 de octubre de 2026)

  • pnpm typecheck: correcto, 10 tareas.
  • pnpm test: correcto, 195 pruebas, incluidas HTTP/MariaDB en la base de pruebas; 9 tareas. Las nuevas pruebas cubren límites de paginación, rangos repetidos, búsqueda local/controlada, traducción y distinción de carga/error/vacío.
  • pnpm build: correcto, 2 tareas. Se mantiene el aviso de tamaño del paquete web.
  • pnpm lint y pnpm check: ejecutados; siguen fallando por problemas previos ajenos a la migración. La comprobación específica de todos los archivos de código modificados y nuevos es correcta. No se han añadido supresiones.
  • Navegador: revisadas todas las familias de pantallas y las secciones de cuentas/accesos; búsqueda, filtros específicos y limpieza, columnas bloqueadas/configurables, ordenación y recuperación del orden inicial, segunda página, tamaño de página y opción vacía.
  • Navegación comprobada a persona y activo; edición/copia en modal y cancelación sin guardar. Las definiciones de serie no ofrecen edición y las plantillas globales no ofrecen edición desde una compañía.
  • Español/inglés y anchura móvil de 390 px comprobados; el activo abre la ficha modal en móvil. En escritorio la página no presenta desbordamiento horizontal; la tabla conserva su propio desplazamiento.
  • No se han creado ni alterado registros de negocio durante la revisión del navegador.

Ajuste inicial de acciones de fila (7 de octubre de 2026)

La regla vigente de acción principal visible figura en Reglas de interacción; este apartado registra la verificación del ajuste inicial.

Disparador solo con icono de tres puntos, etiqueta accesible y título conservados. Columna actions siempre al final, compacta, alineada y anclada a la derecha; no admite ocultación, búsqueda u ordenación. El fondo opaco respeta hover, menú abierto y selección del inventario.

Verificación: 204 pruebas correctas, tipos y compilación correctos; los cinco archivos de código/estilos de este ajuste pasan Biome. Las comprobaciones globales conservan los errores anteriores. En navegador se han comprobado apertura/cancelación de edición, botón sin texto, posición de cabecera y celdas antes y después del desplazamiento horizontal a anchura móvil, y color del activo seleccionado. No se modificaron registros de negocio durante la revisión.

Selector de activos

Los formularios que seleccionan activos usan un diálogo con el mismo AssetList del inventario. Reutiliza EntityTable, búsqueda, pestañas por plantilla, columnas y paginación. La selección provisional no cambia el formulario hasta confirmar, ni altera la URL o filtros del listado padre. Cada consumidor restringe los candidatos y declara selección única o múltiple con límite. Véase componentes de interfaz.

Tickets, intervenciones y sus plantillas se conservan en el archivo de funcionalidades, fuera del inventario activo.

Columna visual del tipo de activo

En AssetList, el icono de plantilla ocupa una columna icon compacta antes de Nombre, con cabecera accesible y tooltip con el nombre de plantilla, disponible con puntero y teclado. La columna Plantilla conserva solo el nombre. La columna visual no se ordena ni se oculta y no sustituye la ordenación inicial por Nombre. En PickerList, la selección permanece siempre por delante del icono.

Campos adicionales disponibles en Activos

El control Columnas del inventario y de los selectores de activos incluye todos los campos activos del catálogo y los conservados en instantáneas de activos, además de los datos generales y de interfaces. Las columnas adicionales se ofrecen desmarcadas inicialmente; el usuario elige las que necesita. La identidad de cada columna de característica deriva del UUID de campo, nunca de su nombre. Los filtros por plantilla no reconstruyen el conjunto de columnas ni borran la elección local. No agregar columnas de historial completo a las filas: el historial sigue consultándose en la ficha correspondiente.

Adopción proporcional en catálogos y configuraciones — L04.2

Los catálogos navegables de activos, recursos y accesos y el listado de Procesos usan los contratos opcionales de URL y retorno existentes. Orden/página se validan contra las columnas de la colección; cambiar pestaña descarta criterios incompatibles de forma atómica. Las preferencias de columnas se separan por compañía/global y colección. Las restricciones explícitas de perfil/persona/recurso/entorno no se eliminan al limpiar criterios voluntarios.

Marcas, plantillas de procesos y las configuraciones con editor/historial modal conservan consulta/orden/página locales cuando no existe navegación que desmonte la colección. La instancia local se identifica por su ámbito obligatorio. El estado de consulta incluye las referencias imprescindibles, conservando la tabla durante carga/refetch/error.

Restaurar foco/scroll requiere también estabilidad del contenedor propietario. La señal opcional layoutReady de los consumidores navegables permite esperar sus consultas de composición sin modificar Core, shell ni los datos de la tabla. No sustituye la validación de disponibilidad del registro. Consumidores, excepciones y evidencias en L04.2.

Paginación remota sin total

Si una API aprobada devuelve items y nextCursor sin total, se utiliza CursorEntityTable con la misma estructura de bandas. El pie comunica el rango de filas y la página actual, con Anterior/Siguiente y tamaño de página. No ofrece salto a última página ni un total estimado. Los criterios se aplican en servidor antes de paginar; nunca se ordena o filtra solo la página cargada como si fuera la colección completa. La búsqueda y los cambios de filtro, tamaño u orden reinician cursor e historial de páginas. La vuelta de la ficha, cuando el consumidor integra el contrato de retorno, conserva los criterios y la página; al recargar un enlace sin pila de cursores, Anterior puede volver al inicio. Se documenta este límite en la pantalla consumidora.

Sublistados y relaciones — L04.3

El estado de lectura de una ficha se liga a su entrada de History y a una clave por colección. No hereda la búsqueda, orden o página del listado padre. Los datos siguen en TanStack Query; los borradores de selección solo viven durante la apertura del diálogo. Los cursores recibidos se conservan como tokens del proveedor, sin totales, offsets ni ordenación local de una página remota.

El retorno de la ficha y del inventario pueden coexistir en la misma entrada, con registros independientes. La restauración espera la composición real y utiliza el contenedor de scroll más próximo y la tabla de origen. Un panel contextual conserva la orientación inicial de V01; solo restaura su sublistado si existe retorno guardado. La desaparición del registro ofrece una alternativa de foco contextual.

Revalidar una opción visible antes de confirmar; fuera de página se conserva el borrador legítimo y la operación propietaria vuelve a validar su vigencia. Cancelar nunca equivale a guardar. Estados, consumidores verificados y excepciones en L04.3.

Incorporar o revisar un consumidor

Este documento contiene el contrato vigente. Los informes L02–L04 explican decisiones, mediciones y límites de cada entrega, sin convertirse en requisitos acumulativos distintos. Antes de implementar, clasificar la superficie y comprobar las APIs instaladas:

Superficie Composición y propietario Comprobaciones mínimas
Listado autónomo local EntityListHeader y EntityTable; colección completa en TanStack Query. El consumidor aporta campos, filtros y acciones. navigation enlaza criterios con useListLocation cuando la ruta tiene contexto compartible; tamaño y columnas conservan sus preferencias. Tres bandas, identidad protegida, orden/página, consulta directa/recarga, Atrás/Volver, estados, teclado y scroll dentro del contenedor.
Catálogo Misma tabla con ámbito y pestañas propios. Las acciones respetan herencia, vigencia y retirada; edición modal. No mezclar preferencias de ámbitos incompatibles. Verificar restricciones y retorno sin exigir ruta de ficha a un catálogo que no la tiene.
Sublistado de ficha Estado de lectura por propietario y colección mediante el adaptador existente y useEntryState. Datos en Query, nunca en History. Integrar retorno de la ficha mediante useListReturn donde hay enlaces relacionados. Independencia del padre y de otros sublistados, origen por identidad, composición lista antes de restaurar, alternativa de foco si desaparece el registro.
Selector local PickerList con búsqueda inicial y selección provisional local. Identidad visible, columna selection compacta y confirmación/cancelación explícitas. Altura útil, clic de fila no interactiva, Space/Enter/flechas según primitiva, Escape, elegibilidad y foco del disparador al cerrar. No persistir el borrador.
Colección remota RemoteOptionPicker, CursorPagination o CursorEntityTable según su finalidad y el contrato existente del proveedor. Criterios aplicados antes de paginar. Cursores opacos, página anterior/siguiente, cancelación, respuestas obsoletas, error/reintento y confirmación fuera de página. No inventar un total ni filtrar/ordenar solo la página cargada.
Resumen o historial Vista compacta o cronología con identidad de evento/revisión y orden de negocio. Ausencias —, estados y acciones propias, teclado/foco y desbordamiento. No añadir herramientas de tabla completa por uniformidad.

Las excepciones requieren motivo funcional; la falta de prueba o de implementación es un pendiente. Una fila seleccionada debe conservar contraste de texto, enlaces, acciones y foco en ambos temas, incluidas sus celdas fijadas. Reutilizar la receta contextual existente antes de duplicar estilos. No modificar tokens globales o vendor para compensar un consumidor.

La validación distingue estructura inicial, refetch con datos marcados como anteriores, fallo inicial, recuperación, vacío, cero coincidencias y denegación. Un 401/403 impide seguir mostrando filas de la caché como si el acceso estuviera permitido. No forzar foco al actualizar datos. La matriz de cierre acredita únicamente los consumidores y escenarios expresamente ensayados.