todos-contra-el-fuego-web/PENDIENTE.md
vjrj f775d4ac26 bootstrap: home carousel jQuery plugin -> react-bootstrap <Carousel>
Second (last) jQuery/BS4 JS blocker to the BS5 CSS swap. Replaces the
`bootstrap-carousel-swipe` jQuery plugin + `$(...).carousel()` init with
react-bootstrap's <Carousel> (native swipe, no jQuery) for both home carousels.

- Preserves the progressive `.lazy` background mechanism (blur -> full image on
  slide-in): the old `slide.bs.carousel` handler becomes <Carousel onSlide>,
  which marks the incoming index in component state.
- Keeps all per-slide class hooks (carousel-item-N, carousel-snd-item-N).
- CSS ports in Index-custom.scss for react-bootstrap's BS5 markup: indicators
  render as <button> (not <li>), and prev/next labels use .visually-hidden
  (BS4 had .sr-only) -> add a shim so labels stay hidden on current BS4 CSS.
- Drops the now-unused bootstrap-carousel-swipe dependency.

Full-app build boots clean. Needs a visual staging check of the home page.
2026-07-22 00:13:10 +02:00

7.4 KiB

Pendiente — web "Todos contra el fuego" (rama meteor3-wip)

Estado a 2026-07-18. La migración Meteor 1.6 → 3.1 + MongoDB 7 está completa y verificada (server async, React 18, web renderiza, smoke REST byte-idéntico). Lo que falta, agrupado. Ver UPGRADE.md para el detalle de lo ya hecho.


1. Modernización de librerías react-* antiguas (deuda de front grande)

Funcionan en React 18 por compatibilidad heredada, pero ensucian la consola en desarrollo (no en producción) y bloquean el salto a React 19. Estado:

Lib De → A Estado
react-helmet 5.2 → react-helmet-async 2 hecho
react-i18next + i18next 7.4/10.5 → 14/23 hecho
react-bootstrap 0.31 → 2 hecho (CSS sigue en Bootstrap 4)
reactstrap + 3 deps muertas eliminadas (0 usos)
react-router-dom 4.2 → 6.30 hecho (history 5, HOC withRouterCompat)
react-leaflet + leaflet 1.8/1.3 → 4.2/1.9 hecho (Map→MapContainer, refs directas, useMap/useMapEvents; 4 plugins reimplementados: MapControl portal, GoogleMutantLayer, fullscreen, sleep/graphicscale vanilla; ver UPGRADE.md)
Bootstrap CSS/JS 4.1 → 5 ⏸️ diferida (carrusel/navbar jQuery BS4; ver UPGRADE.md)

Lo verificado en navegador tras cada lib: /, /fires, /fire/archive/<hex>, /login, /subscriptions + consola. Smoke REST byte-idéntico en cada paso. Limpieza de warnings restantes YA hecha: defaultProps en componentes función → parámetros por defecto; UNSAFE_componentWillReceiveProps (FromNow, FireStats, Fires, SelectionMap) → getDerivedStateFromProps/componentDidUpdate; Reconnect (banner Blaze meteorStatus con findDOMNode) → React nativo con useTracker(Meteor.status); react-share 2→5 y react-progress-bar.js → progressbar.js (ambos tiraban findDOMNode/defaultProps); y react-leaflet 1.8→4.2 (mapa central, 4 plugins reimplementados). Tras esto la consola tiene 0 warnings de React en las rutas principales (verificado forzando re-render en / y /fires). Único resto para React 19: el <Blaze serverFacts> de Status.js (findDOMNode), solo en /status (admin).


