feat: version 2.3.0 -- aviso de actualizacion pendiente al iniciar sesion

Superadmin ve un popup con acceso directo a Configuracion >
Actualizaciones si hay una version nueva disponible, en vez de tener
que acordarse de revisar el panel manualmente.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Milton Gonzalez
2026-09-22 12:49:00 -05:00
parent 74dc1ce5d7
commit ea0feb7e3a
7 changed files with 64 additions and 9 deletions
+28 -2
View File
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { Outlet, useNavigate } from 'react-router-dom';
import { Menu, Sun, Moon, Bell, LogOut, User, Globe, KeyRound, Save } from 'lucide-react';
import { NavigationView } from '../components/NavigationView.jsx';
@@ -12,13 +12,14 @@ import { useUi } from '../context/ui-context.jsx';
import { useAsync } from '../hooks/useAsync.js';
import { listNotifications, markAllNotificationsRead, markNotificationRead } from '../services/notifications.js';
import { changePassword } from '../services/auth.js';
import { getUpdateStatus } from '../services/updater.js';
const EMPTY_PASSWORD_FORM = { currentPassword: '', newPassword: '', confirmPassword: '' };
export default function AppShell() {
const [navMode, setNavMode] = useState('expanded');
const { user, logout } = useAuth();
const { t, theme, setTheme, lang, setLang, pushToast } = useUi();
const { t, theme, setTheme, lang, setLang, pushToast, openDialog } = useUi();
const navigate = useNavigate();
const { data: notifData, reload: reloadNotifications } = useAsync(listNotifications, []);
@@ -28,6 +29,31 @@ export default function AppShell() {
const [passwordForm, setPasswordForm] = useState(EMPTY_PASSWORD_FORM);
const [passwordError, setPasswordError] = useState('');
// Al entrar (una vez por sesion, no en cada navegacion): si es superadmin y hay una
// actualizacion pendiente, avisar con un popup y un acceso directo al panel. Silencioso si
// falla (ej. Gitea sin conexion) -- no debe molestar el login por un chequeo secundario.
useEffect(() => {
if (user?.roleCode !== 'superadmin') return;
getUpdateStatus()
.then((status) => {
if (status.upToDate) return;
openDialog({
tone: 'warning',
title: t('updater_login_popup_title'),
message: `${t('updater_login_popup_msg')} v${status.currentVersion} → v${status.latestVersion}`,
actions: [
{ label: t('common_close'), variant: 'standard' },
{
label: t('updater_login_popup_go'), variant: 'accent',
onClick: () => navigate('/configuracion?open=updates'),
},
],
});
})
.catch(() => {});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
function toggleNav() {
setNavMode((m) => (m === 'expanded' ? 'compact' : 'expanded'));
}