fix: version 2.2.4 -- ocultar boton Actualizar automaticamente al terminar
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
# Changelog - project.linkedcorp.net
|
# Changelog - project.linkedcorp.net
|
||||||
|
|
||||||
|
## [2.2.4] - 2026-09-22
|
||||||
|
### Fixed
|
||||||
|
- El botón "Actualizar" se quedaba visible después de aplicar la actualización, hasta que se
|
||||||
|
refrescaba la pestaña a mano. Ahora, mientras se aplica, el panel consulta el estado cada
|
||||||
|
pocos segundos y en cuanto confirma que ya quedó en la última versión, el botón desaparece
|
||||||
|
solo (sin depender de la recarga automática del service worker).
|
||||||
|
|
||||||
## [2.2.3] - 2026-09-22
|
## [2.2.3] - 2026-09-22
|
||||||
### Fixed
|
### Fixed
|
||||||
- Al actualizar (ya sea con el botón nuevo o por deploy manual), la pestaña abierta seguía
|
- Al actualizar (ya sea con el botón nuevo o por deploy manual), la pestaña abierta seguía
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "project-linkedcorp-backend",
|
"name": "project-linkedcorp-backend",
|
||||||
"version": "2.2.3",
|
"version": "2.2.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/server.js",
|
"main": "src/server.js",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "project-linkedcorp-frontend",
|
"name": "project-linkedcorp-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2.2.3",
|
"version": "2.2.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { RefreshCw, Download } from 'lucide-react';
|
import { RefreshCw, Download } from 'lucide-react';
|
||||||
import { useUi } from '../../context/ui-context.jsx';
|
import { useUi } from '../../context/ui-context.jsx';
|
||||||
import { useAsync, useAction } from '../../hooks/useAsync.js';
|
import { useAsync, useAction } from '../../hooks/useAsync.js';
|
||||||
@@ -8,12 +8,36 @@ import { Badge } from '../../components/Badge.jsx';
|
|||||||
import { InfoBar } from '../../components/InfoBar.jsx';
|
import { InfoBar } from '../../components/InfoBar.jsx';
|
||||||
|
|
||||||
const CRITICALITY_COLOR = { alta: 'danger', media: 'warning', baja: 'success' };
|
const CRITICALITY_COLOR = { alta: 'danger', media: 'warning', baja: 'success' };
|
||||||
|
const POLL_INTERVAL_MS = 5000;
|
||||||
|
const POLL_MAX_ATTEMPTS = 60; // ~5 minutos tope
|
||||||
|
|
||||||
export default function UpdaterPanel() {
|
export default function UpdaterPanel() {
|
||||||
const { t, openDialog, pushToast } = useUi();
|
const { t, openDialog, pushToast } = useUi();
|
||||||
const { data: status, loading, error, reload } = useAsync(getUpdateStatus, []);
|
const { data: status, loading, error, reload, setData } = useAsync(getUpdateStatus, []);
|
||||||
const runAction = useAction();
|
const runAction = useAction();
|
||||||
const [applying, setApplying] = useState(false);
|
const [applying, setApplying] = useState(false);
|
||||||
|
const mountedRef = useRef(true);
|
||||||
|
useEffect(() => () => { mountedRef.current = false; }, []);
|
||||||
|
|
||||||
|
// El servidor se reinicia a mitad de la actualizacion (backend y frontend), asi que durante
|
||||||
|
// ese rato las llamadas van a fallar por un momento -- se ignoran y se sigue insistiendo.
|
||||||
|
// Cuando confirma que ya esta al dia, el boton "Actualizar" desaparece solo (esta gateado por
|
||||||
|
// !status.upToDate mas abajo) sin depender de que la pestaña se recargue.
|
||||||
|
async function pollUntilUpToDate() {
|
||||||
|
for (let i = 0; i < POLL_MAX_ATTEMPTS && mountedRef.current; i++) {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
||||||
|
if (!mountedRef.current) return;
|
||||||
|
try {
|
||||||
|
const result = await getUpdateStatus();
|
||||||
|
if (!mountedRef.current) return;
|
||||||
|
setData(result);
|
||||||
|
if (result.upToDate) { setApplying(false); return; }
|
||||||
|
} catch {
|
||||||
|
// backend reiniciandose -- se ignora y se reintenta en el proximo ciclo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mountedRef.current) setApplying(false);
|
||||||
|
}
|
||||||
|
|
||||||
function confirmApply() {
|
function confirmApply() {
|
||||||
openDialog({
|
openDialog({
|
||||||
@@ -28,7 +52,7 @@ export default function UpdaterPanel() {
|
|||||||
setApplying(true);
|
setApplying(true);
|
||||||
await applyUpdate();
|
await applyUpdate();
|
||||||
pushToast({ tone: 'success', message: t('updater_apply_started') });
|
pushToast({ tone: 'success', message: t('updater_apply_started') });
|
||||||
}).finally(() => setApplying(false)),
|
}).then(pollUntilUpToDate).catch(() => setApplying(false)),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user