2. Deuda funcional / de calidad de la web (independiente de prod)

  • Comentarios (feature React nueva): verificación manual en staging. El smoke no llega a la UI. Los métodos (insert/edit/remove/like/dislike) y el embed (mediaAnalyzers) ya están cubiertos por mocha (test/server/comments.test.js), pero quedan por probar a mano en una página de fuego:
    • publicar / editar / borrar un comentario (UI React)
    • like / dislike (toggle)
    • render del embed de imagen y de YouTube
    • email a otros comentaristas (onCommentAdd.js, entrega real de correo)
  • FireContainer endurecido (imports/ui/pages/Fires/Fires.js): el findOne() sin selector ahora se acota por el _id de la URL en la ruta archive (new Meteor.Collection.ObjectID(id)); en active/alert/hash cada publicación deja un único fire en minimongo, así que el read vacío es correcto.
  • Suite de tests con runner (meteortesting:mocha). npm test corre meteor test … --driver-package meteortesting:mocha (watch: npm run test-watch). Tests reescritos a chai + APIs async de Meteor 3 en test/server/*.test.js (server-only), incluyendo cobertura nueva de los métodos de comentarios. Jest y rest.test.js (ya cubierto por smoke/) eliminados. 36 passing. Pendiente menor: portar los casos de token inválido (401/400) de rest.test.js al smoke.
  • Rate-limit de publications (imports/startup/server/api.js): reglas type: 'subscription' vía rateLimitSubscriptions — 5/1000ms en fireFrom* y comments.forReference; 10/1000ms en las subs geo (map pan/zoom).
  • Google Maps con loading=async (imports/startup/client/Gkeys.js): se envuelve GoogleMapsLoader.createUrl para añadir el parámetro (el paquete google-maps npm no expone hook). Verificar en staging que el mapa carga y el aviso de consola desaparece.
  • meteor-accounts-t9n actualizado a ^2.6.0 (es/en OK). El paquete sigue sin build gallego (gl), así que se mantiene el fallback gl→es documentado en i18n.js. Traducción gallega de la app (gl/common.json): 0 claves faltantes.
  • Salto Bootstrap 4→5 (CSS/JS) pendiente: react-bootstrap ya está en v2 y corre sobre el CSS Bootstrap 4 actual (alexwine:bootstrap-4) con un único shim .form-label en forms.scss. Ya no quedan dependencias del JS jQuery de BS4 — los dos blockers se migraron a React:
    • Collapse del navbar (Navigation.js + NavItem.js): data-toggle= "collapse" jQuery → estado React (useState que alterna .show). Verificar en staging el menú móvil (<lg): abrir/cerrar y cierre al pulsar un enlace.
    • Carrusel del home (Index.js): bootstrap-carousel-swipe (jQuery) + $(...).carousel()<Carousel> de react-bootstrap con swipe nativo; se conserva el mecanismo .lazy de fondos (blur→full) vía onSlide. Dep bootstrap-carousel-swipe eliminada. Ports de CSS en Index-custom.scss: indicadores libutton (markup BS5) y shim .visually-hidden. Verificar en staging el home: transiciones, swipe, indicadores, prev/next y carga progresiva de las imágenes de fondo.
    • Falta (el salto de CSS en sí, ya sin bloqueos de JS): importar bootstrap@5 SCSS+JS, ml-automs-auto (y demás utilidades direccionales), revisar new-age.scss/custom.scss/bootstrap-overrides.scss y retirar alexwine:bootstrap-4.
  • Limpieza menor: migración 217 // TODO remove falsepositives lowercase collection; prerender.js gating comentado; sección per-fire del sitemap eliminada (era código muerto tras firesMapEnabled=false).

3. Observabilidad (Sentry/GlitchTip) — casi cerrado

  • Server-side reporta a GlitchTip; cliente vía túnel /sentry-tunnel (esquiva el 503 de Cloudflare). DSN en settings-development.json (gitignored).
  • Pendiente: poner el DSN en el METEOR_SETTINGS de producción y confirmar que el servidor de prod alcanza GlitchTip (IPv4). Nota: el túnel es un relay acotado al proyecto propio (aceptable, documentado).
  • Consola de dev: warnings de librería restantes solo se van con el punto 1.

4. Cutover a producción (infra — fase 3, es lo grande)

  • Migrar datos Mongo 3.2 → 7 (mongodump/restore) en el servidor real.
  • Desplegar el stack (Docker) al servidor limpio vía el ansible de Comunes — NO al viejo shiva. Ver RUNBOOK.md (stack compose local validado).
  • Coordinar orden con notificaciones: la web NO debe desplegarse antes de que el microservicio tcef-notifications emita en prod (si no, los usuarios dejan de recibir avisos). Ver dependencia en UPGRADE.md.
  • Secretos de prod (METEOR_SETTINGS, no el fichero gitignored), cron del GeoLite2 City (MaxMind) en el nuevo host, proxy/TLS por el ansible compartido.

5. Fuera del repo web (bloquean el "hecho" global, pistas aparte)

  • tcef-notifications: rollout por canal shadow→canary→full (FCM en canary superado; email y telegram pendientes) y redeploy del servicio actualizado.
  • App móvil fires_flutter: republicación en Play Store.

Regla de trabajo en todo lo anterior: commits locales atómicos en meteor3-wip, smoke REST byte-idéntico tras cada cambio, verificación visual en navegador, y NUNCA git push.