frontend-plus-react 0.6.0 → 0.8.0
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 +23 -1
- package/README.md +1 -0
- package/dist/index.cjs +945 -514
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +8 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +989 -558
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -100,15 +100,37 @@ Son las de `dmencu` (que aplican a todo proyecto compartido de esta carpeta), es
|
|
|
100
100
|
- `wScreens.table` de `my-menu.js` abre una tabla con lo que declara el ítem de menú y, **encima**, lo de la dirección. Acá lo hace `utils/parametrosDeTabla.ts` (`parametrosDeTabla(item, direccion)`) y lo usan `MenuTablePage` (`/menu/:nombre`) y `GenericDataGridPage` (`/table/:nombre`): `ff` (fixedFields, arreglo `[{fieldName, value, ...}]` u objeto `{campo: valor}`), `fc` (filtros iniciales), `td` (cambios a la definición de la tabla, mezclados en profundidad con `fusionar`, como `changing` de `best-globals`), `pf` y `pick` (viajan en `table_data` como `paramfun` y `pick`, solo si vienen) y `label` (nombre de la pestaña).
|
|
101
101
|
- Los parámetros `ff`, `fc`, `td` y `pf` van codificados con `json4all` (`JSON4all.toUrl` / `parse`, que acepta también JSON común). La dirección se lee como `UriSearchToObject` (partir por `&` y por el primer `=`, `decodeURIComponent`), **no** con `URLSearchParams`: ahí un `+` sería un espacio.
|
|
102
102
|
- **`fc` / `filterColumns`** (el de la definición del servidor también): `[{column, operator, value}]` es una fila de filtros; con varias filas (arreglo de arreglos, alternativas) **solo se aplica la primera** y se avisa por consola: la grilla tiene una sola fila de filtros. El `.d.ts` de `MenuInfoTable` dice `fieldName` en vez de `column`; el cliente de BP usa `column` y se aceptan las dos. Antes `menuInicial.ts` ponía `td` y `fc` en la dirección y nadie los leía.
|
|
103
|
+
- **La ruta de un ítem de menú lleva sus grupos: `/menu/<grupo>/.../<nombre>`** (`rutaDeTablaDeMenu`, `gruposDeItem`, `itemDeRuta` en `utils/menuInicial.ts`; la ruta es `/menu/*`). Los `name` se repiten entre grupos: en dmencu «encuestador», «recuperador», «ingresador» y «supervisor» están en asignación (`t_encu_areas`...) y en recepción (`encuestadores_asignados`...), con tablas distintas. Con `/menu/:nombre` se buscaba el primer ítem con ese nombre: recepción abría la tabla de asignación (sin sus detalles ni la columna de acciones, `clientSide` de `tareas_tem_recepcion`) y el menú marcaba los dos ítems. Los segmentos van con `encodeURIComponent`. Una dirección vieja `/menu/<nombre>` cae en la primera tabla con ese nombre. Quien arma la ruta de un ítem tiene que pasarle sus grupos (`SideMenu` los lleva por `MenuListItem`; la pantalla de inicio los calcula con `gruposDeItem`).
|
|
103
104
|
- **fixedFields** (`utils/fixedFields.ts`, igual que `TableConnector`): uno que fija el valor oculta su columna (salvo `show`), no se edita y no se filtra; uno con `range` o `until` es un rango: la columna se ve, se edita y se filtra.
|
|
104
105
|
|
|
105
106
|
### Anchos de columna
|
|
106
107
|
- Como `backend-plus` (`fieldDef.width` en `my-tables.js`, «Width in pixels for the grid» en el `.d.ts`), el `width` que declara el backend para un campo manda sobre el que se calcula con el título y los datos (`calcularAnchosDeColumnas`). Sin `width` se calcula. Las columnas se pueden arrastrar desde el borde del encabezado (`resizable`, con `columnWidths` en el estado de la grilla); en `backend-plus` el `width` también es el mínimo, acá el usuario puede achicarla.
|
|
107
108
|
|
|
109
|
+
### Columnas ocultas (`hiddenColumns`, como `backend-plus`)
|
|
110
|
+
- Una grilla abre con ocultas las `hiddenColumns` de la definición (el servidor suma ahí los campos `isName: 'known'`, `table-def-adapt.js`; `utils/columnasOcultas.ts`, `columnasOcultasIniciales`). **Un campo con `visible: false` es otra cosa: viaja en la definición pero no se dibuja nunca** (`campoDibujable`): no es una columna oculta que el usuario pueda mostrar, así que no está en el diálogo ni se exporta (`backend-plus` lo trata como oculta; acá se decidió que nunca se vea). Si el menú o la dirección pasan `td` con `hiddenColumns`, se aplica porque la definición ya viene mezclada. Antes `useGridColumns` ignoraba `hiddenColumns`.
|
|
111
|
+
- 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
|
+
- 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
|
+
### Menú lateral (`SideMenu`)
|
|
115
|
+
- **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.
|
|
116
|
+
- **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).
|
|
117
|
+
- **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.
|
|
118
|
+
- Í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.
|
|
119
|
+
|
|
120
|
+
### Estilo alineado con el skin `modern` de backend-skins
|
|
121
|
+
- 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`. Sigue distinto: la barra azul del título de cada grilla y los íconos (acá son los de MUI).
|
|
122
|
+
|
|
123
|
+
### Cambiar contraseña y recuperar clave
|
|
124
|
+
- **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`).
|
|
125
|
+
- **«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.
|
|
126
|
+
|
|
108
127
|
### Sesión y arranque
|
|
109
128
|
- 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.
|
|
110
129
|
- **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ú.
|
|
111
130
|
- 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.
|
|
131
|
+
- **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ó.
|
|
132
|
+
- **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.
|
|
133
|
+
- Enter en un campo del login ingresa directamente (no pasa el foco al botón).
|
|
112
134
|
|
|
113
135
|
---
|
|
114
136
|
|
|
@@ -145,7 +167,7 @@ Para no perder lo que la grilla de `backend-plus` ya hace y que acá todavía no
|
|
|
145
167
|
|
|
146
168
|
- **Framework**: Vitest + jsdom + Testing Library. **Comandos**: `npm test` (una pasada), `npx vitest` (modo vigilancia), `npm run typecheck`.
|
|
147
169
|
- 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`.
|
|
148
|
-
- 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 (
|
|
170
|
+
- 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.
|
|
149
171
|
- 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.
|
|
150
172
|
- Para el mock de `fetch` y de `fetchApi` usar `vi.stubGlobal` / `vi.mock`; no levantar servidores en los tests.
|
|
151
173
|
- 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`.
|