mirror of
https://github.com/logto-io/logto.git
synced 2025-04-14 23:11:31 -05:00
feat(console): add permissions page for org role details page (#5631)
This commit is contained in:
parent
6ed7ab5ef9
commit
11c974cfdd
19 changed files with 219 additions and 5 deletions
|
@ -26,7 +26,7 @@ type FormData = Pick<OrganizationScope, 'name' | 'description'>;
|
|||
const organizationScopesPath = 'api/organization-scopes';
|
||||
|
||||
/** A modal that allows users to create or edit an organization permission. */
|
||||
function OrganizationPermissionModal({ data, onClose }: Props) {
|
||||
function ManageOrganizationPermissionModal({ data, onClose }: Props) {
|
||||
const isCreateMode = data === null;
|
||||
|
||||
const { t } = useTranslation(undefined, {
|
||||
|
@ -111,4 +111,4 @@ function OrganizationPermissionModal({ data, onClose }: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default OrganizationPermissionModal;
|
||||
export default ManageOrganizationPermissionModal;
|
|
@ -0,0 +1,11 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.filter {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.assignButton {
|
||||
margin-left: _.unit(2);
|
||||
}
|
||||
}
|
|
@ -1,9 +1,155 @@
|
|||
import { type OrganizationScope } from '@logto/schemas';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import useSWR from 'swr';
|
||||
|
||||
import Plus from '@/assets/icons/plus.svg';
|
||||
import ActionsButton from '@/components/ActionsButton';
|
||||
import Breakable from '@/components/Breakable';
|
||||
import EmptyDataPlaceholder from '@/components/EmptyDataPlaceholder';
|
||||
import ManageOrganizationPermissionModal from '@/components/ManageOrganizationPermissionModal';
|
||||
import Button from '@/ds-components/Button';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
import Search from '@/ds-components/Search';
|
||||
import Table from '@/ds-components/Table';
|
||||
import Tag from '@/ds-components/Tag';
|
||||
import useApi, { type RequestError } from '@/hooks/use-api';
|
||||
import useSearchParametersWatcher from '@/hooks/use-search-parameters-watcher';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
const organizationRolesPath = 'api/organization-roles';
|
||||
|
||||
type Props = {
|
||||
organizationRoleId: string;
|
||||
};
|
||||
|
||||
function Permissions({ organizationRoleId }: Props) {
|
||||
return <div>TBD</div>;
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const api = useApi();
|
||||
|
||||
const { data, error, isLoading, mutate } = useSWR<OrganizationScope[], RequestError>(
|
||||
`${organizationRolesPath}/${organizationRoleId}/scopes`
|
||||
);
|
||||
|
||||
const [{ keyword }, updateSearchParameters] = useSearchParametersWatcher({
|
||||
keyword: '',
|
||||
});
|
||||
|
||||
const filteredData = useMemo(() => {
|
||||
if (keyword) {
|
||||
return data?.filter((roleScope) => roleScope.name.includes(keyword));
|
||||
}
|
||||
return data;
|
||||
}, [data, keyword]);
|
||||
|
||||
const [editPermission, setEditPermission] = useState<OrganizationScope>();
|
||||
|
||||
const scopeRemoveHandler = useCallback(
|
||||
(scopeToRemove: OrganizationScope) => async () => {
|
||||
await api.put(`${organizationRolesPath}/${organizationRoleId}/scopes`, {
|
||||
json: {
|
||||
organizationScopeIds:
|
||||
data?.filter((scope) => scope.id !== scopeToRemove.id).map(({ id }) => id) ?? [],
|
||||
},
|
||||
});
|
||||
toast.success(
|
||||
t('organization_role_details.permissions.removed', { name: scopeToRemove.name })
|
||||
);
|
||||
void mutate();
|
||||
},
|
||||
[api, data, mutate, organizationRoleId, t]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Table
|
||||
rowGroups={[{ key: 'organizationRolePermissions', data: filteredData }]}
|
||||
rowIndexKey="id"
|
||||
columns={[
|
||||
{
|
||||
title: <DynamicT forKey="organization_role_details.permissions.name_column" />,
|
||||
dataIndex: 'name',
|
||||
colSpan: 7,
|
||||
render: ({ name }) => {
|
||||
return (
|
||||
<Tag variant="cell">
|
||||
<Breakable>{name}</Breakable>
|
||||
</Tag>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: <DynamicT forKey="organization_role_details.permissions.description_column" />,
|
||||
dataIndex: 'description',
|
||||
colSpan: 8,
|
||||
render: ({ description }) => <Breakable>{description ?? '-'}</Breakable>,
|
||||
},
|
||||
{
|
||||
title: null,
|
||||
dataIndex: 'action',
|
||||
colSpan: 1,
|
||||
render: (scope) => (
|
||||
<ActionsButton
|
||||
fieldName="organization_role_details.permissions.name_column"
|
||||
deleteConfirmation="organization_role_details.permissions.remove_confirmation"
|
||||
textOverrides={{
|
||||
delete: 'organization_role_details.permissions.remove_permission',
|
||||
deleteConfirmation: 'general.remove',
|
||||
}}
|
||||
onEdit={() => {
|
||||
setEditPermission(scope);
|
||||
}}
|
||||
onDelete={async () => {
|
||||
await scopeRemoveHandler(scope)();
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
filter={
|
||||
<div className={styles.filter}>
|
||||
<Search
|
||||
isClearable={Boolean(keyword)}
|
||||
placeholder={t('organization_template.permissions.search_placeholder')}
|
||||
defaultValue={keyword}
|
||||
onSearch={(keyword) => {
|
||||
if (keyword) {
|
||||
updateSearchParameters({ keyword });
|
||||
}
|
||||
}}
|
||||
onClearSearch={() => {
|
||||
updateSearchParameters({ keyword: '' });
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
title="organization_role_details.permissions.assign_permissions"
|
||||
className={styles.assignButton}
|
||||
type="primary"
|
||||
icon={<Plus />}
|
||||
onClick={() => {
|
||||
// Todo @xiaoyijun Assign permissions to org role
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
placeholder={<EmptyDataPlaceholder />}
|
||||
isLoading={isLoading}
|
||||
errorMessage={error?.body?.message ?? error?.message}
|
||||
onRetry={async () => mutate(undefined, true)}
|
||||
/>
|
||||
{editPermission && (
|
||||
<ManageOrganizationPermissionModal
|
||||
data={editPermission}
|
||||
onClose={() => {
|
||||
setEditPermission(undefined);
|
||||
void mutate();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default Permissions;
|
||||
|
|
|
@ -10,6 +10,7 @@ import PermissionsEmpty from '@/assets/images/permissions-empty.svg';
|
|||
import ActionsButton from '@/components/ActionsButton';
|
||||
import Breakable from '@/components/Breakable';
|
||||
import EmptyDataPlaceholder from '@/components/EmptyDataPlaceholder';
|
||||
import ManageOrganizationPermissionModal from '@/components/ManageOrganizationPermissionModal';
|
||||
import { organizationPermissionLink } from '@/consts';
|
||||
import Button from '@/ds-components/Button';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
|
@ -22,7 +23,6 @@ import useDocumentationUrl from '@/hooks/use-documentation-url';
|
|||
import useSearchParametersWatcher from '@/hooks/use-search-parameters-watcher';
|
||||
import { buildUrl, formatSearchKeyword } from '@/utils/url';
|
||||
|
||||
import OrganizationPermissionModal from './OrganizationPermissionModal';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
function OrganizationPermissions() {
|
||||
|
@ -141,7 +141,7 @@ function OrganizationPermissions() {
|
|||
onRetry={async () => mutate(undefined, true)}
|
||||
/>
|
||||
{permissionModalData !== undefined && (
|
||||
<OrganizationPermissionModal
|
||||
<ManageOrganizationPermissionModal
|
||||
data={permissionModalData}
|
||||
onClose={() => {
|
||||
setPermissionModalData(undefined);
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: 'Org-Berechtigung',
|
||||
},
|
||||
assign_permissions: 'Berechtigungen zuweisen',
|
||||
remove_permission: 'Berechtigung entfernen',
|
||||
remove_confirmation:
|
||||
'Wenn diese Berechtigung entfernt wird, verliert der Benutzer mit dieser Organisationsrolle den Zugriff, der durch diese Berechtigung gewährt wurde.',
|
||||
removed: 'Die Berechtigung {{name}} wurde erfolgreich aus dieser Organisationsrolle entfernt',
|
||||
},
|
||||
general: {
|
||||
tab: 'Allgemein',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: 'Org permission',
|
||||
},
|
||||
assign_permissions: 'Assign permissions',
|
||||
remove_permission: 'Remove permission',
|
||||
remove_confirmation:
|
||||
'If this permission is removed, the user with this organization role will lose the access granted by this permission.',
|
||||
removed: 'The permission {{name}} was successfully removed from this organization role',
|
||||
},
|
||||
general: {
|
||||
tab: 'General',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: 'Permiso de organización',
|
||||
},
|
||||
assign_permissions: 'Asignar permisos',
|
||||
remove_permission: 'Eliminar permiso',
|
||||
remove_confirmation:
|
||||
'Si este permiso se elimina, el usuario con este rol de organización perderá el acceso otorgado por este permiso.',
|
||||
removed: 'El permiso {{name}} se eliminó correctamente de este rol de organización',
|
||||
},
|
||||
general: {
|
||||
tab: 'General',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: "Autorisation d'organisation",
|
||||
},
|
||||
assign_permissions: 'Attribuer des autorisations',
|
||||
remove_permission: 'Supprimer la permission',
|
||||
remove_confirmation:
|
||||
"Si cette permission est supprimée, l'utilisateur avec ce rôle d'organisation perdra l'accès accordé par cette permission.",
|
||||
removed: "La permission {{name}} a été supprimée avec succès de ce rôle d'organisation",
|
||||
},
|
||||
general: {
|
||||
tab: 'Général',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: 'Autorizzazione organizzazione',
|
||||
},
|
||||
assign_permissions: 'Assegna autorizzazioni',
|
||||
remove_permission: 'Rimuovi permesso',
|
||||
remove_confirmation:
|
||||
"Se questo permesso viene rimosso, l'utente con questo ruolo organizzativo perderà l'accesso concessogli da questo permesso.",
|
||||
removed: 'Il permesso {{name}} è stato rimosso con successo da questo ruolo organizzativo',
|
||||
},
|
||||
general: {
|
||||
tab: 'Generale',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: '組織許可',
|
||||
},
|
||||
assign_permissions: '許可を割り当てる',
|
||||
remove_permission: '権限を削除',
|
||||
remove_confirmation:
|
||||
'この権限を削除すると、この組織の役割を持つユーザーはこの権限によって付与されたアクセスを失います。',
|
||||
removed: 'この組織の役割から権限 {{name}} が正常に削除されました',
|
||||
},
|
||||
general: {
|
||||
tab: '一般',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: '조직 권한',
|
||||
},
|
||||
assign_permissions: '권한 할당',
|
||||
remove_permission: '권한 삭제',
|
||||
remove_confirmation:
|
||||
'이 권한을 제거하면이 조직 역할을하는 사용자는이 권한으로 부여된 액세스를 잃게됩니다.',
|
||||
removed: '권한 {{name}}이(가)이 조직 역할에서 성공적으로 제거되었습니다',
|
||||
},
|
||||
general: {
|
||||
tab: '일반',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: 'Uprawnienie organizacji',
|
||||
},
|
||||
assign_permissions: 'Przypisz uprawnienia',
|
||||
remove_permission: 'Usuń uprawnienie',
|
||||
remove_confirmation:
|
||||
'Jeśli to uprawnienie zostanie usunięte, użytkownik z tą rolą organizacyjną utraci dostęp udzielony przez to uprawnienie.',
|
||||
removed: 'Uprawnienie {{name}} zostało pomyślnie usunięte z tej roli organizacyjnej',
|
||||
},
|
||||
general: {
|
||||
tab: 'Ogólne',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: 'Permissão da org',
|
||||
},
|
||||
assign_permissions: 'Atribuir permissões',
|
||||
remove_permission: 'Remover permissão',
|
||||
remove_confirmation:
|
||||
'Se esta permissão for removida, o usuário com essa função organizacional perderá o acesso concedido por esta permissão.',
|
||||
removed: 'A permissão {{name}} foi removida com sucesso desta função organizacional',
|
||||
},
|
||||
general: {
|
||||
tab: 'Geral',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: 'Permissão da org',
|
||||
},
|
||||
assign_permissions: 'Atribuir permissões',
|
||||
remove_permission: 'Remover permissão',
|
||||
remove_confirmation:
|
||||
'Se esta permissão for removida, o utilizador com esta função organizacional perderá o acesso concedido por esta permissão.',
|
||||
removed: 'A permissão {{name}} foi removida com sucesso desta função organizacional',
|
||||
},
|
||||
general: {
|
||||
tab: 'Geral',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: 'Разрешение организации',
|
||||
},
|
||||
assign_permissions: 'Назначить разрешения',
|
||||
remove_permission: 'Удалить разрешение',
|
||||
remove_confirmation:
|
||||
'Если это разрешение будет удалено, пользователь с этой организационной ролью потеряет доступ, предоставленный этим разрешением.',
|
||||
removed: 'Разрешение {{name}} успешно удалено из этой организационной роли',
|
||||
},
|
||||
general: {
|
||||
tab: 'Общее',
|
||||
|
|
|
@ -15,6 +15,10 @@ const organization_role_details = {
|
|||
org: 'Kuruluş izni',
|
||||
},
|
||||
assign_permissions: 'İzinleri atama',
|
||||
remove_permission: 'İzni kaldır',
|
||||
remove_confirmation:
|
||||
'Bu izin kaldırılırsa, bu organizasyon rolüne sahip kullanıcı bu izin tarafından verilen erişimi kaybeder.',
|
||||
removed: '{{name}} izni bu organizasyon rolünden başarıyla kaldırıldı',
|
||||
},
|
||||
general: {
|
||||
tab: 'Genel',
|
||||
|
|
|
@ -15,6 +15,9 @@ const organization_role_details = {
|
|||
org: '组织权限',
|
||||
},
|
||||
assign_permissions: '分配权限',
|
||||
remove_permission: '移除权限',
|
||||
remove_confirmation: '如果移除此权限,拥有此组织角色的用户将失去此权限授予的访问权限。',
|
||||
removed: '权限 {{name}} 已成功从此组织角色中移除',
|
||||
},
|
||||
general: {
|
||||
tab: '常规',
|
||||
|
|
|
@ -15,6 +15,9 @@ const organization_role_details = {
|
|||
org: '組織權限',
|
||||
},
|
||||
assign_permissions: '分配權限',
|
||||
remove_permission: '移除權限',
|
||||
remove_confirmation: '如果移除此權限,擁有此組織角色的使用者將失去此權限所授予的存取權。',
|
||||
removed: '權限 {{name}} 已成功從此組織角色中移除',
|
||||
},
|
||||
general: {
|
||||
tab: '一般',
|
||||
|
|
|
@ -15,6 +15,9 @@ const organization_role_details = {
|
|||
org: '組織權限',
|
||||
},
|
||||
assign_permissions: '分配權限',
|
||||
remove_permission: '移除權限',
|
||||
remove_confirmation: '如果移除此權限,擁有此組織角色的使用者將失去此權限所授予的存取權。',
|
||||
removed: '權限 {{name}} 已成功從此組織角色中移除',
|
||||
},
|
||||
general: {
|
||||
tab: '一般',
|
||||
|
|
Loading…
Add table
Reference in a new issue