frontend-plus-react 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +18 -1
- package/README.md +1 -0
- package/dist/index.cjs +619 -262
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +19 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +692 -335
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -70,6 +70,7 @@ Son las de `dmencu` (que aplican a todo proyecto compartido de esta carpeta), es
|
|
|
70
70
|
- F4 con la tecla apretada: las pulsaciones que caen en la celda antes de que el editor nuevo tenga el foco se le pasan por `registrarEditor`, o quedan en cola hasta que haya uno. F4 usa el valor que acaba de copiar si la fila de arriba todavía no se redibujó.
|
|
71
71
|
|
|
72
72
|
### Detalles desplegados (como `backend-plus`)
|
|
73
|
+
- **El botón del detalle**: Ctrl+clic o la ruedita lo abren en otra pestaña. La ruedita llega como `auxclick`, y en Windows el navegador empieza el desplazamiento automático al apretarla y no lo manda: el botón cancela el `mousedown` del botón del medio. El botón se centra sobre toda la celda (`position: absolute; inset: 0`): la columna mide 30 px y la grilla le deja 8 px de margen a cada lado, así que centrarlo dentro del margen lo corría a la derecha de su sigla.
|
|
73
74
|
- Un detalle es una fila especial (`FilaDetalle`, marcada con un `Symbol`) que se intercala debajo de su fila y ocupa todas las columnas; adentro hay otra `GenericDataGrid` (recursiva). Ctrl+click o botón del medio lo abre en otra pestaña.
|
|
74
75
|
- Alturas: **de arriba hacia abajo**. La grilla principal toma lo que queda de la ventana; cada detalle recibe `altoDisponible` y no puede pasar de ahí, así su pie queda visible. No calcular el tope con el alto medido de la grilla padre: una grilla de pocas filas es baja y aplasta a su detalle.
|
|
75
76
|
- Un detalle con muchas filas muestra `firstDisplayCount` (20) cuando supera `firstDisplayOverLimit` (30), los mismos umbrales de `backend-plus`, y **virtualiza** sus filas; los chicos crecen según su contenido. La grilla principal siempre virtualiza.
|
|
@@ -111,10 +112,26 @@ Son las de `dmencu` (que aplican a todo proyecto compartido de esta carpeta), es
|
|
|
111
112
|
- El estado es `columnasOcultas` de `GenericDataGrid` (se guarda en el cache de los detalles). Cambiarlo sí rearma las columnas, pero solo lo cambia el usuario: **Alt+clic en el encabezado** oculta (`defaultColumnHeaderCellRenderer`, en la captura para que react-data-grid no ordene) y **«ocultar o mostrar columnas»** del menú abre `DialogoDeColumnas` (a la izquierda las que se ven, a la derecha las ocultas; un clic cambia de lado). No lista las que oculta un fixedField, que no se pueden mostrar.
|
|
112
113
|
- La exportación no incluye las ocultas salvo la opción `hiddens` (`ExportDialog`). El editor vertical (`VerticalEditorPage`, recibe `columnasOcultas`) tampoco muestra ni los `visible: false` ni las ocultas, como el modo vertical de `backend-plus`. Los detalles desplegados son otra `GenericDataGrid`: cada uno lleva sus propias columnas ocultas.
|
|
113
114
|
|
|
115
|
+
### Menú lateral (`SideMenu`)
|
|
116
|
+
- **Acordeón**: abrir un grupo cierra a sus hermanos (con lo que tengan abierto adentro, `abrirGrupo`); al navegar queda abierto solo el camino del ítem que se muestra (`abrirCamino`). El estado abierto/cerrado se guarda por el **camino** del grupo (`asignacion/encuestador`, `claveDeMenu`), no por su nombre: los nombres se repiten entre grupos.
|
|
117
|
+
- **Buscador** arriba, fijo junto con el logo (solo scrollea la lista): palabras sueltas, sin tildes ni mayúsculas, en la etiqueta del ítem **o de sus grupos** (`utils/busquedaDeMenu.ts`); los resultados llevan debajo el camino de grupos. ↑ ↓ Enter Escape; **Ctrl+K** lo enfoca desde cualquier pantalla (abre el menú si está cerrado).
|
|
118
|
+
- **Recientes**: las últimas 4 pantallas (`localStorage`, `fpr.menu.recientes`). Un ítem que ya está **no cambia de lugar**, y ahí no se hace `scrollIntoView`: se hizo las dos cosas y el menú saltaba al principio al elegir un ítem.
|
|
119
|
+
- Íconos grises; el ítem seleccionado y el grupo abierto toman el color de su tipo. Una wScreen se considera implementada si está en `myWScreens` **o** si el puente está encendido (se pide a backend-plus); el triángulo de advertencia es solo para «no implementada». Las pantallas del puente viven en `/bp/menu#w=<pantalla>`: así se detecta cuál está seleccionada.
|
|
120
|
+
|
|
121
|
+
### Estilo alineado con el skin `modern` de backend-skins
|
|
122
|
+
- Para que lo que entra por el puente se parezca: bordes `#e0e0e0`, encabezado `#eceff1` con letra de peso 500, hover y selección con el color primario translúcido (variables `--rdg-*` de `.rdg-light` en `GenericDataGrid.css`; usan `--primary-rgb` del skin si está cargado). Los íconos de acciones de la grilla son grises sin borde (toman su color al pasar el mouse), como `.table-button`. Al scrollear, detrás de las filas hay un patrón de filas vacías (`background-image` de `.rdg-light`, 30 px) para que no se vea blanco mientras React dibuja las filas virtualizadas, y `content-visibility: visible` (react-data-grid lo pone en `auto`). Por eso los colores de hover y selección tienen que ser **opacos** (`color-mix` con blanco): uno translúcido deja ver el patrón como una raya en la fila. Sigue distinto: la barra azul del título de cada grilla y los íconos (acá son los de MUI).
|
|
123
|
+
|
|
124
|
+
### Cambiar contraseña y recuperar clave
|
|
125
|
+
- **Cambiar contraseña** (`/chpass`, `CambiarClavePage`; ícono de llave junto a «Salir»): `POST /chpass` con `oldPassword`, `newPassword` y `repPassword`, como el formulario de backend-plus. El servidor contesta con una redirección: al login si cambió (y **cierra la sesión**) o de vuelta a `/chpass` con el motivo en la página (`.error-message`, `resultadoDeCambioDeClave`; depende del HTML de `chpass.jade`).
|
|
126
|
+
- **«Me olvidé la clave»** en el login es opcional: prop `recuperarClave` de `App` (`true` = `/new-pass`, o la ruta de `login.forget.urlPath`). Es un enlace a la página del backend; el mail y el formulario siguen siendo del servidor, y al terminar queda en el login del servidor, no en el de React.
|
|
127
|
+
|
|
114
128
|
### Sesión y arranque
|
|
115
129
|
- Con el estado todavía sin cargar (`idle`), `PrivateRoute` manda a `/login` guardando la ruta pedida; `InitialRedirectHandler` (montado fuera de las rutas privadas) vuelve a esa ruta cuando la sesión resulta válida. Tiene una guarda para no caer en la pantalla de inicio mientras la ruta guardada se limpia.
|
|
116
130
|
- **No hay `HomePage` ni ruta `/home`: la pantalla de inicio la define el backend, como en `backend-plus`.** `/` (`PantallaInicial`) redirige al ítem de menú con `selectedByDefault` (y, si es un grupo, al que lo declare adentro; `itemInicial`, `rutaDeItemDeMenu` en `utils/menuInicial.ts`, que también arma las rutas del menú lateral). Si el backend no declara ninguno, `/` queda vacía, igual que en `backend-plus`. El login y `InitialRedirectHandler` mandan a `/`. Una aplicación que quiera otra pantalla de inicio la declara en su menú.
|
|
117
131
|
- El cartel «¡Sesión expirada!» solo corresponde si hubo una sesión (guardada de la visita anterior o activa en esta carga). En la primera visita sin sesión, ir al login no lleva cartel.
|
|
132
|
+
- **Cierre de sesión a propósito** (Salir, cambiar la contraseña): no es una sesión expirada (no hay cartel) y **no se recuerda la pantalla** para volver a ella (`utils/cierreVoluntario.ts`, solo en memoria y hasta volver a iniciar sesión; si se guardara, un enlace abierto después de recargar no se recordaría). La pantalla solo se recuerda si se abre un enlace sin sesión o si la cookie se venció.
|
|
133
|
+
- **Cookie vencida**: al volver a ingresar solo vuelve a su pantalla **el mismo usuario** (`redirectUsername` en el router; `AppContext` lo anota al perder la sesión). Una ruta que se pidió sin haber tenido sesión (un enlace compartido) no tiene usuario: vale para cualquiera.
|
|
134
|
+
- Enter en un campo del login ingresa directamente (no pasa el foco al botón).
|
|
118
135
|
|
|
119
136
|
---
|
|
120
137
|
|
|
@@ -151,7 +168,7 @@ Para no perder lo que la grilla de `backend-plus` ya hace y que acá todavía no
|
|
|
151
168
|
|
|
152
169
|
- **Framework**: Vitest + jsdom + Testing Library. **Comandos**: `npm test` (una pasada), `npx vitest` (modo vigilancia), `npm run typecheck`.
|
|
153
170
|
- Los tests viven al lado de lo que prueban (`*.test.ts` / `*.test.tsx`) y están en castellano. La preparación común está en `src/test/preparacion.ts`.
|
|
154
|
-
- Se cubren las funcionalidades críticas y, sobre todo, **cada bug que se arregla lleva su test**: se verifica que falle si se reintroduce el bug. Hoy (
|
|
171
|
+
- Se cubren las funcionalidades críticas y, sobre todo, **cada bug que se arregla lleva su test**: se verifica que falle si se reintroduce el bug. Hoy (243 casos): codificación de parámetros, el menú (búsqueda), el cambio de contraseña y a dónde se vuelve tras ingresar, fixedFields de los detalles, detalle wScreen y `condition`, `PantallaDeRuta`, `ff` del menú, el store de la grilla, la vista de datos (orden, filtros, edición en el lugar), la edición con filtro, la cola de F4, la vuelta a la ruta pedida tras el login, el cartel de sesión expirada y los helpers.
|
|
155
172
|
- jsdom no calcula medidas ni trae `ResizeObserver`: lo que depende del layout (alturas, anchos, virtualización) se prueba en el navegador con `mi-frontend`, no en Vitest.
|
|
156
173
|
- Para el mock de `fetch` y de `fetchApi` usar `vi.stubGlobal` / `vi.mock`; no levantar servidores en los tests.
|
|
157
174
|
- Antes de commitear: `npm run typecheck`, `npm test` y `npm run build`.
|
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@ las decisiones de diseño y cómo probar con un backend real.
|
|
|
29
29
|
|
|
30
30
|
- **Teclado en una celda en edición**: Enter y Tab guardan y pasan a la celda siguiente, Shift+Tab a la anterior, ↑ y ↓ a la de arriba y abajo; ← y → solo salen de la celda al llegar al borde del texto. El clic fuera de la grilla también guarda.
|
|
31
31
|
- **F9 o Alt+↓** (y la lupa junto al editor) abren el selector del tipo de campo: las filas de la tabla referenciada (FK y softFK, con sus campos `isName`), Sí/No, las `options`, un calendario o el contenido completo. Los filtros tienen los mismos selectores (referencias, Sí/No, `options` y fecha). Los filtros tienen los mismos selectores (referencias, Sí/No, `options` y fecha).
|
|
32
|
+
- **Menú lateral** con acordeón, buscador (Ctrl+K) y pantallas recientes; **cambio de contraseña** (`/chpass`) y, opcional, el enlace «me olvidé la clave» del login (prop `recuperarClave`).
|
|
32
33
|
- **Parámetros de la tabla** en la dirección y en el menú, como en backend-plus: `ff` (fixedFields, también con `show`, `range` y `until`), `fc` (filtros iniciales), `td`, `pf`, `pick` y `label`.
|
|
33
34
|
- Un campo con `table` se guarda en esa tabla, y el `width` del campo manda sobre el ancho calculado.
|
|
34
35
|
- Los detalles completos están en `CLAUDE.md`.
|