0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-30 20:33:54 -05:00

feat(console): support searching for organization roles (#5646)

This commit is contained in:
Xiao Yijun 2024-04-08 14:05:34 +08:00 committed by GitHub
parent bf471e1451
commit 756c2f472c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 46 additions and 24 deletions

View file

@ -8,6 +8,6 @@
.filter { .filter {
display: flex; display: flex;
flex-direction: row-reverse;
align-items: center; align-items: center;
justify-content: space-between;
} }

View file

@ -1,5 +1,7 @@
import { type OrganizationRoleWithScopes } from '@logto/schemas'; import { type OrganizationRoleWithScopes } from '@logto/schemas';
import { cond } from '@silverhand/essentials';
import { useState } from 'react'; import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import useSWR from 'swr'; import useSWR from 'swr';
import Plus from '@/assets/icons/plus.svg'; import Plus from '@/assets/icons/plus.svg';
@ -7,11 +9,13 @@ import OrgRoleIcon from '@/assets/icons/role-feature.svg';
import RolesEmptyDark from '@/assets/images/roles-empty-dark.svg'; import RolesEmptyDark from '@/assets/images/roles-empty-dark.svg';
import RolesEmpty from '@/assets/images/roles-empty.svg'; import RolesEmpty from '@/assets/images/roles-empty.svg';
import Breakable from '@/components/Breakable'; import Breakable from '@/components/Breakable';
import EmptyDataPlaceholder from '@/components/EmptyDataPlaceholder';
import ItemPreview from '@/components/ItemPreview'; import ItemPreview from '@/components/ItemPreview';
import ThemedIcon from '@/components/ThemedIcon'; import ThemedIcon from '@/components/ThemedIcon';
import { defaultPageSize, organizationRoleLink } from '@/consts'; import { defaultPageSize, organizationRoleLink } from '@/consts';
import Button from '@/ds-components/Button'; import Button from '@/ds-components/Button';
import DynamicT from '@/ds-components/DynamicT'; import DynamicT from '@/ds-components/DynamicT';
import Search from '@/ds-components/Search';
import Table from '@/ds-components/Table'; import Table from '@/ds-components/Table';
import TablePlaceholder from '@/ds-components/Table/TablePlaceholder'; import TablePlaceholder from '@/ds-components/Table/TablePlaceholder';
import Tag from '@/ds-components/Tag'; import Tag from '@/ds-components/Tag';
@ -19,16 +23,18 @@ import { type RequestError } from '@/hooks/use-api';
import useDocumentationUrl from '@/hooks/use-documentation-url'; import useDocumentationUrl from '@/hooks/use-documentation-url';
import useSearchParametersWatcher from '@/hooks/use-search-parameters-watcher'; import useSearchParametersWatcher from '@/hooks/use-search-parameters-watcher';
import useTenantPathname from '@/hooks/use-tenant-pathname'; import useTenantPathname from '@/hooks/use-tenant-pathname';
import { buildUrl } from '@/utils/url'; import { buildUrl, formatSearchKeyword } from '@/utils/url';
import CreateOrganizationRoleModal from './CreateOrganizationRoleModal'; import CreateOrganizationRoleModal from './CreateOrganizationRoleModal';
import * as styles from './index.module.scss'; import * as styles from './index.module.scss';
function OrganizationRoles() { function OrganizationRoles() {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const { getDocumentationUrl } = useDocumentationUrl(); const { getDocumentationUrl } = useDocumentationUrl();
const { navigate } = useTenantPathname(); const { navigate } = useTenantPathname();
const [{ page }, updateSearchParameters] = useSearchParametersWatcher({ const [{ page, keyword }, updateSearchParameters] = useSearchParametersWatcher({
page: 1, page: 1,
keyword: '',
}); });
const { data, error, mutate, isLoading } = useSWR< const { data, error, mutate, isLoading } = useSWR<
@ -38,6 +44,7 @@ function OrganizationRoles() {
buildUrl('api/organization-roles', { buildUrl('api/organization-roles', {
page: String(page), page: String(page),
page_size: String(defaultPageSize), page_size: String(defaultPageSize),
...cond(keyword && { q: formatSearchKeyword(keyword) }),
}) })
); );
@ -83,6 +90,17 @@ function OrganizationRoles() {
}} }}
filter={ filter={
<div className={styles.filter}> <div className={styles.filter}>
<Search
placeholder={t('organization_template.roles.search_placeholder')}
defaultValue={keyword}
isClearable={Boolean(keyword)}
onSearch={(keyword) => {
updateSearchParameters({ keyword });
}}
onClearSearch={() => {
updateSearchParameters({ keyword: '' });
}}
/>
<Button <Button
title="organization_template.roles.create_title" title="organization_template.roles.create_title"
type="primary" type="primary"
@ -94,27 +112,31 @@ function OrganizationRoles() {
</div> </div>
} }
placeholder={ placeholder={
<TablePlaceholder keyword ? (
image={<RolesEmpty />} <EmptyDataPlaceholder />
imageDark={<RolesEmptyDark />} ) : (
title="organization_template.roles.placeholder_title" <TablePlaceholder
description="organization_template.roles.placeholder_description" image={<RolesEmpty />}
learnMoreLink={{ imageDark={<RolesEmptyDark />}
href: getDocumentationUrl(organizationRoleLink), title="organization_template.roles.placeholder_title"
targetBlank: 'noopener', description="organization_template.roles.placeholder_description"
}} learnMoreLink={{
action={ href: getDocumentationUrl(organizationRoleLink),
<Button targetBlank: 'noopener',
title="organization_template.roles.create_title" }}
type="primary" action={
size="large" <Button
icon={<Plus />} title="organization_template.roles.create_title"
onClick={() => { type="primary"
setIsCreateModalOpen(true); size="large"
}} icon={<Plus />}
/> onClick={() => {
} setIsCreateModalOpen(true);
/> }}
/>
}
/>
)
} }
pagination={{ pagination={{
page, page,