diff --git a/packages/console/src/ds-components/Table/TableLoading.module.scss b/packages/console/src/ds-components/Table/Skeleton/index.module.scss
similarity index 86%
rename from packages/console/src/ds-components/Table/TableLoading.module.scss
rename to packages/console/src/ds-components/Table/Skeleton/index.module.scss
index d6ecd7c30..9ce639640 100644
--- a/packages/console/src/ds-components/Table/TableLoading.module.scss
+++ b/packages/console/src/ds-components/Table/Skeleton/index.module.scss
@@ -1,6 +1,12 @@
@use '@/scss/underscore' as _;
-.loading {
+.rect {
+ @include _.shimmering-animation;
+ height: 26px;
+ max-width: 344px;
+}
+
+.row {
.itemPreview {
display: flex;
align-items: center;
@@ -31,8 +37,6 @@
}
.rect {
- @include _.shimmering-animation;
height: 32px;
- max-width: 344px;
}
}
diff --git a/packages/console/src/ds-components/Table/TableLoading.tsx b/packages/console/src/ds-components/Table/Skeleton/index.tsx
similarity index 51%
rename from packages/console/src/ds-components/Table/TableLoading.tsx
rename to packages/console/src/ds-components/Table/Skeleton/index.tsx
index 218839cad..97e11de4a 100644
--- a/packages/console/src/ds-components/Table/TableLoading.tsx
+++ b/packages/console/src/ds-components/Table/Skeleton/index.tsx
@@ -1,15 +1,34 @@
-import * as styles from './TableLoading.module.scss';
+import * as styles from './index.module.scss';
type Props = {
columnSpans: number[];
+ /** For the compact inline style table */
+ isCompact?: boolean;
};
-function TableLoading({ columnSpans }: Props) {
+function Skeleton({ columnSpans, isCompact }: Props) {
+ if (isCompact) {
+ return (
+ <>
+ {Array.from({ length: 2 }).map((_, rowIndex) => (
+ // eslint-disable-next-line react/no-array-index-key
+
@@ -31,4 +50,4 @@ function TableLoading({ columnSpans }: Props) {
);
}
-export default TableLoading;
+export default Skeleton;
diff --git a/packages/console/src/ds-components/Table/index.tsx b/packages/console/src/ds-components/Table/index.tsx
index 95360c036..9a523203e 100644
--- a/packages/console/src/ds-components/Table/index.tsx
+++ b/packages/console/src/ds-components/Table/index.tsx
@@ -9,9 +9,9 @@ import Pagination from '@/ds-components/Pagination';
import OverlayScrollbar from '../OverlayScrollbar';
+import Skeleton from './Skeleton';
import TableEmptyWrapper from './TableEmptyWrapper';
import TableError from './TableError';
-import TableLoading from './TableLoading';
import * as styles from './index.module.scss';
import type { Column, RowGroup } from './types';
@@ -35,6 +35,7 @@ export type Props<
placeholder?: ReactNode;
loadingSkeleton?: ReactNode;
errorMessage?: string;
+ /** The inline style table that is usually embedded in other card containers, has rounded-corner border */
hasBorder?: boolean;
onRetry?: () => void;
/** A footer that will be rendered on the bottom-left of the table. */
@@ -110,7 +111,10 @@ function Table<
{isLoading &&
(loadingSkeleton ?? (
- colSpan ?? 1)} />
+ colSpan ?? 1)}
+ />
))}
{hasError && (
diff --git a/packages/console/src/pages/Organizations/OrganizationsTable/index.tsx b/packages/console/src/pages/Organizations/OrganizationsTable/index.tsx
index 74319ee88..0baaccd48 100644
--- a/packages/console/src/pages/Organizations/OrganizationsTable/index.tsx
+++ b/packages/console/src/pages/Organizations/OrganizationsTable/index.tsx
@@ -27,10 +27,11 @@ const pathname = '/organizations';
const apiPathname = 'api/organizations';
type Props = {
+ isLoading: boolean;
onCreate: () => void;
};
-function OrganizationsTable({ onCreate }: Props) {
+function OrganizationsTable({ isLoading, onCreate }: Props) {
const [keyword, setKeyword] = useState('');
const [page, setPage] = useState(1);
const { data: response, error } = useSWR<[OrganizationWithFeatured[], number], RequestError>(
@@ -42,14 +43,14 @@ function OrganizationsTable({ onCreate }: Props) {
})
);
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
- const isLoading = !response && !error;
+ const isTableLoading = isLoading || (!response && !error);
const [data, totalCount] = response ?? [[], 0];
const { navigate } = useTenantPathname();
return (
}
rowGroups={[{ key: 'data', data }]}
rowClickHandler={({ id }) => {
diff --git a/packages/console/src/pages/Organizations/TemplateTable/index.tsx b/packages/console/src/pages/Organizations/TemplateTable/index.tsx
index a8a863a3d..f4cd63789 100644
--- a/packages/console/src/pages/Organizations/TemplateTable/index.tsx
+++ b/packages/console/src/pages/Organizations/TemplateTable/index.tsx
@@ -1,14 +1,11 @@
import { type AdminConsoleKey } from '@logto/phrases';
-import classNames from 'classnames';
import { type FieldValues, type FieldPath } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import CirclePlus from '@/assets/icons/circle-plus.svg';
import Plus from '@/assets/icons/plus.svg';
-import EmptyDataPlaceholder from '@/components/EmptyDataPlaceholder';
import Button from '@/ds-components/Button';
import DynamicT from '@/ds-components/DynamicT';
-import { Ring as Spinner } from '@/ds-components/Spinner';
import Table from '@/ds-components/Table';
import { type Column } from '@/ds-components/Table/types';
@@ -49,12 +46,8 @@ function TemplateTable<
isLoading,
onPageChange,
}: Props) {
- const hasData = !isLoading && data.length > 0;
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
-
- if (isLoading) {
- ;
- }
+ const noData = !isLoading && data.length === 0;
return (
@@ -63,10 +56,19 @@ function TemplateTable<
)}
- {hasData && (
+ {onAdd && noData && (
+ <>
+ {name && (
+
+ {t('organizations.empty_placeholder', { entity: String(t(name)).toLowerCase() })}
+
+ )}
+ } title="general.add" onClick={onAdd} />
+ >
+ )}
+ {!noData && (
}
isLoading={isLoading}
rowGroups={[
{
@@ -94,16 +96,6 @@ function TemplateTable<
}
/>
)}
- {onAdd && !hasData && (
- <>
- {name && (
-
- {t('organizations.empty_placeholder', { entity: String(t(name)).toLowerCase() })}
-
- )}
- } title="general.add" onClick={onAdd} />
- >
- )}
);
}
diff --git a/packages/console/src/pages/Organizations/index.tsx b/packages/console/src/pages/Organizations/index.tsx
index 87732ec2f..a4dbe4d4e 100644
--- a/packages/console/src/pages/Organizations/index.tsx
+++ b/packages/console/src/pages/Organizations/index.tsx
@@ -31,8 +31,8 @@ function Organizations({ tab }: Props) {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const { navigate } = useTenantPathname();
const [isCreating, setIsCreating] = useState(false);
- const { configs } = useConfigs();
- const isInitialSetup = !configs?.organizationCreated;
+ const { configs, isLoading: isLoadingConfigs } = useConfigs();
+ const isInitialSetup = !isLoadingConfigs && !configs?.organizationCreated;
const handleCreate = useCallback(() => {
if (isInitialSetup) {
@@ -85,7 +85,7 @@ function Organizations({ tab }: Props) {
{t('organizations.organization_template')}
- {!tab && }
+ {!tab && }
{tab === 'template' && }
>
)}
diff --git a/packages/console/src/pages/TenantSettings/TenantBasicSettings/SigningKeys/index.tsx b/packages/console/src/pages/TenantSettings/TenantBasicSettings/SigningKeys/index.tsx
index 5ce753655..14e47b956 100644
--- a/packages/console/src/pages/TenantSettings/TenantBasicSettings/SigningKeys/index.tsx
+++ b/packages/console/src/pages/TenantSettings/TenantBasicSettings/SigningKeys/index.tsx
@@ -124,21 +124,6 @@ function SigningKeys() {
rowIndexKey="id"
rowGroups={[{ key: 'signing_keys', data }]}
columns={tableColumns}
- loadingSkeleton={
- <>
- {Array.from({ length: 2 }).map((_, rowIndex) => (
- // eslint-disable-next-line react/no-array-index-key
-
- {tableColumns.map(({ colSpan }, columnIndex) => (
- // eslint-disable-next-line react/no-array-index-key
-
-
- |
- ))}
-
- ))}
- >
- }
/>
diff --git a/packages/console/src/pages/UserDetails/UserSettings/UserMfaVerifications/index.tsx b/packages/console/src/pages/UserDetails/UserSettings/UserMfaVerifications/index.tsx
index b3ca58532..561b27e90 100644
--- a/packages/console/src/pages/UserDetails/UserSettings/UserMfaVerifications/index.tsx
+++ b/packages/console/src/pages/UserDetails/UserSettings/UserMfaVerifications/index.tsx
@@ -61,7 +61,7 @@ function UserMfaVerifications({ userId }: Props) {
{t(mfaVerifications?.length ? 'field_description' : 'field_description_empty')}
)}
- {(Boolean(mfaVerifications?.length) || error) && (
+ {(isLoading || Boolean(mfaVerifications?.length) || error) && (
0);
+
return (
-
- {t(
- displayConnectors && displayConnectors.length > 0
- ? 'user_details.connectors.connected'
- : 'user_details.connectors.not_connected'
- )}
-
- {displayConnectors && displayConnectors.length > 0 && (
+ {!isLoading && !error && (
+
+ {t(
+ hasConnectors
+ ? 'user_details.connectors.connected'
+ : 'user_details.connectors.not_connected'
+ )}
+
+ )}
+ {(isLoading || hasConnectors || error) && (
0;
+ const hasLinkedSsoIdentities = Boolean(displaySsoConnectors && displaySsoConnectors.length > 0);
return (
-
- {t(
- hasLinkedSsoIdentities
- ? 'user_details.sso_connectors.connected'
- : 'user_details.sso_connectors.not_connected'
- )}
-
- {hasLinkedSsoIdentities && (
+ {!isLoading && !error && (
+
+ {t(
+ hasLinkedSsoIdentities
+ ? 'user_details.sso_connectors.connected'
+ : 'user_details.sso_connectors.not_connected'
+ )}
+
+ )}
+ {(isLoading || hasLinkedSsoIdentities || error) && (
|