mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-13 08:15:43 +00:00
fix(frontend): replace stacked spinners on agent pages with skeletons
This commit is contained in:
1 parent
295969b6a4
commit
6282161b5a
3 files changed
+78
-43
No files matched your search
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user