22 KiB
Dashboard de puesto de trabajo: implementación
Fecha: 22 de octubre de 2026. Ruta real: /companies/:companyId/workstations/:id.
Resultado y referencias
La ficha presenta ordenador principal, configuraciones pendientes, personas y perfiles, responsable y contexto, equipamiento, software, configuraciones por perfil, soporte/acceso remoto y último cambio. El historial completo, edición, renombrado, alta de perfil y ciclo de vida siguen usando las operaciones existentes.
La implementación utiliza consultas reales. El JSON de la auditoría solo se importa en pruebas; no alimenta la aplicación ni se inserta en una BD. No hay endpoints, modelos, esquemas, migraciones ni dependencias nuevos.
Se han conservado los ocho entregables de la auditoría como descripción del estado anterior y base funcional. No existe una imagen aprobada accesible en esta conversación o adjunta a la tarea: la comparación se realiza con la especificación textual del usuario. No se afirma fidelidad de píxel respecto a una imagen no disponible.
Composición y diferencias justificadas
- El shell, sus sidebars, búsqueda superior y navegación conservan su implementación.
- Cabecera con breadcrumb, nombre editable, estado, compañía, sede y responsable. Editar, historial y menú de ciclo de vida permanecen accesibles.
- La primera banda reserva al ordenador la columna izquierda y sitúa pendientes al extremo derecho, sin ocupar el hueco con estadísticas. No se han creado las cuatro tarjetas eliminadas.
- El grid inferior utiliza
minmax(0,1.6fr)yminmax(0,1fr)desde 1000 px de contenedor: aproximadamente 62/38. La primera banda cambia desde 900 px. Por debajo se conserva una columna y el orden lógico pedido. - Paneles compactos con borde, radio y espaciado del sistema existente; sin sombras decorativas ni gráficos.
- Se utiliza el catálogo propio de iconos Tabler. La especificación menciona Lucide, pero prioriza el design system instalado para componentes/tokens. No se ha introducido otra biblioteca ni cambiado vendor.
- El azul de la ficha utiliza los tokens existentes
secondaryysecondary-foreground, asignados localmente a los roles primarios dentro de su contenedor. El tema global y los portales de diálogos conservan su configuración. No se añade otra paleta. - Las plantillas, nombres y fechas visibles proceden del servidor; no se fuerza «Portátil corporativo» ni la fecha de la ilustración cuando el catálogo o las revisiones reales dicen otra cosa.
- Las celdas sin valor usan «—». Responsable ausente en cabecera se expresa como «Sin responsable», un estado semántico fuera de una celda de listado.
Componentes reutilizados y componentes nuevos
| Unidad | Reutilización / motivo |
|---|---|
DetailPanel, DetailField |
Estructura común. DetailPanel incorpora density="compact"; el valor por defecto conserva sus recetas anteriores |
EntityTable, EntityStatus, entityListState |
Tablas con búsqueda, orden, paginación, columnas configurables y estados inicial/actualización/error/datos anteriores |
WorkstationNameEditor, WorkstationActions, WorkstationEditorDialog, WorkProfileEditorDialog |
Operaciones reales conservadas. WorkstationActions.children permite intercalar la acción de historial sin duplicar el menú |
WorkstationHistoryDialog, WorkstationHistory, TimeLine |
Historial completo real. Se exporta el diálogo desde la API pública de Assets; añade altura estable y destino de foco de retorno |
SoftwareInstallationsPanel |
Gestión completa de instalaciones dentro de WorkstationSoftwareDialog; conserva alta, edición, borrado, cerradas e historial |
AssetSupport, RemoteSummary, TeleworkAuthorizationSummary |
Consulta y gestión de soporte/contexto con semántica existente |
buildEnvironment |
Reutiliza el cálculo de configuraciones y sus detalles, sin copiar políticas de autorización |
WorkstationComputer, WorkstationResponsible, WorkstationLatestChange |
Presentación específica de responsabilidades distintas de la ficha |
WorkstationPendingConfigurations, WorkstationProfileConfigurations, WorkstationConfigurationFamily |
Conteo verificable, selección explícita y grupos con estado independiente |
WorkstationSoftware, WorkstationSupport |
Integración de fuentes/operaciones existentes con contexto del equipo y la persona seleccionados |
WorkstationQueryFeedback, WorkstationDashboardSkeleton |
Feedback repetido por fuente y geometría de carga inicial de esta pantalla |
WorkstationAssets y WorkstationProfiles se adaptan en sus ubicaciones existentes. El antiguo WorkstationPeople se retira tras buscar sus referencias: solo lo utilizaban la composición anterior y sus pruebas. La distinción entre responsable y personas usuarias se presenta ahora en los bloques de perfiles y contexto. Sus referencias en la auditoría son históricas, no importaciones activas.
Los componentes nuevos viven en modules/companies/src/web/workstations/detail/; no se ha creado un framework de widgets ni trasladado lógica específica a la biblioteca visual genérica.
Consultas, relaciones y selección
El controller conserva inventario, puesto y operaciones locales. useWorkstationConfigurationQueries consulta recursos, Access, carpetas, correo, aplicaciones, impresoras, certificados, remoto y teletrabajo con claves centralizadas. Software utiliza su clave por compañía y soporte su clave por activo. No se crea una consulta por perfil o tarjeta de equipamiento.
Las consultas del detalle de perfiles/configuraciones/software/soporte no se habilitan sin un ordenador principal confirmado dentro de assetIds. El shell puede conservar sus consultas propias por compañía. Se ha retirado del controller la consulta de catálogo que ya no necesitaba esta composición; las especificaciones de activos proporcionan su plantilla legible.
Las relaciones se resuelven por ID y compañía. Los perfiles pertenecen al ordenador principal; el responsable procede de personId. Los activos actuales proceden exclusivamente de assetIds. Las impresoras configuradas por perfil y los activos históricos no se incorporan a ese equipamiento.
Perfiles activos y archivados se distinguen explícitamente; el acceso a archivados amplía la tabla existente. La ausencia de cuenta no invalida un perfil. El selector de configuraciones utiliza perfiles activos, conserva el ID seleccionado durante refetch y, si deja de ser válido, muestra el primer activo con una explicación. No se sincroniza estado remoto mediante efectos.
Cada configuración conserva su familia, perfil y procedencia. Aplicación del perfil e instalación de equipo son registros distintos. Las carpetas muestran estado y cobertura documental por separado, incluida cobertura desconocida. Cuando faltan metadatos de recursos/Access, se informa de esa dependencia y no se presenta una lista vacía como si fuese un resultado completo.
El soporte corresponde al ordenador. El contexto remoto identifica a la persona del perfil seleccionado y limita conexiones a las que usan ese activo como origen o destino. La autorización de teletrabajo es de esa persona. No se inicia conexión ni se deduce presencia, VPN activa o permiso efectivo sobre SMB.
Indicadores y revisiones
La única tarjeta estadística es «Configuraciones pendientes». Cuenta IDs distintos por familia de carpetas, correo, aplicaciones, impresoras y certificados en estado pending, con profileId de un perfil activo del principal y la misma compañía. Excluye legacy sin perfil, archivados, otras compañías, removal_pending, revisión y software instalado.
El total solo se presenta si perfiles y las cinco consultas necesarias tienen datos sin fallo. Ante fallo deja de ser definitivo, aunque se conserven datos anteriores. Sin ordenador la población de perfiles del principal es vacía y el total es cero. El botón de pendientes selecciona un perfil con pendientes, activa el filtro y lleva el foco a la sección.
Estado técnico y asignación de uso se distinguen: values.status describe el estado técnico; assigned indica reserva en un puesto activo. Un equipo averiado puede conservar su asignación y no debe aparecer como disponible. No se usa un semáforo global de salud.
Último cambio compara las dos últimas revisiones por fecha, sin mutar arrays: nombre, estado, sede, responsable, principal y miembros añadidos/retirados. Solo describe diferencias verificadas. No se mezclan eventos de otras entidades; las etiquetas relacionadas se resuelven con sus nombres disponibles actualmente.
Carga, errores y accesibilidad
La carga inicial conserva una geometría próxima al dashboard. Cada consulta secundaria presenta skeleton, actualización o error con reintento propio; no derriba la cabecera ni las otras tarjetas. Las tablas conservan datos y controles si falla una actualización con caché. No se desmonta el selector durante refetch ni se oculta la diferencia entre cero y total desconocido.
Se reutilizan enlaces reales, regiones nombradas, un h1, paneles h2 y subgrupos h3/h4. No hay contenedores con clic que sustituyan a enlaces. Los estados tienen texto, los iconos decorativos están ocultos y las tablas mantienen cabeceras. Las rutas largas se pueden leer completas mediante ajuste de línea; el overflow de tablas queda dentro de su zona.
El historial devuelve el foco al disparador concreto; el acceso a pendientes mueve el foco a una sección identificada. Las primitivas existentes gestionan teclado, menús, selectores y diálogos. La verificación interactiva y sus límites se registran abajo; no se declara cumplimiento WCAG global.
Entorno de pruebas y reproducción
Se utilizó el preparador aislado scripts/visual-audit.py, sin conectar a la BD habitual. Su MariaDB desechable utiliza exclusivamente metis_desk_test, API/Vite en puertos libres y sesión real de usuario ordinario. El origen anunciado de esta ejecución fue http://localhost:49383.
Preparación y pruebas reproducibles, desde WSL:
bash scripts/setup-playwright-wsl.sh
python3 scripts/visual-audit.py
# En otra terminal, con la ruta privada anunciada por el preparador:
METIS_PLAYWRIGHT_STORAGE_STATE=.artifacts/playwright/authenticated-ID/session.json \
PYTHONDONTWRITEBYTECODE=1 python3 scripts/visual-audit-volume.py
METIS_PLAYWRIGHT_STORAGE_STATE=.artifacts/playwright/authenticated-ID/session.json \
PYTHONDONTWRITEBYTECODE=1 python3 scripts/workstation-dashboard-fixtures.py
METIS_PLAYWRIGHT_STORAGE_STATE=.artifacts/playwright/authenticated-ID/session.json \
PYTHONDONTWRITEBYTECODE=1 python3 scripts/workstation-dashboard-ui.test.py
Los nuevos preparadores rechazan sesiones fuera de la ubicación privada y escenarios de otra instalación. Crean datos mediante HTTP real y CSRF. Las comprobaciones que sustituyen el principal o modifican la cuenta de carpeta restauran sus valores en finally. No se guardan credenciales en el informe ni se instala Chromium en WSL.
Volumen inicial de la auditoría interactiva: 15 compañías, 59 personas, 135 activos y 73 recursos en la compañía principal. La variante S04 tiene 80 miembros y 60 perfiles (50 activos y 10 archivados). S10 añade un activo sintético de sustitución, elevando después el inventario a 136; queda dentro del mismo entorno desechable.
Verificaciones y límites
Verificaciones ejecutadas sobre esta implementación:
| Comprobación | Resultado |
|---|---|
| Tipos de Companies, Assets, RDX UI y Web | Correctos con comandos dirigidos |
| Pruebas dirigidas de dashboard, relaciones y ficha | 20 pruebas correctas, usando --test-isolation=none para exponer cada caso |
| Biome sobre archivos del cambio | Correcto, sin supresiones |
| ESLint de espaciado sobre archivos del cambio | Correcto |
pnpm build |
Correcto; Vite conserva advertencia de bundle mayor de 500 kB |
| Playwright MCP | 11 métodos interactivos verificados mediante pasadas completas y dirigidas; cubren S01–S11, teclado, contraste, paginación y guardados reales |
pnpm typecheck global |
Se detiene en packages/shadcn-ui/src/components/calendar.tsx:165, por opcionalidad exacta de locale; vendor no modificado |
pnpm lint global |
15 errores fuera del cambio, principalmente bloques sin llaves en código de fotos; también diagnósticos de ejemplos de skills |
pnpm check global |
167 errores fuera del cambio, incluyendo formato de ejemplos/fixtures y código de fotos |
pnpm test global |
La última pasada completa deja 41 de 42 archivos de Companies correctos; falla únicamente companies-page.test.tsx, con las dos aserciones ajenas descritas abajo. El test del dashboard detectado inicialmente se corrigió y pasa |
Las dos aserciones ajenas esperan los literales Personas (1) y Esta persona no tiene acceso a Metis Desk; los archivos de compañías/personas afectados no se han modificado en esta tarea. No se amplía el alcance para corregirlas. Los fallos globales impiden declarar todo el monorepo en verde; las comprobaciones dirigidas distinguen el dashboard de esa deuda.
La primera pasada interactiva detectó etiquetas de prueba antiguas, una espera de refetch que no provocaba un evento de reconexión real y una comprobación de texto que incluía una etiqueta oculta al lector. Se corrigieron los recorridos sin ocultar fallos ni introducir esperas arbitrarias. También se corrigieron una etiqueta de compañía sin traducir y las cabeceras extensas de perfiles observadas en las capturas.
Quedan fuera de lo acreditado: comparación con la imagen original ausente, lector de pantalla real, zoom 200/400 %, modo oscuro y auditoría WCAG completa. No se implementa autorización granular por compañía: se conservan autenticación y comprobaciones de pertenencia existentes, con el límite documentado en la auditoría.
Evidencias visuales
Las capturas e informes sintéticos se guardan en .artifacts/playwright/workstation-dashboard-implementation/, fuera de Git. Se abrieron capturas de escritorio, móvil y fallos parciales para revisar la composición; la inspección final se detalla al cerrar la pasada.
Se generan S01 en 1600, 1440, 1280, 1024, 768 y 390 px; vistas de configuraciones; S02, S03, S04 de alta densidad, S05, S06, S07 con datos anteriores, S08 sin coincidencias, S10 y S11. measurements.json registra geometría, hashes y comprobaciones; no contiene cookies. Se han inspeccionado también S01 de 1600 px, configuraciones en 390 px, cobertura desconocida y desmantelado. Las mediciones no detectaron desbordamiento horizontal global en los seis anchos. El muestreo de 38 textos/acciones/enlaces dio contraste mínimo 5,03:1. No hubo excepciones JavaScript de página; los HTTP 503 simulados son parte de los escenarios de error. La ubicación local no garantiza conservación portable: al compartir el trabajo hay que adjuntar los PNG elegidos, nunca session.json.
Archivos del cambio
Los siguientes archivos contienen la implementación, sus pruebas o su documentación. Los ocho entregables originales de auditoría permanecen fuera de estos cambios.
- docs/componentes-de-interfaz.md
- docs/workplace-dashboard-implementacion.md
- modules/assets/src/common/locales/en.json
- modules/assets/src/common/locales/es.json
- modules/assets/src/web/index.ts
- modules/assets/src/web/workstations/history/ui/workstation-history-dialog.tsx
- modules/assets/src/web/workstations/shared/ui/workstation-actions.tsx
- modules/companies/package.json
- modules/companies/src/web/workstations/detail/controllers/use-workstation-configuration-queries.ts
- modules/companies/src/web/workstations/detail/controllers/use-workstation-detail-controller.ts
- modules/companies/src/web/workstations/detail/helpers/workstation-dashboard.test.ts
- modules/companies/src/web/workstations/detail/helpers/workstation-dashboard.ts
- modules/companies/src/web/workstations/detail/ui/workstation-assets.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-computer.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-configuration-family.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-dashboard-skeleton.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-detail-content.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-detail-page.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-detail.test.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-latest-change.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-pending-configurations.tsx
modules/companies/src/web/workstations/detail/ui/workstation-people.tsx— retirado; responsabilidad integrada en los bloques actuales.- modules/companies/src/web/workstations/detail/ui/workstation-profile-configurations.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-profiles.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-query-feedback.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-responsible.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-software-dialog.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-software.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-support.tsx
- packages/rdx-ui/src/components/detail-panel.tsx
- scripts/workstation-dashboard-fixtures.py
- scripts/workstation-dashboard-ui.test.py
Skills consultadas
frontend-design guio la composición específica y su revisión visual;
ux-dashboard, la jerarquía y la exclusión de estadísticas decorativas;
ux-tables, las cabeceras breves, comparación y manejo de volumen;
shadcn, la comprobación de APIs Base UI y composición de primitivas;
vercel-composition-patterns, los slots y la separación de responsabilidades;
vercel-react-best-practices, la caché compartida, la ausencia de efectos para datos
derivados y las consultas sin N+1. No se instaló ninguna skill ni auditor externo.
Comandos dirigidos adicionales
pnpm --filter @metis/companies typecheck
pnpm --filter @metis/assets typecheck
pnpm --filter @repo/rdx-ui typecheck
pnpm --filter @metis/web typecheck
TSX_TSCONFIG_PATH=tsconfig.json node --import tsx --test --test-isolation=none \
modules/companies/src/web/workstations/detail/helpers/workstation-dashboard.test.ts \
modules/companies/src/web/workstations/detail/helpers/workstation-relations.test.ts \
modules/companies/src/web/workstations/detail/ui/workstation-detail.test.tsx
Se comprobaron Biome y ESLint sobre la lista de archivos de código anterior y
git diff --check. Los comandos globales ejecutados fueron pnpm typecheck,
pnpm lint, pnpm test, pnpm check y pnpm build, con los resultados y límites
indicados. La sintaxis de los dos scripts Python se comprobó con ast.parse, sin
instalar paquetes ni dejar bytecode en el repositorio.
Capturas seleccionadas para revisión
- S01, escritorio 1600 px.
- S01, móvil 390 px.
- Configuraciones en móvil.
- Cobertura documental desconocida.
- Errores parciales.
- Puesto desmantelado.
Se conservan 18 PNG y el informe de medidas en esa carpeta estable. No incluye sesiones ni credenciales. El preparador y su contenedor se han retirado al terminar; se comprobó que la sesión privada ya no existe y las capturas permanecen para revisión local.