fix(frontend): replace stacked spinners on agent pages with skeletons

This commit is contained in:
ManishMadan2882 committed 2026-09-22 04:48:46 +05:30
1 parent 295969b6a4
commit 6282161b5a
3 files changed
+78 -43

No files matched your search

+6 -17
View File
@@ -4,7 +4,6 @@ import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import userService from '../api/services/userService';
import Spinner from '../components/Spinner';
import { selectToken } from '../preferences/preferenceSlice';
import Analytics from '../settings/Analytics';
import Logs from '../settings/Logs';
@@ -67,22 +66,12 @@ export default function AgentLogs() {
</div>
)}
</div>
{loadingAgent ? (
<div className="flex h-[345px] w-full items-center justify-center">
<Spinner />
</div>
) : (
agent && <Analytics agentId={agent.id} />
)}
{!loadingAgent && agent && <GuardrailEvents agentId={agent.id} />}
{loadingAgent ? (
<div className="flex h-[55vh] w-full items-center justify-center">
<Spinner />
</div>
) : (
agent && (
<Logs agentId={agent.id} tableHeader={t('agents.logs.tableHeader')} />
)
{agentId && (loadingAgent || agent) && (
<>
<Analytics agentId={agentId} />
<GuardrailEvents agentId={agentId} />
<Logs agentId={agentId} tableHeader={t('agents.logs.tableHeader')} />
</>
)}
</div>
);
+50 -26
View File
@@ -5,7 +5,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { useNavigate, useSearchParams } from 'react-router-dom';
import userService from '../api/services/userService';
import Spinner from '../components/Spinner';
import SkeletonLoader from '../components/SkeletonLoader';
import { Button } from '../components/ui/button';
import { Input } from '../components/ui/input';
import {
@@ -155,7 +155,14 @@ export default function AgentsList() {
return hasAgentsInSection;
});
const showPageLoader =
activeFilter === 'all' &&
agentSectionsConfig.some(
(config) => !isDataLoaded[config.id as AgentSectionId],
);
const showSearchEmptyState =
!showPageLoader &&
searchQuery &&
hasAnyAgents &&
!hasFilteredResults &&
@@ -207,29 +214,46 @@ export default function AgentsList() {
</div>
</div>
{visibleSections.map((sectionConfig) => (
<AgentSection
key={sectionConfig.id}
config={sectionConfig}
filteredAgents={
filteredAgentsBySection[sectionConfig.id as AgentSectionId]
}
totalAgents={totalAgentsBySection[sectionConfig.id as AgentSectionId]}
searchQuery={searchQuery}
isFilteredView={activeFilter !== 'all'}
isLoading={isLoading[sectionConfig.id as AgentSectionId]}
folders={sectionConfig.id === 'user' ? folders : null}
folderPath={sectionConfig.id === 'user' ? folderPath : []}
onFolderPathChange={
sectionConfig.id === 'user' ? setFolderPath : undefined
}
onCreateFolder={handleSubmitNewFolder}
onDeleteFolder={handleDeleteFolder}
onRenameFolder={handleRenameFolder}
setModalFolderId={setModalFolderId}
setShowAgentTypeModal={setShowAgentTypeModal}
/>
))}
{showPageLoader ? (
<div className="mt-8 flex flex-col gap-4">
<div className="flex animate-pulse flex-col gap-2">
<div className="bg-muted h-7 w-32 rounded"></div>
<div className="bg-muted h-5 w-64 max-w-full rounded"></div>
</div>
<div className="grid grid-cols-2 gap-3 sm:flex sm:flex-wrap">
<SkeletonLoader component="agentCards" count={4} />
</div>
</div>
) : (
visibleSections.map((sectionConfig) => (
<AgentSection
key={sectionConfig.id}
config={sectionConfig}
filteredAgents={
filteredAgentsBySection[sectionConfig.id as AgentSectionId]
}
totalAgents={
totalAgentsBySection[sectionConfig.id as AgentSectionId]
}
searchQuery={searchQuery}
isFilteredView={activeFilter !== 'all'}
isLoading={
isLoading[sectionConfig.id as AgentSectionId] &&
!isDataLoaded[sectionConfig.id as AgentSectionId]
}
folders={sectionConfig.id === 'user' ? folders : null}
folderPath={sectionConfig.id === 'user' ? folderPath : []}
onFolderPathChange={
sectionConfig.id === 'user' ? setFolderPath : undefined
}
onCreateFolder={handleSubmitNewFolder}
onDeleteFolder={handleDeleteFolder}
onRenameFolder={handleRenameFolder}
setModalFolderId={setModalFolderId}
setShowAgentTypeModal={setShowAgentTypeModal}
/>
))
)}
{showSearchEmptyState && (
<div className="text-muted-foreground mt-12 flex flex-col items-center justify-center gap-2">
@@ -574,8 +598,8 @@ function AgentSection({
<div className="flex flex-col gap-4">
{isLoading ? (
<div className="flex h-40 w-full items-center justify-center">
<Spinner />
<div className="grid grid-cols-2 gap-3 sm:flex sm:flex-wrap">
<SkeletonLoader component="agentCards" count={4} />
</div>
) : (
<>
@@ -13,6 +13,7 @@ interface SkeletonLoaderProps {
| 'sourceCards'
| 'toolCards'
| 'addToolCards'
| 'agentCards'
| 'connectedState'
| 'filesSection';
}
@@ -264,6 +265,26 @@ const SkeletonLoader: React.FC<SkeletonLoaderProps> = ({
</>
);
const renderAgentCards = () => (
<>
{Array.from({ length: count }).map((_, idx) => (
<div
key={`agent-skel-${idx}`}
className="bg-muted flex h-44 animate-pulse flex-col rounded-2xl px-4 py-5 sm:w-48 sm:px-6"
>
<div className="px-1">
<div className="bg-muted-foreground/20 h-7 w-7 rounded-full"></div>
</div>
<div className="mt-3 space-y-2 px-1">
<div className="bg-muted-foreground/20 h-4 w-2/3 rounded"></div>
<div className="bg-muted-foreground/20 h-3 w-full rounded"></div>
<div className="bg-muted-foreground/20 h-3 w-4/5 rounded"></div>
</div>
</div>
))}
</>
);
const renderToolCards = () => (
<>
{Array.from({ length: count }).map((_, idx) => (
@@ -325,6 +346,7 @@ const SkeletonLoader: React.FC<SkeletonLoaderProps> = ({
sourceCards: renderSourceCards,
toolCards: renderToolCards,
addToolCards: renderAddToolCards,
agentCards: renderAgentCards,
connectedState: renderConnectedState,
filesSection: renderFilesSection,
};