Completes the Bootstrap 4->5 migration now that every jQuery/BS4 widget is React
(navbar, carousel, dropdowns) — plus the feedback toggle here (Feedback.js:
global `$('#feedback-form').toggle()` -> React state).
- Load Bootstrap 5 CSS from the `bootstrap` npm package in client/index.js
(imported first so app + component styles and react-bootstrap override it).
- Remove the `alexwine:bootstrap-4` meteor package (BS4 CSS + jQuery + BS4 JS).
jQuery for jquery-validation still comes from the npm `jquery` dep.
- Utility renames to BS5: ml-auto->ms-auto, float-right->float-end,
btn-block->w-100, data-toggle->data-bs-toggle (FromNow tooltip).
- forms.scss `.form-label` is no longer a shim (BS5 ships it); comment updated.
Full-app build boots clean; server suite 36 passing. Needs a visual staging pass
across all pages (BS4->5 shifts grid gutters/typography); forms should improve
since react-bootstrap v2 already emitted BS5 markup.
7.7 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)
- ✅
FireContainerendurecido (imports/ui/pages/Fires/Fires.js): elfindOne()sin selector ahora se acota por el_idde la URL en la rutaarchive(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 testcorremeteor test … --driver-package meteortesting:mocha(watch:npm run test-watch). Tests reescritos achai+ APIs async de Meteor 3 entest/server/*.test.js(server-only), incluyendo cobertura nueva de los métodos de comentarios. Jest yrest.test.js(ya cubierto porsmoke/) eliminados. 36 passing. Pendiente menor: portar los casos de token inválido (401/400) derest.test.jsal smoke. - ✅ Rate-limit de publications (
imports/startup/server/api.js): reglastype: 'subscription'víarateLimitSubscriptions— 5/1000ms enfireFrom*ycomments.forReference; 10/1000ms en las subs geo (map pan/zoom). - ✅ Google Maps con
loading=async(imports/startup/client/Gkeys.js): se envuelveGoogleMapsLoader.createUrlpara añadir el parámetro (el paquetegoogle-mapsnpm no expone hook). Verificar en staging que el mapa carga y el aviso de consola desaparece. - ✅
meteor-accounts-t9nactualizado a^2.6.0(es/en OK). El paquete sigue sin build gallego (gl), así que se mantiene el fallback gl→es documentado eni18n.js. Traducción gallega de la app (gl/common.json): 0 claves faltantes. - ✅ Salto Bootstrap 4→5 (CSS/JS) hecho — react-bootstrap v2 ahora corre sobre
su CSS nativo (BS5). Compila y arranca; falta SOLO verificación visual en
staging (BS4→5 cambia sutilezas de grid/gutters/tipografía en todas las páginas).
- Widgets jQuery/BS4 migrados a React (los blockers): navbar collapse
(
Navigation.js/NavItem.js), carrusel del home (Index.js→<Carousel>, conserva.lazyvíaonSlide), dropdowns de idioma/tipo (Profile.js/Fires.js→<Dropdown>), y toggle del feedback (Feedback.js→ estado React). Depsbootstrap-carousel-swipeyalexwine:bootstrap-4eliminadas; jQuery global ya no se usa (solojquery+jquery-validationvía npm envalidate.js). - CSS:
bootstrap@5npm importado enimports/startup/client/index.js(antes queapp.scss, para que los overrides ganen). Renombres de utilidades:ml-auto→ms-auto,float-right→float-end,btn-block→w-100,data-toggle→data-bs-toggle,sr-only→.visually-hidden(shim). - QA visual pendiente en staging (todas las páginas): formularios (react-
bootstrap ya emite markup BS5 → deberían mejorar), navbar, botones, modales,
cards, grid/gutters, y los widgets migrados (menú móvil, carrusel, dropdowns,
feedback). Alertas de
themeteorchef:bert(comprobar que siguen bien sin el jQuery de alexwine). - Menor:
popper.js@1enpackage.jsones legacy sin uso (react-bootstrap trae@popperjs/core@2) → se puede quitar. El bloque.form-labeldeforms.scssya es redundante (BS5 lo trae) salvo por eldisplay:blockexplícito.
- Widgets jQuery/BS4 migrados a React (los blockers): navbar collapse
(
- Limpieza menor: migración 217
// TODO remove falsepositives lowercase collection;prerender.jsgating comentado; sección per-fire del sitemap eliminada (era código muerto trasfiresMapEnabled=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 ensettings-development.json(gitignored). - Pendiente: poner el DSN en el
METEOR_SETTINGSde 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-notificationsemita en prod (si no, los usuarios dejan de recibir avisos). Ver dependencia enUPGRADE.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.