Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import { CredentialsSkeleton } from '@/app/workspace/[workspaceId]/settings/comp
import { CustomToolsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/custom-tools/custom-tool-skeleton'
import { GeneralSkeleton } from '@/app/workspace/[workspaceId]/settings/components/general/general-skeleton'
import { InboxSkeleton } from '@/app/workspace/[workspaceId]/settings/components/inbox/inbox-skeleton'
import { IntegrationsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/integrations/integrations-skeleton'
import { McpSkeleton } from '@/app/workspace/[workspaceId]/settings/components/mcp/mcp-skeleton'
import { RecentlyDeletedSkeleton } from '@/app/workspace/[workspaceId]/settings/components/recently-deleted/recently-deleted-skeleton'
import { SkillsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/skills/skill-skeleton'
import { WorkflowMcpServersSkeleton } from '@/app/workspace/[workspaceId]/settings/components/workflow-mcp-servers/workflow-mcp-servers-skeleton'
import type { SettingsSection } from '@/app/workspace/[workspaceId]/settings/navigation'
Expand Down Expand Up @@ -52,7 +54,7 @@ const Integrations = dynamic(
import('@/app/workspace/[workspaceId]/settings/components/integrations/integrations').then(
(m) => m.Integrations
),
{ loading: () => <CredentialsSkeleton /> }
{ loading: () => <IntegrationsSkeleton /> }
)
const Credentials = dynamic(
() =>
Expand Down Expand Up @@ -145,7 +147,7 @@ const RecentlyDeleted = dynamic(
import(
'@/app/workspace/[workspaceId]/settings/components/recently-deleted/recently-deleted'
).then((m) => m.RecentlyDeleted),
{ loading: () => <SettingsSectionSkeleton /> }
{ loading: () => <RecentlyDeletedSkeleton /> }
)
const AccessControl = dynamic(
() => import('@/ee/access-control/components/access-control').then((m) => m.AccessControl),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,71 @@
import { Skeleton } from '@/components/emcn'

/**
* Skeleton component for admin settings loading state.
* Matches the exact layout structure of the Admin component.
*/
export function AdminSkeleton() {
return (
<div className='flex h-full flex-col gap-6'>
<div className='flex items-center justify-between'>
<Skeleton className='h-[14px] w-[120px]' />
<Skeleton className='h-[20px] w-[36px] rounded-full' />
</div>

<div className='h-px bg-[var(--border-secondary)]' />

<div className='flex flex-col gap-2'>
<Skeleton className='h-[14px] w-[340px]' />
<div className='flex gap-2'>
<Skeleton className='h-9 flex-1 rounded-md' />
<Skeleton className='h-9 w-[80px] rounded-md' />
</div>
</div>
<div className='flex flex-col gap-2'>

<div className='h-px bg-[var(--border-secondary)]' />

<div className='flex flex-col gap-3'>
<Skeleton className='h-[14px] w-[120px]' />
<Skeleton className='h-[200px] w-full rounded-lg' />

<div className='flex gap-2'>
<Skeleton className='h-9 flex-1 rounded-md' />
<Skeleton className='h-9 w-[80px] rounded-md' />
</div>

<div className='flex flex-col gap-0.5'>
<div className='flex items-center gap-3 border-[var(--border-secondary)] border-b px-3 py-2'>
<Skeleton className='h-[12px] w-[200px]' />
<Skeleton className='h-[12px] flex-1' />
<Skeleton className='h-[12px] w-[80px]' />
<Skeleton className='h-[12px] w-[80px]' />
<Skeleton className='h-[12px] w-[250px]' />
</div>

{Array.from({ length: 5 }).map((_, i) => (
<div
key={i}
className='flex items-center gap-3 border-[var(--border-secondary)] border-b px-3 py-2 last:border-b-0'
>
<Skeleton className='h-[14px] w-[200px]' />
<Skeleton className='h-[14px] flex-1' />
<Skeleton className='h-[20px] w-[50px] rounded-full' />
<Skeleton className='h-[20px] w-[50px] rounded-full' />
<div className='flex w-[250px] justify-end gap-1'>
<Skeleton className='h-[28px] w-[80px] rounded-md' />
<Skeleton className='h-[28px] w-[64px] rounded-md' />
<Skeleton className='h-[28px] w-[40px] rounded-md' />
</div>
</div>
))}
</div>

<div className='flex items-center justify-between'>
<Skeleton className='h-[14px] w-[160px]' />
<div className='flex gap-1'>
<Skeleton className='h-[28px] w-[64px] rounded-md' />
<Skeleton className='h-[28px] w-[48px] rounded-md' />
</div>
</div>
</div>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,31 @@ export function ApiKeysSkeleton() {
return (
<div className='flex h-full flex-col gap-4.5'>
<div className='flex items-center gap-2'>
<Skeleton className='h-[30px] flex-1 rounded-lg' />
<Skeleton className='h-[30px] w-[80px] rounded-md' />
<Skeleton className='h-[38px] flex-1 rounded-lg' />
<Skeleton className='h-[38px] w-[90px] rounded-md' />
</div>
<div className='flex flex-col gap-2'>
<ApiKeySkeleton />
<ApiKeySkeleton />

<div className='min-h-0 flex-1 overflow-y-auto'>
<div className='flex flex-col gap-4.5'>
<div className='flex flex-col gap-2'>
<Skeleton className='h-5 w-[80px]' />
<Skeleton className='h-5 w-[180px]' />
</div>

<div className='flex flex-col gap-2'>
<Skeleton className='h-5 w-[60px]' />
<ApiKeySkeleton />
<ApiKeySkeleton />
</div>
</div>
</div>

<div className='mt-6 flex items-center justify-between'>
<div className='flex items-center gap-2'>
<Skeleton className='h-5 w-[170px]' />
<Skeleton className='h-3 w-3 rounded-full' />
</div>
<Skeleton className='h-5 w-9 rounded-full' />
</div>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,14 @@ export function ApiKeys() {
<div ref={scrollContainerRef} className='min-h-0 flex-1 overflow-y-auto'>
{isLoading ? (
<div className='flex flex-col gap-4.5'>
{/* Workspace section header */}
<div className='flex flex-col gap-2'>
<Skeleton className='h-5 w-[70px]' />
<div className='text-[var(--text-muted)] text-sm'>
<Skeleton className='h-5 w-[140px]' />
</div>
<Skeleton className='h-5 w-[80px]' />
<Skeleton className='h-5 w-[180px]' />
</div>
{/* Personal section header + keys */}
<div className='flex flex-col gap-2'>
<Skeleton className='h-5 w-[55px]' />
<Skeleton className='h-5 w-[60px]' />
<ApiKeySkeleton />
<ApiKeySkeleton />
</div>
Expand Down Expand Up @@ -310,6 +310,15 @@ export function ApiKeys() {
</div>

{/* Allow Personal API Keys Toggle - Fixed at bottom */}
{isLoading && canManageWorkspaceKeys && (
<div className='mt-6 flex items-center justify-between'>
<div className='flex items-center gap-2'>
<Skeleton className='h-5 w-[170px]' />
<Skeleton className='h-3 w-3 rounded-full' />
</div>
<Skeleton className='h-5 w-9 rounded-full' />
</div>
)}
{!isLoading && canManageWorkspaceKeys && (
<Tooltip.Provider delayDuration={150}>
<div className='mt-6 flex items-center justify-between'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ export function BYOKKeySkeleton() {
<div className='flex items-center gap-3'>
<Skeleton className='h-9 w-9 flex-shrink-0 rounded-md' />
<div className='flex min-w-0 flex-col justify-center gap-[1px]'>
<Skeleton className='h-[14px] w-[100px]' />
<Skeleton className='h-[13px] w-[200px]' />
<Skeleton className='h-[16px] w-[100px]' />
<Skeleton className='h-[14px] w-[200px]' />
</div>
</div>
<Skeleton className='h-[32px] w-[72px] rounded-md' />
<div className='flex flex-shrink-0 items-center gap-2'>
<Skeleton className='h-[32px] w-[72px] rounded-md' />
<Skeleton className='h-[32px] w-[64px] rounded-md' />
</div>
</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,70 @@
import { Skeleton } from '@/components/emcn'

const GRID_COLS = 'grid grid-cols-[minmax(0,1fr)_8px_minmax(0,1fr)_auto] items-center'
const GRID_COLS = 'grid grid-cols-[minmax(0,1fr)_8px_minmax(0,1fr)_auto_auto] items-center'
const COL_SPAN_ALL = 'col-span-5'

/**
* Skeleton component for a single secret row in the grid layout.
* Skeleton for a single integration credential row.
*/
export function CredentialSkeleton() {
return (
<div className={GRID_COLS}>
<div className='flex items-center justify-between gap-3'>
<div className='flex min-w-0 items-center gap-2.5'>
<Skeleton className='h-8 w-8 flex-shrink-0 rounded-md' />
<div className='flex min-w-0 flex-col justify-center gap-[1px]'>
<Skeleton className='h-4 w-[120px] rounded' />
<Skeleton className='h-3.5 w-[160px] rounded' />
</div>
</div>
<div className='flex flex-shrink-0 items-center gap-1'>
<Skeleton className='h-9 w-[60px] rounded-md' />
<Skeleton className='h-9 w-[88px] rounded-md' />
</div>
</div>
)
}

/**
* Skeleton for a single secret row matching the credentials grid layout.
*/
function CredentialRowSkeleton() {
return (
<div className='contents'>
<Skeleton className='h-9 rounded-md' />
<div />
<Skeleton className='h-9 rounded-md' />
<div className='ml-2 flex items-center gap-0'>
<Skeleton className='h-9 w-9 rounded-md' />
<Skeleton className='h-9 w-9 rounded-md' />
</div>
<Skeleton className='ml-2 h-9 w-[60px] rounded-md' />
<Skeleton className='h-9 w-9 rounded-md' />
</div>
)
}

/**
* Skeleton for the Secrets section shown during dynamic import loading.
* Skeleton for the Credentials (Secrets) page shown during dynamic import loading.
*/
export function CredentialsSkeleton() {
return (
<div className='flex h-full flex-col gap-4'>
<div className='flex items-center gap-2'>
<Skeleton className='h-[30px] flex-1 rounded-lg' />
<Skeleton className='h-[30px] w-[56px] rounded-md' />
<Skeleton className='h-[30px] w-[50px] rounded-md' />
</div>
<div className='flex flex-col gap-2'>
<Skeleton className='h-5 w-[70px]' />
<div className='text-[var(--text-muted)] text-small'>
<Skeleton className='h-5 w-[160px]' />

<div className='min-h-0 flex-1 overflow-y-auto'>
<div className='flex flex-col gap-4'>
<div className={`${GRID_COLS} gap-y-2`}>
<Skeleton className={`${COL_SPAN_ALL} h-5 w-[70px]`} />
<CredentialRowSkeleton />
<CredentialRowSkeleton />

<div className={`${COL_SPAN_ALL} h-[8px]`} />

<Skeleton className={`${COL_SPAN_ALL} h-5 w-[55px]`} />
<CredentialRowSkeleton />
<CredentialRowSkeleton />
</div>
</div>
</div>
<div className='flex flex-col gap-2'>
<Skeleton className='h-5 w-[55px]' />
<CredentialSkeleton />
<CredentialSkeleton />
</div>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ export function CustomToolSkeleton() {
return (
<div className='flex items-center justify-between gap-3'>
<div className='flex min-w-0 flex-col justify-center gap-[1px]'>
<Skeleton className='h-[14px] w-[100px]' />
<Skeleton className='h-[13px] w-[200px]' />
<Skeleton className='h-4 w-[100px]' />
<Skeleton className='h-3.5 w-[200px]' />
</div>
<div className='flex flex-shrink-0 items-center gap-2'>
<Skeleton className='h-[30px] w-[40px] rounded-sm' />
<Skeleton className='h-[30px] w-[52px] rounded-sm' />
<Skeleton className='h-[30px] w-[54px] rounded-sm' />
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ export function GeneralSkeleton() {
<Skeleton className='h-9 w-9 rounded-full' />
<div className='flex flex-1 flex-col justify-center gap-[1px]'>
<div className='flex items-center gap-2'>
<Skeleton className='h-5 w-24' />
<Skeleton className='h-4 w-24' />
<Skeleton className='h-[10.5px] w-[10.5px]' />
</div>
<Skeleton className='h-5 w-40' />
<Skeleton className='h-3.5 w-40' />
</div>
</div>

Expand Down
Loading
Loading