diff --git a/packages/console/src/assets/images/permissions-empty-dark.svg b/packages/console/src/assets/images/permissions-empty-dark.svg new file mode 100644 index 000000000..f22616e0c --- /dev/null +++ b/packages/console/src/assets/images/permissions-empty-dark.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/console/src/assets/images/permissions-empty.svg b/packages/console/src/assets/images/permissions-empty.svg new file mode 100644 index 000000000..f25d15829 --- /dev/null +++ b/packages/console/src/assets/images/permissions-empty.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/console/src/assets/images/roles-empty-dark.svg b/packages/console/src/assets/images/roles-empty-dark.svg new file mode 100644 index 000000000..fdd5875dc --- /dev/null +++ b/packages/console/src/assets/images/roles-empty-dark.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/console/src/assets/images/roles-empty.svg b/packages/console/src/assets/images/roles-empty.svg new file mode 100644 index 000000000..970a68056 --- /dev/null +++ b/packages/console/src/assets/images/roles-empty.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/console/src/assets/images/users-empty-dark.svg b/packages/console/src/assets/images/users-empty-dark.svg new file mode 100644 index 000000000..acdf8b4c1 --- /dev/null +++ b/packages/console/src/assets/images/users-empty-dark.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/console/src/assets/images/users-empty.svg b/packages/console/src/assets/images/users-empty.svg new file mode 100644 index 000000000..c7fc01528 --- /dev/null +++ b/packages/console/src/assets/images/users-empty.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/console/src/components/AuditLogTable/index.tsx b/packages/console/src/components/AuditLogTable/index.tsx index 2fa2902c1..aa2a849b2 100644 --- a/packages/console/src/components/AuditLogTable/index.tsx +++ b/packages/console/src/components/AuditLogTable/index.tsx @@ -12,6 +12,7 @@ import type { RequestError } from '@/hooks/use-api'; import useSearchParametersWatcher from '@/hooks/use-search-parameters-watcher'; import { buildUrl } from '@/utils/url'; +import EmptyDataPlaceholder from '../EmptyDataPlaceholder'; import Table from '../Table'; import type { Column } from '../Table/types'; import ApplicationSelector from './components/ApplicationSelector'; @@ -117,6 +118,7 @@ const AuditLogTable = ({ userId, className }: Props) => { } + placeholder={} pagination={{ page, totalCount, diff --git a/packages/console/src/components/DataEmpty/index.tsx b/packages/console/src/components/DataEmpty/index.tsx deleted file mode 100644 index 949cbf84e..000000000 --- a/packages/console/src/components/DataEmpty/index.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { AppearanceMode } from '@logto/schemas'; -import type { ReactNode } from 'react'; -import { useTranslation } from 'react-i18next'; - -import EmptyDark from '@/assets/images/table-empty-dark.svg'; -import Empty from '@/assets/images/table-empty.svg'; -import { useTheme } from '@/hooks/use-theme'; - -import * as styles from './index.module.scss'; - -export type Props = { - title?: string; - description?: string; - image?: ReactNode; - children?: ReactNode; - imageClassName?: string; -}; - -const DataEmpty = ({ title, description, image, imageClassName, children }: Props) => { - const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); - - const theme = useTheme(); - - return ( -
- {image ?? - (theme === AppearanceMode.LightMode ? ( - - ) : ( - - ))} -
{title ?? t('errors.empty')}
- {description &&
{description}
} - {children} -
- ); -}; - -export default DataEmpty; diff --git a/packages/console/src/components/DataEmpty/index.module.scss b/packages/console/src/components/EmptyDataPlaceholder/index.module.scss similarity index 52% rename from packages/console/src/components/DataEmpty/index.module.scss rename to packages/console/src/components/EmptyDataPlaceholder/index.module.scss index 194814704..eecfa7350 100644 --- a/packages/console/src/components/DataEmpty/index.module.scss +++ b/packages/console/src/components/EmptyDataPlaceholder/index.module.scss @@ -16,4 +16,27 @@ color: var(--color-neutral-50); margin-bottom: _.unit(2); } + + &.large { + .image { + width: 256px; + height: 256px; + margin-bottom: _.unit(6); + } + } + + &.medium { + .image { + width: 200px; + height: 200px; + margin-bottom: _.unit(6); + } + } + + &.small { + .image { + width: 128px; + height: 128px; + } + } } diff --git a/packages/console/src/components/EmptyDataPlaceholder/index.tsx b/packages/console/src/components/EmptyDataPlaceholder/index.tsx new file mode 100644 index 000000000..3591451df --- /dev/null +++ b/packages/console/src/components/EmptyDataPlaceholder/index.tsx @@ -0,0 +1,29 @@ +import { AppearanceMode } from '@logto/schemas'; +import classNames from 'classnames'; +import { useTranslation } from 'react-i18next'; + +import EmptyDark from '@/assets/images/table-empty-dark.svg'; +import Empty from '@/assets/images/table-empty.svg'; +import { useTheme } from '@/hooks/use-theme'; + +import * as styles from './index.module.scss'; + +export type Props = { + title?: string; + size?: 'large' | 'medium' | 'small'; +}; + +const EmptyDataPlaceholder = ({ title, size = 'medium' }: Props) => { + const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); + const theme = useTheme(); + const EmptyImage = theme === AppearanceMode.LightMode ? Empty : EmptyDark; + + return ( +
+ +
{title ?? t('errors.empty')}
+
+ ); +}; + +export default EmptyDataPlaceholder; diff --git a/packages/console/src/components/PermissionsTable/index.tsx b/packages/console/src/components/PermissionsTable/index.tsx index 810005fcc..2c037f380 100644 --- a/packages/console/src/components/PermissionsTable/index.tsx +++ b/packages/console/src/components/PermissionsTable/index.tsx @@ -4,6 +4,8 @@ import { conditional } from '@silverhand/essentials'; import { useTranslation } from 'react-i18next'; import Delete from '@/assets/images/delete.svg'; +import PermissionsEmptyDark from '@/assets/images/permissions-empty-dark.svg'; +import PermissionsEmpty from '@/assets/images/permissions-empty.svg'; import Plus from '@/assets/images/plus.svg'; import Button from '@/components/Button'; import IconButton from '@/components/IconButton'; @@ -13,8 +15,11 @@ import type { Column } from '@/components/Table/types'; import TextLink from '@/components/TextLink'; import { Tooltip } from '@/components/Tip'; import { ApiResourceDetailsTabs } from '@/consts/page-tabs'; +import useDocumentationUrl from '@/hooks/use-documentation-url'; +import EmptyDataPlaceholder from '../EmptyDataPlaceholder'; import type { Props as PaginationProps } from '../Pagination'; +import TablePlaceholder from '../Table/TablePlaceholder'; import * as styles from './index.module.scss'; type SearchProps = { @@ -31,6 +36,7 @@ type Props = { deleteButtonTitle?: AdminConsoleKey; isReadOnly?: boolean; isApiColumnVisible?: boolean; + isCreateGuideVisible?: boolean; pagination?: PaginationProps; search: SearchProps; createHandler: () => void; @@ -46,6 +52,7 @@ const PermissionsTable = ({ deleteButtonTitle = 'general.delete', isReadOnly = false, isApiColumnVisible = false, + isCreateGuideVisible = false, pagination, search: { keyword, searchHandler, clearSearchHandler }, createHandler, @@ -53,6 +60,7 @@ const PermissionsTable = ({ retryHandler, }: Props) => { const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); + const { getDocumentationUrl } = useDocumentationUrl(); const nameColumn: Column = { title: t('permissions.name_column'), @@ -146,17 +154,30 @@ const PermissionsTable = ({ } isLoading={isLoading} pagination={pagination} - placeholder={{ - content: isReadOnly ? undefined : ( -