build: actualizar dist con la versión de producción más reciente
This commit is contained in:
+75
-8
@@ -35,6 +35,7 @@ import {
|
||||
deleteHubApp,
|
||||
fetchHubApps,
|
||||
fetchHubData,
|
||||
fetchMyAppAccess,
|
||||
migrateLocalAppsIfNeeded,
|
||||
recordRecent,
|
||||
saveHubApp,
|
||||
@@ -536,14 +537,29 @@ function MobileNav({ user, view, onNavigate, onLogout }: MobileNavProps) {
|
||||
);
|
||||
}
|
||||
|
||||
type AccessState = boolean | null;
|
||||
|
||||
function AccessIndicator({ hasAccess }: { hasAccess: AccessState }) {
|
||||
const label = hasAccess === null ? "Verificando acceso" : hasAccess ? "Disponible" : "Sin acceso";
|
||||
const stateClass = hasAccess === null ? "access-indicator--checking" : hasAccess ? "access-indicator--granted" : "access-indicator--denied";
|
||||
|
||||
return (
|
||||
<span className={`access-indicator ${stateClass}`} aria-label={label}>
|
||||
<span aria-hidden="true" />
|
||||
{label}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
interface QuickLaunchProps {
|
||||
app: HubApp;
|
||||
isFavorite: boolean;
|
||||
hasAccess: AccessState;
|
||||
onActivate: (app: HubApp) => void;
|
||||
onFavorite: (appId: string) => void;
|
||||
}
|
||||
|
||||
function QuickLaunch({ app, isFavorite, onActivate, onFavorite }: QuickLaunchProps) {
|
||||
function QuickLaunch({ app, isFavorite, hasAccess, onActivate, onFavorite }: QuickLaunchProps) {
|
||||
const available = Boolean(getSafeUrl(app.url));
|
||||
return (
|
||||
<article className="quick-launch">
|
||||
@@ -560,7 +576,10 @@ function QuickLaunch({ app, isFavorite, onActivate, onFavorite }: QuickLaunchPro
|
||||
</button>
|
||||
</div>
|
||||
<div className="quick-launch__copy">
|
||||
<span className="quick-launch__category">{app.category}</span>
|
||||
<div className="quick-launch__meta">
|
||||
<span className="quick-launch__category">{app.category}</span>
|
||||
<AccessIndicator hasAccess={hasAccess} />
|
||||
</div>
|
||||
<h3>{app.name}</h3>
|
||||
<p>{app.description}</p>
|
||||
</div>
|
||||
@@ -576,11 +595,12 @@ interface DirectoryRowProps {
|
||||
app: HubApp;
|
||||
index: number;
|
||||
isFavorite: boolean;
|
||||
hasAccess: AccessState;
|
||||
onActivate: (app: HubApp) => void;
|
||||
onFavorite: (appId: string) => void;
|
||||
}
|
||||
|
||||
function DirectoryRow({ app, index, isFavorite, onActivate, onFavorite }: DirectoryRowProps) {
|
||||
function DirectoryRow({ app, index, isFavorite, hasAccess, onActivate, onFavorite }: DirectoryRowProps) {
|
||||
const available = Boolean(getSafeUrl(app.url));
|
||||
return (
|
||||
<article className="directory-row">
|
||||
@@ -591,9 +611,8 @@ function DirectoryRow({ app, index, isFavorite, onActivate, onFavorite }: Direct
|
||||
<p>{app.description}</p>
|
||||
</div>
|
||||
<span className="directory-row__category">{app.category}</span>
|
||||
<span className={`availability ${available ? "availability--ready" : "availability--pending"}`}>
|
||||
<span aria-hidden="true" />
|
||||
{available ? "Disponible" : "Enlace pendiente"}
|
||||
<span className="directory-row__status">
|
||||
<AccessIndicator hasAccess={hasAccess} />
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
@@ -880,11 +899,13 @@ function Pagination({ currentPage, totalPages, onPageChange, compact = false, la
|
||||
|
||||
const HUB_ITEMS_PER_PAGE = 10;
|
||||
const QUICK_ITEMS_PER_PAGE = 6;
|
||||
const ADMIN_ITEMS_PER_PAGE = 10;
|
||||
const ADMIN_ITEMS_PER_PAGE = 12;
|
||||
|
||||
interface HubViewProps {
|
||||
user: HubUser;
|
||||
data: HubData;
|
||||
accessByApp: Record<string, boolean>;
|
||||
accessReady: boolean;
|
||||
storageWarning: string;
|
||||
onActivate: (app: HubApp) => void;
|
||||
onFavorite: (appId: string) => void;
|
||||
@@ -892,7 +913,7 @@ interface HubViewProps {
|
||||
onRequestAccess: (app: HubApp) => Promise<boolean>;
|
||||
}
|
||||
|
||||
function HubView({ user, data, storageWarning, onActivate, onFavorite, onAdmin, onRequestAccess }: HubViewProps) {
|
||||
function HubView({ user, data, accessByApp, accessReady, storageWarning, onActivate, onFavorite, onAdmin, onRequestAccess }: HubViewProps) {
|
||||
const [categorySearches, setCategorySearches] = useState<Record<string, string>>({
|
||||
Todas: "",
|
||||
Administración: "",
|
||||
@@ -1068,6 +1089,7 @@ function HubView({ user, data, storageWarning, onActivate, onFavorite, onAdmin,
|
||||
key={app.id}
|
||||
app={app}
|
||||
isFavorite={favorites.has(app.id)}
|
||||
hasAccess={accessReady ? accessByApp[app.id] === true : null}
|
||||
onActivate={onActivate}
|
||||
onFavorite={onFavorite}
|
||||
/>
|
||||
@@ -1152,6 +1174,7 @@ function HubView({ user, data, storageWarning, onActivate, onFavorite, onAdmin,
|
||||
app={app}
|
||||
index={(currentPage - 1) * HUB_ITEMS_PER_PAGE + index}
|
||||
isFavorite={favorites.has(app.id)}
|
||||
hasAccess={accessReady ? accessByApp[app.id] === true : null}
|
||||
onActivate={onActivate}
|
||||
onFavorite={onFavorite}
|
||||
/>
|
||||
@@ -1861,6 +1884,8 @@ function App() {
|
||||
const [authReady, setAuthReady] = useState(false);
|
||||
const [catalogReady, setCatalogReady] = useState(false);
|
||||
const [catalogWarning, setCatalogWarning] = useState("");
|
||||
const [accessByApp, setAccessByApp] = useState<Record<string, boolean>>({});
|
||||
const [accessReady, setAccessReady] = useState(false);
|
||||
const [loginError, setLoginError] = useState("");
|
||||
const authorizationSequence = useRef(0);
|
||||
const authorizedUserIdRef = useRef<string | null>(null);
|
||||
@@ -2011,6 +2036,44 @@ function App() {
|
||||
};
|
||||
}, [activeUser?.id, activeUser?.role, initialLocalData.data.apps, notify]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!activeUser) {
|
||||
setAccessByApp({});
|
||||
setAccessReady(false);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let active = true;
|
||||
let loading = false;
|
||||
|
||||
const refreshAccess = async () => {
|
||||
if (loading) return;
|
||||
loading = true;
|
||||
try {
|
||||
const accessMap = await fetchMyAppAccess();
|
||||
if (!active) return;
|
||||
setAccessByApp(accessMap);
|
||||
setAccessReady(true);
|
||||
} catch (error) {
|
||||
console.warn("No se pudo verificar el acceso a las aplicaciones:", error);
|
||||
if (active) setAccessReady(false);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
void refreshAccess();
|
||||
const intervalId = window.setInterval(() => void refreshAccess(), 60_000);
|
||||
const handleFocus = () => void refreshAccess();
|
||||
window.addEventListener("focus", handleFocus);
|
||||
|
||||
return () => {
|
||||
active = false;
|
||||
window.clearInterval(intervalId);
|
||||
window.removeEventListener("focus", handleFocus);
|
||||
};
|
||||
}, [activeUser?.id]);
|
||||
|
||||
useEffect(() => {
|
||||
const syncViewWithHash = () => {
|
||||
const requestedView: AppView = window.location.hash === "#admin" ? "admin" : "hub";
|
||||
@@ -2240,6 +2303,8 @@ function App() {
|
||||
}
|
||||
setSession(null);
|
||||
setCatalogReady(false);
|
||||
setAccessByApp({});
|
||||
setAccessReady(false);
|
||||
setView("hub");
|
||||
window.history.replaceState(null, "", getAppUrl());
|
||||
};
|
||||
@@ -2281,6 +2346,8 @@ function App() {
|
||||
<HubView
|
||||
user={session.user}
|
||||
data={data}
|
||||
accessByApp={accessByApp}
|
||||
accessReady={accessReady}
|
||||
storageWarning={catalogWarning}
|
||||
onActivate={handleActivate}
|
||||
onFavorite={(appId) => void handleFavorite(appId)}
|
||||
|
||||
Reference in New Issue
Block a user