feat: loading states update (#3639)
* dev: implement layout skeleton loader and helper function * chore: implemented layout loader * chore: settings loader added * chore: cycle, module, view, pages, notification and projects loader added * chore: kanban loader improvement * chore: loader utils updated
This commit is contained in:
parent
83139989c2
commit
b1989bae1b
51 changed files with 951 additions and 507 deletions
|
|
@ -13,7 +13,8 @@ import { WorkspaceSettingHeader } from "components/headers";
|
|||
import { ApiTokenListItem, CreateApiTokenModal } from "components/api-token";
|
||||
import { EmptyState, getEmptyStateImagePath } from "components/empty-state";
|
||||
// ui
|
||||
import { Button, Spinner } from "@plane/ui";
|
||||
import { Button } from "@plane/ui";
|
||||
import { APITokenSettingsLoader } from "components/ui";
|
||||
// services
|
||||
import { APITokenService } from "services/api_token.service";
|
||||
// types
|
||||
|
|
@ -56,49 +57,47 @@ const ApiTokensPage: NextPageWithLayout = observer(() => {
|
|||
</div>
|
||||
);
|
||||
|
||||
if (!tokens) {
|
||||
return <APITokenSettingsLoader />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<CreateApiTokenModal isOpen={isCreateTokenModalOpen} onClose={() => setIsCreateTokenModalOpen(false)} />
|
||||
{tokens ? (
|
||||
<section className="h-full w-full overflow-y-auto py-8 pr-9">
|
||||
{tokens.length > 0 ? (
|
||||
<>
|
||||
<div className="flex items-center justify-between border-b border-custom-border-200 py-3.5">
|
||||
<h3 className="text-xl font-medium">API tokens</h3>
|
||||
<Button variant="primary" onClick={() => setIsCreateTokenModalOpen(true)}>
|
||||
Add API token
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
{tokens.map((token) => (
|
||||
<ApiTokenListItem key={token.id} token={token} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<div className="flex items-center justify-between gap-4 border-b border-custom-border-200 pb-3.5">
|
||||
<h3 className="text-xl font-medium">API tokens</h3>
|
||||
<Button variant="primary" onClick={() => setIsCreateTokenModalOpen(true)}>
|
||||
Add API token
|
||||
</Button>
|
||||
</div>
|
||||
<div className="h-full w-full flex items-center justify-center">
|
||||
<EmptyState
|
||||
title={emptyStateDetail.title}
|
||||
description={emptyStateDetail.description}
|
||||
image={emptyStateImage}
|
||||
size="lg"
|
||||
/>
|
||||
</div>
|
||||
<section className="h-full w-full overflow-y-auto py-8 pr-9">
|
||||
{tokens.length > 0 ? (
|
||||
<>
|
||||
<div className="flex items-center justify-between border-b border-custom-border-200 py-3.5">
|
||||
<h3 className="text-xl font-medium">API tokens</h3>
|
||||
<Button variant="primary" onClick={() => setIsCreateTokenModalOpen(true)}>
|
||||
Add API token
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
) : (
|
||||
<div className="grid h-full w-full place-items-center p-4">
|
||||
<Spinner />
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
{tokens.map((token) => (
|
||||
<ApiTokenListItem key={token.id} token={token} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<div className="flex items-center justify-between gap-4 border-b border-custom-border-200 pb-3.5">
|
||||
<h3 className="text-xl font-medium">API tokens</h3>
|
||||
<Button variant="primary" onClick={() => setIsCreateTokenModalOpen(true)}>
|
||||
Add API token
|
||||
</Button>
|
||||
</div>
|
||||
<div className="h-full w-full flex items-center justify-center">
|
||||
<EmptyState
|
||||
title={emptyStateDetail.title}
|
||||
description={emptyStateDetail.description}
|
||||
image={emptyStateImage}
|
||||
size="lg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ import { WorkspaceSettingLayout } from "layouts/settings-layout";
|
|||
import { SingleIntegrationCard } from "components/integration";
|
||||
import { WorkspaceSettingHeader } from "components/headers";
|
||||
// ui
|
||||
import { IntegrationAndImportExportBanner } from "components/ui";
|
||||
import { Loader } from "@plane/ui";
|
||||
import { IntegrationAndImportExportBanner, IntegrationsSettingsLoader } from "components/ui";
|
||||
// types
|
||||
import { NextPageWithLayout } from "lib/types";
|
||||
// fetch-keys
|
||||
|
|
@ -53,10 +52,7 @@ const WorkspaceIntegrationsPage: NextPageWithLayout = observer(() => {
|
|||
{appIntegrations ? (
|
||||
appIntegrations.map((integration) => <SingleIntegrationCard key={integration.id} integration={integration} />)
|
||||
) : (
|
||||
<Loader className="mt-4 space-y-2.5">
|
||||
<Loader.Item height="89px" />
|
||||
<Loader.Item height="89px" />
|
||||
</Loader>
|
||||
<IntegrationsSettingsLoader />
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ import { WorkspaceSettingHeader } from "components/headers";
|
|||
import { WebhooksList, CreateWebhookModal } from "components/web-hooks";
|
||||
import { EmptyState, getEmptyStateImagePath } from "components/empty-state";
|
||||
// ui
|
||||
import { Button, Spinner } from "@plane/ui";
|
||||
import { Button } from "@plane/ui";
|
||||
import { WebhookSettingsLoader } from "components/ui";
|
||||
// types
|
||||
import { NextPageWithLayout } from "lib/types";
|
||||
// constants
|
||||
|
|
@ -59,12 +60,7 @@ const WebhooksListPage: NextPageWithLayout = observer(() => {
|
|||
</div>
|
||||
);
|
||||
|
||||
if (!webhooks)
|
||||
return (
|
||||
<div className="grid h-full w-full place-items-center p-4">
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
if (!webhooks) return <WebhookSettingsLoader />;
|
||||
|
||||
return (
|
||||
<div className="h-full w-full overflow-hidden py-8 pr-9">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue