diff --git a/docs/auditoria-listados-l01.md b/docs/auditoria-listados-l01.md index 4f8532c..78f8543 100644 --- a/docs/auditoria-listados-l01.md +++ b/docs/auditoria-listados-l01.md @@ -769,3 +769,21 @@ El informe documenta suites, capturas abiertas, geometría y fallos técnicos pr **V12 queda resuelto en ese alcance; V05 y V07 siguen pendientes y V08 conserva su cierre L02.2.** No se generaliza la adopción a todos los listados ni se implementan L03/L04. +## Seguimiento L03.1 — Contexto de listados V05 + +El 22 de octubre de 2026 se implementa y verifica [L03.1](contexto-listados-l03-1.md). +**V05 queda resuelto en Activos, Recursos y Personas para los escenarios comprobados**; +el resto de consumidores permanece pendiente. Se conservan las reproducciones históricas +de esta auditoría como línea base, incluida la pérdida vertical original. + +URL conserva búsqueda, filtros, sort y página; las preferencias mantienen sus claves y el +retorno usa la entrada de History para scroll/foco, sin caché adicional. Playwright MCP +verifica siete resoluciones, Atrás/Adelante/Volver, recarga, URL compartida/inválida, registros +retirados mediante GET, errores/refetch y paneles. En móvil recupera X=40/Y=150 y el enlace +de origen; en 1920 el scroll vertical válido es cero. La reproducción previa de esta entrega +sí confirma sort/página/foco/horizontal perdidos, pero no reproduce la pérdida vertical de L01. + +Se verifican 14 métodos nuevos distintos y 33 regresiones con datos sintéticos abundantes. +El informe diferencia ejecuciones finales correctas, intentos intermedios, capturas y deuda +técnica global. **V07 sigue pendiente; V08 y V12 mantienen su alcance anterior.** No se +declara restauración universal ni se implementan L03.2/L04. diff --git a/docs/auditoria-ui-ux-visual.md b/docs/auditoria-ui-ux-visual.md index 857cbf7..c9f585f 100644 --- a/docs/auditoria-ui-ux-visual.md +++ b/docs/auditoria-ui-ux-visual.md @@ -540,3 +540,21 @@ Se utiliza una instalación propia desechable con quince compañías y una princ técnicos reales, diferenciando errores de red provocados y fallos globales preexistentes. **V05/V07 continúan pendientes; V08 mantiene su estado L02.2.** No se declara WCAG completo, rendimiento de producción ni adopción universal del nuevo contrato. +## Seguimiento L03.1 — Contexto de listados V05 + +El 22 de octubre de 2026 se completa [L03.1](contexto-listados-l03-1.md) para Activos, Recursos +y Personas. **V05 se resuelve únicamente en estos pilotos y escenarios verificados**. Los +resultados históricos anteriores se conservan; otros consumidores quedan inventariados para L04. + +La validación autenticada con Playwright MCP compara filas, filtros, Nombre descendente, +página 3, scroll X/Y y foco antes/después en siete resoluciones de 320×640 a 1920×1080. +Comprueba Atrás, Adelante, Volver, recarga con carga retenida, URL directa/compartida, +normalización, preferencias, desaparición simulada y 503 posterior. Recursos conserva su +selección contextual y modalidad; Personas recupera contactos y página 2 con foco de origen. + +Se utiliza una única instalación desechable con quince compañías y una principal con +50 personas, 51 activos y 66 recursos. Se verifican 14 métodos nuevos distintos y 33 +regresiones, se abren capturas representativas y se registran las ejecuciones y límites +reales en el informe. No se declara cumplimiento WCAG completo ni rendimiento de producción. +**V07 continúa pendiente; V08/V12 mantienen su alcance anterior.** Los fallos globales +preexistentes de vendor, lint/check y SSR de Compañías permanecen documentados. diff --git a/docs/componentes-de-interfaz.md b/docs/componentes-de-interfaz.md index ce6e72b..d9569f6 100644 --- a/docs/componentes-de-interfaz.md +++ b/docs/componentes-de-interfaz.md @@ -1180,6 +1180,28 @@ almacenamiento contenga una preferencia contraria. Los datos inválidos o el alm bloqueado no impiden utilizar la tabla. Cambiar de clave carga las preferencias de la nueva vista sin escribir sobre ellas la selección de la anterior. +### Contexto de listados — L03.1 + +`EntityTableNavigation` (`@repo/rdx-ui/lib/entity-table-navigation`) expresa valores externos +de orden y página, callback `onChange` y disponibilidad `ready`. `EntityTable` / `useEntityTable` +lo aceptan opcionalmente; sin él mantienen estado no controlado. El hook admite inicialización +`initialSorting` / `initialPagination`; conserva modelos nativos de TanStack Table, tamaño y +visibilidad. No contiene endpoints, query keys ni nombres de parámetros de negocio. + +`useListLocation` y `useListReturn` (`@metis/core/client`) enlazan, respectivamente, parámetros +declarados por el consumidor y restauración DOM por scope/entrada de History. El segundo +recibe rootRef y señales de disponibilidad/verificación, sin cargar registros. Se espera +layout/fuentes, se limita scroll y se conserva el foco ya aplicado durante refetch. Una +respuesta fallida permite volver a búsqueda, sin confirmar la existencia de una fila en caché. + +`BrowserLink navigation="return"` conserva semántica de anchor y reutiliza historial solo +si su entrada anterior coincide con el destino. Los modos de navegación ordinarios siguen +intactos. `data-entity-id` identifica filas para orientación, sin almacenar referencias DOM. + +Activos, Recursos y Personas son pilotos; la navegación contextual de Recursos mantiene +su instancia y sus políticas de Base UI. Los pickers y sublistados no adoptan automáticamente +la consulta de su padre. Contratos URL, preferencias, API y evidencias en [L03.1](contexto-listados-l03-1.md). + ### Estados de consulta de listados — L02.3 `EntityListState` y `entityListState` (`@repo/rdx-ui/lib/entity-list-state`) separan diff --git a/docs/contexto-listados-l03-1.md b/docs/contexto-listados-l03-1.md new file mode 100644 index 0000000..6803858 --- /dev/null +++ b/docs/contexto-listados-l03-1.md @@ -0,0 +1,344 @@ +# L03.1 — Persistencia y restauración del contexto de listados (V05) + +Fecha: 22 de octubre de 2026. Pilotos: Activos, Recursos y Personas. +Referencias: [L01](auditoria-listados-l01.md), [L02.2](configuracion-columnas-l02-2.md), +[L02.3](estados-listados-l02-3.md), [rutas](rutas-del-cliente.md) y +[listados](patron-de-listados-de-entidades.md). + +## 1. Resumen ejecutivo + +Los pilotos añaden ordenación y página a su consulta navegable. Personas incorpora también +búsqueda y Solo contactos a la URL, conservando su fallback local cuando está embebida fuera +de una ruta propia. El tamaño de página y la visibilidad mantienen sus preferencias existentes. +El retorno utiliza coordenadas e identidad de foco en la entrada de `history.state`, sin DTO, +referencias DOM persistidas ni otra caché remota. + +Activos conserva su ficha completa; Recursos conserva selección URL y panel/diálogo contextual. +No se añaden rutas, endpoints, dependencias, cambios de backend o modificaciones vendor. +Los archivos previos del usuario en `docs/auditorias/` se conservan sin modificación. + +## 2. Auditoría del estado anterior + +| Consumidor inspeccionado | URL antes de L03.1 | Estado local / persistido | Desmontaje, retorno y acceso directo anteriores | +| --- | --- | --- | --- | +| Activos | `q`, `template`; ficha con esos parámetros | Sort/página en `useEntityTable`; selección contextual local; tamaño global y columnas en localStorage | Ficha completa desmonta listado. Atrás recuperaba filtros, pero sort ascendente/página 1/foco BODY; horizontal se perdía. | +| Recursos | `q`, `template`, selección en pathname | Sort/página locales; apertura de panel y diálogo explícito temporales; tamaño persistido | Seleccionar no desmonta tabla. Cierre compacto usa historial; cierre inline oculta panel conservando selección/ruta. Recarga mantenía filtros, pero no sort/página. | +| Personas | Selección en pathname | Búsqueda y Solo contactos en componente padre; sort/página en tabla; tamaño persistido | Detalle sustituye tabla. Padre podía conservar filtros, pero se perdían al reconstruirse; sort/página se reiniciaban. | +| Puestos | Ficha en pathname | Búsqueda y editor locales; sort/página locales; tamaño persistido | Hay ficha completa; la reconstrucción pierde el estado local. Pendiente L04. | +| Perfiles | `q`, `archived`, perfil/configuración en pathname | Sort/página locales; diálogos locales; tamaño persistido | Entorno/configuración sustituye vista. URL reproduce filtros/destino, no todo el contexto. Pendiente L04. | +| Compañías | `q`, `activeOnly`, `companyId` | Tabla/controlador y selección local según consumidor; tamaño persistido | Cambiar espacio reconstruye directorio. Filtros URL sobreviven; sort/página/scroll no tienen contrato completo. | +| Catálogo de activos | `q`, `tab` | Sort/página y editor/detalle/historial locales | Los diálogos no cambian ruta; cambiar catálogo/sección puede desmontar. URL no representa sort/página. | +| Sublistado de puestos de una persona | Ninguna consulta propia navegable | Datos de queries compartidas; controles locales del sublistado | Se desmonta con la ficha. No debe heredar la página/orden del listado de Personas. | + +Los datos remotos proceden de TanStack Query: inventarios/catálogos de Activos y Recursos, +compañía y referencias de puestos/perfiles. No son preferencias ni contexto de navegación. +Un panel/diálogo no equivale a abandonar la página; no se cambia ese contrato para uniformar. +Esta matriz combina inspección del código y L01. Los consumidores ajenos a los tres pilotos +no se presentan como una nueva validación visual con listados poblados. + +La nueva reproducción previa, con 15 compañías y 50 personas/51 activos/66 recursos, conserva +las medidas históricas de L01. En esta instalación hay 40 portátiles con `q=AUDIT-ASSET`: + +| Dimensión | Antes de abrir ficha | Atrás anterior, 1440×900 | Atrás anterior, 390×844 | +| --- | --- | --- | --- | +| Orden / página | Descendente / 3 | Ascendente / 1 | Ascendente / 1 | +| Búsqueda / plantilla | AUDIT-ASSET / Portátil | Conservadas | Conservadas | +| Scroll X | 0 escritorio, 40 móvil | 0 | 0: pérdida de los 40 px | +| Scroll Y | 100 | 100 en esta muestra | 100 en esta muestra | +| Foco | Enlace AUDIT-ASSET-24 | BODY | BODY | + +La muestra nueva no reproduce la pérdida vertical concreta de L01; las pruebas posteriores +desplazan deliberadamente la ficha a otra coordenada para comprobar una restauración real. + +## 3. Arquitectura del contexto + +| Responsabilidad | Fuente única | +| --- | --- | +| Búsqueda/filtros/plantilla/sort/página | URL, únicamente en consumidores habilitados | +| Tamaño / columnas | Preferencias ya existentes | +| Scroll y origen del foco | `history.state.metisListReturn`, con versión y ámbito | +| Registros y referencias | TanStack Query y sus query keys existentes | +| Modalidad, selección y paneles | Contratos V01/V06 del módulo y Base UI | + +`@metis/core/client` conserva su History API. `useListLocation` enlaza los nombres de +parámetros que aporta el consumidor; no conoce TanStack Table ni columnas. rdx-ui recibe +un `EntityTableNavigation` presentacional (`values`, `onChange`, `ready`), valida metadatos +y utiliza los modelos/callbacks nativos de TanStack Table. No se añade dependencia core→rdx-ui. + +## 4. Contrato URL + +| Parámetro de los pilotos | Validación / valor inicial | +| --- | --- | +| `q` | Búsqueda existente; límite de ruta 200 caracteres y semántica propia intacta. | +| `template` | Activos/Recursos: identidad conocida en el catálogo. Se conserva pendiente de metadatos; después se normaliza a Todo si no existe. | +| `contactsOnly` | Personas: `true`; ausente significa false. False/malformados se normalizan; no se añade a otros consumidores. | +| `sort` | ID existente y ordenable; admite `characteristic-` estable. Acciones/columnas desconocidas vuelven al orden inicial. | +| `direction` | `asc` o `desc`, con columna válida. Una pareja inválida usa el orden inicial. | +| `page` | Entero decimal positivo, índice compartible desde 1, seguro en JavaScript; se acota al conjunto disponible. | + +El orden inicial sigue las reglas existentes: declaración explícita, Nombre, primera columna +ordenable o ausencia de orden. Se omiten sort/direction predeterminados y página 1. Se normalizan +repeticiones de los parámetros de contexto; los parámetros ajenos no se sobrescriben. El parser +del workspace sigue rechazando claves desconocidas y las rutas/identidades mal formadas. + +La validación semántica de plantilla y contexto se realiza en el consumidor, una vez disponibles +sus definiciones. El parser permite que esos valores lleguen a esa frontera sin convertir una +página inválida o una columna retirada en una ruta de negocio nueva. Los demás contratos de +validación HTTP y autorización no cambian. + +Política aplicada: **replace** para búsqueda, filtros discretos, sort, página y normalizaciones. +Son variaciones del mismo espacio operativo; Atrás debe volver de ficha a listado, sin recorrer +cada pulsación/página de trabajo. Abrir otra sección o ficha mantiene **push**. La URL sigue +siendo compartible y reproducible aunque no se cree una entrada por cada ajuste. +Cambiar un filtro desde su control reinicia página; normalizar `contactsOnly=false` a ausencia +conserva una página solicitada válida, porque no cambia el conjunto filtrado. + +## 5. Preferencias + +Se conservan `entity-page-size` y `asset-inventory-columns`, sus formatos, límites, defaults y +tolerancia al almacenamiento bloqueado. No se trasladan a parámetros URL ni se borran IDs +antiguos. El enlace compartido utiliza el tamaño preferido del receptor y acota la página si +es necesario; no promete idéntica partición entre usuarios con tamaños distintos. + +## 6. Contexto temporal de retorno + +`metisListReturn` contiene versión 1, scope, URL de referencia, X/Y e identidad opcional de fila +y href. Los números se validan como finitos/no negativos y acotados; los destinos son internos. +Se conserva el resto de `history.state`, incluidos `previous`, `create` y propiedades ajenas. +URL y href admiten hasta 8192 caracteres serializados: una búsqueda válida de 200 caracteres +Unicode puede superar 2000 al codificarse. Este límite no amplía el contrato de búsqueda. + +La captura se integra antes del push de la infraestructura existente y mediante `focusin` / +`scrollend` de los contenedores del listado. Así también se conserva el contexto antes de +recorridos nativos del historial. No se añade otro listener global independiente de popstate, +ni temporizadores de sondeo, ni almacenamiento de DTO o nodos DOM. + +El ámbito incluye compañía y listado. Cambiar filtros invalida una posición incompatible; +una corrección automática de sort/página no impide recuperar y limitar coordenadas del mismo +conjunto filtrado. Los snapshots no se transfieren a otra compañía. + +## 7. Evolución de useEntityTable + +`navigation` es opcional; sin ella continúa el estado no controlado de los consumidores +existentes. Con ella, sorting y pageIndex efectivos se derivan de los valores externos y sus +callbacks escriben la consulta. El tamaño sigue siendo preferencia local persistida. También +se admiten `initialSorting` / `initialPagination` en el hook para inicialización explícita. +En modo controlado, actualizar paginación solo guarda localmente cambios de tamaño; no +mantiene una copia del índice externo. + +Se conservan `useReactTable`, modelos de filtro/orden/paginación, selección, protección y +visibilidad de columnas. No hay otro algoritmo de ordenación ni paginación. Los controles +conservan aria-sort y aria-current. Cambiar sort reinicia la página desde su handler; cambiar +criterios la reinicia desde el controlador del consumidor. No hay dos fuentes activas de verdad. + +La normalización de URL es una sincronización con una frontera externa y espera `ready`: +no acota página 3 a 1 por el conjunto vacío provisional del skeleton, ni elimina un campo +dinámico mientras falta el catálogo. La reducción confirmada del conjunto limita la página. + +## 8. Consumidores piloto + +- **Activos:** controlador conserva q/template; `AssetList` recibe navegación opcional y + transmite el contrato a EntityTable. Los enlaces mantienen la consulta en la ficha completa. +- **Recursos:** conserva q/template, selección en pathname y una sola tabla. Cierre inline + sigue ocultando panel sin borrar ruta/selección; cierre compacto vuelve por History y su + fallback directo conserva la consulta. No se introduce una ficha completa nueva. +- **Personas:** `usePeopleListContext` encapsula URL y fallback embebido. Los enlaces y + acciones de apertura conservan consulta; el botón Volver recupera la entrada del listado. + El padre transmite frescura de compañía para no confirmar registros de una copia fallida. + +## 9. Restauración de scroll y foco + +El scroll vertical real es `[data-slot=workspace-scroll]`; el horizontal es el contenedor de +la tabla. Se espera disponibilidad de datos y composición relevante, fuentes listas y el +siguiente frame de layout. No se espera una cantidad fija de milisegundos. + +Al volver se limita X/Y al máximo real. El foco vuelve al enlace del mismo `data-entity-id`; +si cambió su href por una normalización, se usa un control de esa misma fila. Si desapareció +o los datos no están verificados, se usa la búsqueda; no se selecciona otra fila arbitraria. +En navegación directa sin contexto se orienta al título, respetando interacción ya iniciada. +El enfoque usa preventScroll después de restaurar coordenadas. + +`BrowserLink navigation="return"` reutiliza la entrada anterior solo si coincide con su +destino; sin historial apropiado, reemplaza por el listado. Conserva enlaces reales, clic +modificado, descarga y nueva pestaña. La ficha ausente conserva también acceso a Volver. + +El contexto ya aplicado no se repite por un refetch. Si el usuario escribe durante la carga +no se le roba el foco. Los diálogos siguen sus finalFocus; la restauración genérica no los +enfoca ni abre. Recursos mantiene su instancia y Base UI conserva la orientación modal. + +## 10. Datos y parámetros inválidos + +Página inválida vuelve a 1; fuera de rango se limita a la última válida. Orden desconocido, +no ordenable o dirección inválida vuelve al inicial. Una columna dinámica retirada solo +deja de ser válida si tampoco existe en las instantáneas conservadas: no se elimina legado. + +El vacío confirmado y los filtros sin coincidencias conservan L02.3. Error inicial y posterior +no se confunden con desaparición. Un 503 posterior mantiene filas anteriores y contexto, pero +no autoriza a usar esa caché como prueba para devolver el foco al registro. Personas recibe +pending/ready/unverified del propietario de su consulta, sin una petición adicional. + +## 11. Compatibilidad con Recursos y V01 + +Activos conserva el mínimo de contenedor 1144 px; Recursos 984 px. No cambian presupuestos, +shell, rutas, intención de apertura, modalidad, observers ni reglas de resize. Un sublistado +o picker no adopta la consulta del padre por usar EntityTable: debe habilitar navegación +explícitamente. No se altera la selección provisional de los pickers ni V06. + +## 12. Pruebas automatizadas + +Las pruebas nuevas verifican parser/serializer, límites numéricos, IDs dinámicos, sort no +ordenable, fallback, tabla controlada con filas/página efectivas, consumidor no controlado, +History anterior/Adelante/retorno directo, propiedades ajenas y validación/aislamiento de scope. +Las pruebas de rutas se ajustan al nuevo límite entre validación sintáctica y semántica. + +`scripts/list-context-ui.test.py` utiliza Playwright MCP Docker/Chromium con sesión ordinaria, +login real y datos sintéticos. Cubre matriz de retorno, recarga/enlace compartido, parámetros +inválidos, resultados reducidos, Personas/contactos, Recursos contextual/directo, desaparición, +refetch retenido, carga inicial retenida al recargar, compañía distinta, Escape sin navegación, +campo dinámico retirado y errores simulados de Activos/Compañía. No escribe entidades. + +Los comandos y resultados reales finales se recogen junto a las evidencias; no se equiparan +las comprobaciones dirigidas correctas con las suites globales que mantienen deuda previa. + +### Ejecuciones y resultados + +| Comprobación ejecutada | Resultado real | +| --- | --- | +| Typecheck dirigido de `@repo/rdx-ui`, `@metis/core`, `@metis/assets`, `@metis/resources`, `@metis/companies` | Los cinco correctos; Compañías repetido tras el ajuste final de canonicalización. | +| `pnpm --filter @repo/rdx-ui test` | 11/11 archivos correctos, incluido contrato controlado/no controlado. | +| `pnpm --filter @metis/core test` | 3/3 archivos correctos; History, aislamiento y URL Unicode incluidos. | +| `pnpm --filter @metis/assets test` | 27/27 archivos correctos. | +| `pnpm --filter @metis/resources test` | 11/11 archivos correctos. | +| `pnpm --filter @metis/companies test` | 40/41 archivos correctos. Falla `companies-page.test.tsx`, con las dos expectativas SSR ya documentadas en L02.3: `Personas (1)` y mensaje de acceso de persona. Rutas del workspace pasa. | +| Biome y ESLint dirigidos a los 28 archivos TypeScript modificados/nuevos | Correctos, sin fixes ni supresiones; repetidos tras el último ajuste. | +| `pnpm typecheck` | Falla en vendor `calendar.tsx:165`, TS2375 sobre `locale` y `exactOptionalPropertyTypes`, ya documentado. No se modifica vendor. | +| `pnpm lint` | Falla: 15 errores, un warning y cuatro infos, como L02.3. | +| `pnpm check` | Falla: 167 errores, un warning y cuatro infos; L02.3 registraba 168 errores. Los archivos propios del cambio pasan la comprobación dirigida. | +| `pnpm test` | 7/8 tareas correctas; falla únicamente la tarea de Compañías anterior. Se ejecuta contra otra MariaDB temporal `metis_desk_test`, aislada de la instalación del navegador. | +| `pnpm build` | 2/2 tareas correctas; permanece el aviso de chunks superiores a 500 kB. | +| Playwright L03.1 | 14 métodos distintos comprobados: ejecución principal 12/12, revisión 4/4 (incluye el nuevo caso 13) y revisión de Personas 3/3 (incluye el nuevo caso 14). Los métodos repetidos no se cuentan dos veces. | +| Regresiones Playwright L02.1 / L02.2 / L02.3 | 8/8, 8/8 y 8/8 métodos correctos, respectivamente. | +| Otras regresiones Playwright | 9/9: navegación, capacidad de inventarios, contraste seleccionado, asistentes y políticas de foco. | + +Son **47 métodos distintos de navegador verificados**, contando pilotos y regresiones. No +se afirma una ejecución única de los 14 métodos nuevos: se conservan los logs de cada lote. +Las pruebas comprueban filas reales, aria-sort/current, filtros, coordenadas y elemento activo; +no se limitan a comparar la URL. + +Para repetirlos, preparar la instalación y el volumen según [Playwright MCP](playwright-mcp.md), +mantener vivo su preparador y utilizar el archivo privado de sesión que este proporciona: + +```bash +METIS_PLAYWRIGHT_STORAGE_STATE=.artifacts/playwright/authenticated-/session.json \ + python3 scripts/list-context-ui.test.py +``` + +El script reutiliza los helpers MCP existentes, no inicia servicios y bloquea escrituras HTTP +de negocio durante la inspección. Requiere acceso al Docker configurado y sesión ordinaria +sintética activa; no sirve una sesión de producción. No se versionan archivos de sesión. + +## 13. Evidencias Playwright + +Directorio local ignorado: `.artifacts/playwright/l03-1/`, con baseline `before/`, capturas y +mediciones nuevas en `after/`, resultados URL/DOM/X/Y/foco, consola, logs e índice. Las imágenes +locales no son evidencia portable por sí solas: compartir expresamente PNG/mediciones sin +sesiones. Se abren capturas representativas antes de concluir la revisión visual. + +La matriz incluye 1920×1080, 1440×900, 1366×768, 1024×768, 768×1024, 390×844 y 320×640. +El recorrido inicial corregido a 1440 y 390 conserva Nombre descendente, página 3 y el enlace +AUDIT-ASSET-24. Se restauran 100 px verticales y, en móvil, 40 px horizontales; la suite ampliada +usa 150 px y desplaza la ficha a otra coordenada para comprobar la recuperación. + +| Resolución | Sort / página al regresar | Scroll X/Y antes y después | Foco al regresar | +| --- | --- | --- | --- | +| 1920×1080 | Nombre descendente / 3 | 0 / 0: la tabla cabe en altura | Mismo enlace de registro | +| 1440×900 | Nombre descendente / 3 | 0 / 150 | Mismo enlace de registro | +| 1366×768 | Nombre descendente / 3 | 0 / 150 | Mismo enlace de registro | +| 1024×768 | Nombre descendente / 3 | 0 / 150 | Mismo enlace de registro | +| 768×1024 | Nombre descendente / 3 | 40 / 150 | Mismo enlace de registro | +| 390×844 | Nombre descendente / 3 | 40 / 150 | Mismo enlace de registro | +| 320×640 | Nombre descendente / 3 | 40 / 150 | Mismo enlace de registro | + +En las siete medidas coinciden consulta, filas e identidad del foco, sin overflow horizontal +global. Se alterna Atrás y «Volver a activos»; a 1440 también se comprueba Adelante y otro Atrás. +No se exige scroll vertical inexistente en 1920. Personas recupera contactos, descendente, +página 2, X=40/Y=27 y enlace de origen en 390×844. Recursos se verifica a 1920 inline y a +390 compacto, con misma tabla, consulta y orden/página después del cierre. + +La recarga con GET retenido en 320 mantiene `page=3` y el orden descendente durante skeleton: +no se fuerza una página efectiva antes de que existan filas. Al liberar los datos vuelve a +página 3, X=40/Y=150 y al enlace original. Tras un 503 posterior, Activos y Personas conservan +la tabla/contexto, pero enfocan búsqueda, porque la existencia del registro no está verificada. + +Índice local: [evidencias y logs](../.artifacts/playwright/l03-1/indice-evidencias.md). +Mediciones de referencia: `after/measurements-2776681.json` (12 métodos), +`after/measurements-2784654.json` (revisión y tamaño persistido) y +`after/measurements-2797155.json` (Personas y canonicalización de false). +Capturas abiertas e inspeccionadas: baseline y retorno móvil, Personas, carga retenida a +320, retorno de Personas sin frescura y cierre contextual de Recursos a 390. + +Se utiliza una instalación propia desechable `metis_desk_test`, con **15 compañías, 50 personas, +51 activos y 66 recursos**. No se precisan nuevos puestos/perfiles para estos pilotos; sus +escenarios previos se mantienen como regresión. Las retiradas de registros/campos y los 503 +son interceptaciones GET explícitas, no borrados ni incidencias espontáneas del servidor. + +## 14. Regresiones + +Se ejecutan suites dirigidas y regresiones de L02.1, L02.2, V12, navegación responsive, +capacidad de inventarios, contraste seleccionado, asistentes, acciones y V06. Se conserva +la carga estable y la tabla durante refetch. Se registran por separado intentos intermedios +con errores de instrumentación/contexto Node-DOM o timeouts y las ejecuciones finales. +Se corrigieron durante la entrega el reinicio prematuro al cargar, la frescura de Personas +aportada por su consulta propietaria y la pérdida de página al canonicalizar un filtro false. +El límite de snapshots se ajustó para URL Unicode válidas y se eliminó la copia local del +índice controlado. Cada ajuste tiene comprobación dirigida o de navegador correspondiente. +Los primeros errores de instrumentación MCP (DOM fuera de `page.evaluate`) y timeouts de +lotes concurrentes/HMR no se ocultan ni se contabilizan como pruebas superadas; las +ejecuciones finales se realizaron con menor concurrencia y pasaron. + +## 15. Limitaciones + +V05 se delimita a los tres pilotos y escenarios ejecutados; no se declara una restauración +universal. No se acredita rendimiento de producción, lectores de pantalla, todos los motores +o todas las variantes de historial externo. `scrollend` se verifica en Chromium de la imagen +fijada. Los datos remotos pueden cambiar y las coordenadas se limitan a la geometría vigente. + +Skills consultadas: `ux-navigation` principal; `ux-tables`, `ux-search`, +`vercel-composition-patterns`, `vercel-react-best-practices`, `shadcn` y `ux-error-recovery`. +Se aplican a orientación, continuidad operativa, fronteras de estado, composición y recuperación; +no se introducen tendencias de búsqueda, rediseño ni bibliotecas. Prevalecen AGENTS/DESIGN y +APIs reales. Los auditores especializados referidos por las skills no están disponibles; +no se instalan ni se afirma haberlos ejecutado. + +## 16. Consumidores pendientes para L04 + +Puestos, Perfiles, Compañías, catálogos, procesos/configuraciones y sublistados deben decidir +su contrato navegable antes de adoptar el mecanismo. Un selector remoto conserva su cursor +y búsqueda del proveedor: no debe serializarse como paginación local para uniformar. + +V07 permanece pendiente. V08 y V12 conservan su alcance ya documentado. No se implementa L04 +ni se modifica la normalización de las búsquedas de negocio. + +L03.2 requiere otra instrucción: no se adelantan sus funcionalidades. L04 podrá reutilizar +el contrato tras analizar desmontaje, semántica de selección y consultas de cada consumidor. + +## 17. Archivos principales y cierre + +- `packages/rdx-ui/src/lib/entity-table-navigation.ts`, `hooks/use-entity-table.ts`, + `components/entity-list.tsx` y `components/entity-table-content.tsx`: contrato opcional, + callbacks nativos de tabla e identidad estable de filas; `entity-list.test.tsx` lo verifica. +- `modules/core/src/web/navigation/shared/`: `use-list-location.ts`, `use-list-return.ts`, + `list-return-context.ts`, History/BrowserLink y pruebas; exports públicos de navegación/core. +- Activos: controlador de inventario, `inventory-page.tsx`, `asset-list.tsx` y ficha completa. +- Recursos: controlador y `resources-page.tsx`, preservando panel y fallback de retorno. +- Compañías: `use-people-list-context.ts`, `people-section.tsx`, composición de detalle de + compañía, exports y parser/pruebas de rutas existentes. +- `scripts/list-context-ui.test.py`: pruebas autenticadas nuevas con los helpers MCP existentes. +- `DESIGN.md`, patrón de listados, componentes, rutas, seguimientos de ambas auditorías y este + informe: responsabilidades, alcance verificado y consumidores pendientes. + +No se modifica `packages/shadcn-ui`, shell responsive, estilos, contratos HTTP, base de datos, +autenticación, dependencias ni `docs/auditorias/`. Se revisa el diff completo y enlaces locales. +El preparador propio termina con código 0 y confirma la retirada del entorno temporal; se +comprueba que su archivo privado de sesión ya no existe. Capturas y mediciones permanecen +ignoradas en `.artifacts/playwright/l03-1/`, sin incorporar credenciales al repositorio. diff --git a/docs/patron-de-listados-de-entidades.md b/docs/patron-de-listados-de-entidades.md index 8d4213b..0561623 100644 --- a/docs/patron-de-listados-de-entidades.md +++ b/docs/patron-de-listados-de-entidades.md @@ -113,6 +113,24 @@ Al reintentar, enfocar la búsqueda persistente para evitar que la desaparició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. +## Contexto navegable y retorno — L03.1 + +Activos, Recursos y Personas 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: pickers, sublistados y otros consumidores continúan locales +salvo contrato propio. No heredar la página del listado padre en tablas de una ficha. +Véase el [informe L03.1](contexto-listados-l03-1.md) para alcance y consumidores pendientes. + ## Inventario de listados y ubicaciones actuales La aplicación navega por espacios y secciones mediante rutas URL independientes, según [Rutas del cliente](rutas-del-cliente.md). Los componentes siguientes se componen desde CompaniesWorkspace, CompanyDetail o IdentityWorkspace; altas, ediciones e historiales conservan sus modales. diff --git a/docs/rutas-del-cliente.md b/docs/rutas-del-cliente.md index 94bba4d..04ef014 100644 --- a/docs/rutas-del-cliente.md +++ b/docs/rutas-del-cliente.md @@ -95,16 +95,21 @@ La consulta conserva los filtros que ya están conectados a la URL: - Dashboard y directorio: `companyId`; directorio también `activeOnly` y `q`. - Activos: `q` y `template` (UUID de plantilla), tanto en el listado como en la ficha seleccionada. - Recursos: `q` y `template` (UUID de plantilla), tanto en el listado como en la ficha seleccionada. +- Personas: `q` y `contactsOnly`, también al abrir su detalle. +- Los pilotos Activos, Recursos y Personas añaden `sort`, `direction` y `page`, según + [L03.1](contexto-listados-l03-1.md). Son parámetros de las rutas existentes, no destinos nuevos. - Perfiles y procesos: `q`, con `archived` o `closed`, respectivamente. - Catálogos de activos y recursos: `q` y `tab`; `relations` solo en activos. - Cuentas y accesos: `q` y `kind`, respetando los tipos disponibles en cada ámbito. -Los booleanos se serializan como `true` o `false`. Los UUID, las pestañas y los -parámetros repetidos o desconocidos se rechazan antes de seleccionar una pantalla. La búsqueda admite +Los booleanos conservan su contrato de ruta; Solo contactos se representa con `true` o ausencia. +Identidades de ruta, pestañas y parámetros ajenos desconocidos se rechazan antes de seleccionar +una pantalla. Los pilotos validan sort/direction/page y plantilla contra sus metadatos y +normalizan valores inválidos o repetidos sin perder parámetros de otras operaciones. La búsqueda admite hasta 200 caracteres. Un `companyId` de consulta no puede contradecir la compañía del pathname. Esta validación del navegador no sustituye la autorización del servidor. -Cambiar filtros reemplaza la entrada actual del historial; abrir otra sección o +Cambiar filtros, sort o página en los pilotos reemplaza la entrada actual del historial; abrir otra sección o ficha añade una entrada. Atrás y Adelante recuperan los destinos y filtros. Cerrar una ficha vuelve al destino interno anterior; si se abrió directamente, sustituye la entrada por su listado o por el contexto del perfil correspondiente. @@ -114,7 +119,10 @@ siguen siendo diálogos locales. No se añaden rutas `/new`, `/edit` ni parámet `view` sin una necesidad concreta. El alta rápida que cambia de sección lleva una señal temporal en `history.state`, consumida cuando monta la pantalla que abre el formulario, sin introducirla en la URL compartida. Los restantes filtros locales, -la paginación, ordenación y preferencias de columnas mantienen su estado existente. +la paginación y ordenación mantienen su estado existente fuera de los pilotos. Tamaño y +columnas conservan sus claves de preferencias. Los pilotos guardan exclusivamente scroll y +origen de foco en `history.state.metisListReturn`, aislados por compañía/listado y filtros. +No se guarda una segunda copia de datos remotos ni se persiste ese contexto en localStorage. ## Implementación y futuros destinos @@ -155,7 +163,10 @@ Tickets, intervenciones y plantillas de intervención no tienen rutas activas. S `/companies/:companyId/assets/:assetId` muestra una página de detalle con las pestañas Información e Historial. El listado conserva la selección local para su panel lateral; los enlaces de nombre y las acciones de ver abren la página. Los parámetros `q` y -`template` se conservan en los enlaces del listado y de retorno a este. +`template`, `sort`, `direction` y `page` se conservan en los enlaces y el retorno. +`BrowserLink navigation="return"` vuelve a la entrada anterior si coincide con el listado; +sin historial apropiado reemplaza la entrada por ese destino. Clic modificado y nueva pestaña +siguen utilizando un enlace real. La ausencia del activo conserva el acceso a Volver. ## Presentaciones responsive de la navegación