mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: use new role components in project access (#4018)
https://linear.app/unleash/issue/2-1143/adapt-project-roles-to-use-the-new-role-selector-and-role-description This PR further unifies roles, by having a single `IRole` interface to cover both types, and re-using the same components for project roles.
This commit is contained in:
		
							parent
							
								
									a5ee50cfc9
								
							
						
					
					
						commit
						a9e9ae8c3e
					
				@ -10,7 +10,7 @@ import { ItemList } from 'component/common/ItemList/ItemList';
 | 
				
			|||||||
import useAuthSettings from 'hooks/api/getters/useAuthSettings/useAuthSettings';
 | 
					import useAuthSettings from 'hooks/api/getters/useAuthSettings/useAuthSettings';
 | 
				
			||||||
import { Link } from 'react-router-dom';
 | 
					import { Link } from 'react-router-dom';
 | 
				
			||||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
 | 
					import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import { useUsers } from 'hooks/api/getters/useUsers/useUsers';
 | 
					import { useUsers } from 'hooks/api/getters/useUsers/useUsers';
 | 
				
			||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
					import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
				
			||||||
import { RoleSelect } from 'component/common/RoleSelect/RoleSelect';
 | 
					import { RoleSelect } from 'component/common/RoleSelect/RoleSelect';
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import { useEffect, useState } from 'react';
 | 
					import { useEffect, useState } from 'react';
 | 
				
			||||||
import { IPermission, ICheckedPermissions } from 'interfaces/permissions';
 | 
					import { IPermission, ICheckedPermissions } from 'interfaces/permissions';
 | 
				
			||||||
import IRole, { PredefinedRoleType } from 'interfaces/role';
 | 
					import { IRole, PredefinedRoleType } from 'interfaces/role';
 | 
				
			||||||
import { useRoles } from 'hooks/api/getters/useRoles/useRoles';
 | 
					import { useRoles } from 'hooks/api/getters/useRoles/useRoles';
 | 
				
			||||||
import { permissionsToCheckedPermissions } from 'utils/permissions';
 | 
					import { permissionsToCheckedPermissions } from 'utils/permissions';
 | 
				
			||||||
import { ROOT_ROLE_TYPE } from '@server/util/constants';
 | 
					import { ROOT_ROLE_TYPE } from '@server/util/constants';
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ import { PageHeader } from 'component/common/PageHeader/PageHeader';
 | 
				
			|||||||
import { Add } from '@mui/icons-material';
 | 
					import { Add } from '@mui/icons-material';
 | 
				
			||||||
import { UPDATE_ROLE } from '@server/types/permissions';
 | 
					import { UPDATE_ROLE } from '@server/types/permissions';
 | 
				
			||||||
import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton';
 | 
					import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledPageContent = styled(PageContent)(({ theme }) => ({
 | 
					const StyledPageContent = styled(PageContent)(({ theme }) => ({
 | 
				
			||||||
    '& .page-header': {
 | 
					    '& .page-header': {
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
 | 
				
			|||||||
import { Dialogue } from 'component/common/Dialogue/Dialogue';
 | 
					import { Dialogue } from 'component/common/Dialogue/Dialogue';
 | 
				
			||||||
import { useServiceAccounts } from 'hooks/api/getters/useServiceAccounts/useServiceAccounts';
 | 
					import { useServiceAccounts } from 'hooks/api/getters/useServiceAccounts/useServiceAccounts';
 | 
				
			||||||
import { useUsers } from 'hooks/api/getters/useUsers/useUsers';
 | 
					import { useUsers } from 'hooks/api/getters/useUsers/useUsers';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import { RoleDeleteDialogUsers } from './RoleDeleteDialogUsers/RoleDeleteDialogUsers';
 | 
					import { RoleDeleteDialogUsers } from './RoleDeleteDialogUsers/RoleDeleteDialogUsers';
 | 
				
			||||||
import { RoleDeleteDialogServiceAccounts } from './RoleDeleteDialogServiceAccounts/RoleDeleteDialogServiceAccounts';
 | 
					import { RoleDeleteDialogServiceAccounts } from './RoleDeleteDialogServiceAccounts/RoleDeleteDialogServiceAccounts';
 | 
				
			||||||
import { useGroups } from 'hooks/api/getters/useGroups/useGroups';
 | 
					import { useGroups } from 'hooks/api/getters/useGroups/useGroups';
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { VFC } from 'react';
 | 
					import { VFC } from 'react';
 | 
				
			||||||
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
 | 
					import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
 | 
				
			||||||
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
 | 
					import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import { useRole } from 'hooks/api/getters/useRole/useRole';
 | 
					import { useRole } from 'hooks/api/getters/useRole/useRole';
 | 
				
			||||||
import { RoleDescription } from 'component/common/RoleDescription/RoleDescription';
 | 
					import { RoleDescription } from 'component/common/RoleDescription/RoleDescription';
 | 
				
			||||||
import { PREDEFINED_ROLE_TYPES } from '@server/util/constants';
 | 
					import { PREDEFINED_ROLE_TYPES } from '@server/util/constants';
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ import { Box, styled } from '@mui/material';
 | 
				
			|||||||
import { PREDEFINED_ROLE_TYPES } from '@server/util/constants';
 | 
					import { PREDEFINED_ROLE_TYPES } from '@server/util/constants';
 | 
				
			||||||
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
 | 
					import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
 | 
				
			||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
 | 
					import { ADMIN } from 'component/providers/AccessProvider/permissions';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import { VFC } from 'react';
 | 
					import { VFC } from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledBox = styled(Box)(() => ({
 | 
					const StyledBox = styled(Box)(() => ({
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
import { Badge } from 'component/common/Badge/Badge';
 | 
					import { Badge } from 'component/common/Badge/Badge';
 | 
				
			||||||
import { styled } from '@mui/material';
 | 
					import { styled } from '@mui/material';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import { HighlightCell } from 'component/common/Table/cells/HighlightCell/HighlightCell';
 | 
					import { HighlightCell } from 'component/common/Table/cells/HighlightCell/HighlightCell';
 | 
				
			||||||
import { PREDEFINED_ROLE_TYPES } from '@server/util/constants';
 | 
					import { PREDEFINED_ROLE_TYPES } from '@server/util/constants';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { useMemo, useState } from 'react';
 | 
					import { useMemo, useState } from 'react';
 | 
				
			||||||
import { TablePlaceholder, VirtualizedTable } from 'component/common/Table';
 | 
					import { TablePlaceholder, VirtualizedTable } from 'component/common/Table';
 | 
				
			||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
import IRole, { PredefinedRoleType } from 'interfaces/role';
 | 
					import { IRole, PredefinedRoleType } from 'interfaces/role';
 | 
				
			||||||
import useToast from 'hooks/useToast';
 | 
					import useToast from 'hooks/useToast';
 | 
				
			||||||
import { formatUnknownError } from 'utils/formatUnknownError';
 | 
					import { formatUnknownError } from 'utils/formatUnknownError';
 | 
				
			||||||
import { PageContent } from 'component/common/PageContent/PageContent';
 | 
					import { PageContent } from 'component/common/PageContent/PageContent';
 | 
				
			||||||
 | 
				
			|||||||
@ -33,7 +33,7 @@ import { INewPersonalAPIToken } from 'interfaces/personalAPIToken';
 | 
				
			|||||||
import { ServiceAccountTokens } from './ServiceAccountTokens/ServiceAccountTokens';
 | 
					import { ServiceAccountTokens } from './ServiceAccountTokens/ServiceAccountTokens';
 | 
				
			||||||
import { IServiceAccount } from 'interfaces/service-account';
 | 
					import { IServiceAccount } from 'interfaces/service-account';
 | 
				
			||||||
import { RoleSelect } from 'component/common/RoleSelect/RoleSelect';
 | 
					import { RoleSelect } from 'component/common/RoleSelect/RoleSelect';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledForm = styled('form')(() => ({
 | 
					const StyledForm = styled('form')(() => ({
 | 
				
			||||||
    display: 'flex',
 | 
					    display: 'flex',
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { useMemo, useState } from 'react';
 | 
					import { useMemo, useState } from 'react';
 | 
				
			||||||
import { TablePlaceholder, VirtualizedTable } from 'component/common/Table';
 | 
					import { TablePlaceholder, VirtualizedTable } from 'component/common/Table';
 | 
				
			||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import useToast from 'hooks/useToast';
 | 
					import useToast from 'hooks/useToast';
 | 
				
			||||||
import { formatUnknownError } from 'utils/formatUnknownError';
 | 
					import { formatUnknownError } from 'utils/formatUnknownError';
 | 
				
			||||||
import { PageContent } from 'component/common/PageContent/PageContent';
 | 
					import { PageContent } from 'component/common/PageContent/PageContent';
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
 | 
				
			|||||||
import { EDIT } from 'constants/misc';
 | 
					import { EDIT } from 'constants/misc';
 | 
				
			||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
					import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
				
			||||||
import { RoleSelect } from 'component/common/RoleSelect/RoleSelect';
 | 
					import { RoleSelect } from 'component/common/RoleSelect/RoleSelect';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledForm = styled('form')(() => ({
 | 
					const StyledForm = styled('form')(() => ({
 | 
				
			||||||
    display: 'flex',
 | 
					    display: 'flex',
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ import ConfirmUserAdded from '../ConfirmUserAdded/ConfirmUserAdded';
 | 
				
			|||||||
import { useUsers } from 'hooks/api/getters/useUsers/useUsers';
 | 
					import { useUsers } from 'hooks/api/getters/useUsers/useUsers';
 | 
				
			||||||
import useAdminUsersApi from 'hooks/api/actions/useAdminUsersApi/useAdminUsersApi';
 | 
					import useAdminUsersApi from 'hooks/api/actions/useAdminUsersApi/useAdminUsersApi';
 | 
				
			||||||
import { IUser } from 'interfaces/user';
 | 
					import { IUser } from 'interfaces/user';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import useToast from 'hooks/useToast';
 | 
					import useToast from 'hooks/useToast';
 | 
				
			||||||
import { formatUnknownError } from 'utils/formatUnknownError';
 | 
					import { formatUnknownError } from 'utils/formatUnknownError';
 | 
				
			||||||
import { useUsersPlan } from 'hooks/useUsersPlan';
 | 
					import { useUsersPlan } from 'hooks/useUsersPlan';
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { useEffect, useState } from 'react';
 | 
					import { useEffect, useState } from 'react';
 | 
				
			||||||
import { useUsers } from 'hooks/api/getters/useUsers/useUsers';
 | 
					import { useUsers } from 'hooks/api/getters/useUsers/useUsers';
 | 
				
			||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
					import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import { useRoles } from 'hooks/api/getters/useRoles/useRoles';
 | 
					import { useRoles } from 'hooks/api/getters/useRoles/useRoles';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const useCreateUserForm = (
 | 
					const useCreateUserForm = (
 | 
				
			||||||
 | 
				
			|||||||
@ -5,9 +5,10 @@ import {
 | 
				
			|||||||
    styled,
 | 
					    styled,
 | 
				
			||||||
} from '@mui/material';
 | 
					} from '@mui/material';
 | 
				
			||||||
import { useRoles } from 'hooks/api/getters/useRoles/useRoles';
 | 
					import { useRoles } from 'hooks/api/getters/useRoles/useRoles';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole, PredefinedRoleType } from 'interfaces/role';
 | 
				
			||||||
import { RoleDescription } from '../RoleDescription/RoleDescription';
 | 
					import { RoleDescription } from '../RoleDescription/RoleDescription';
 | 
				
			||||||
import { ConditionallyRender } from '../ConditionallyRender/ConditionallyRender';
 | 
					import { ConditionallyRender } from '../ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
 | 
					import { ROOT_ROLE_TYPE } from '@server/util/constants';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledRoleOption = styled('div')(({ theme }) => ({
 | 
					const StyledRoleOption = styled('div')(({ theme }) => ({
 | 
				
			||||||
    display: 'flex',
 | 
					    display: 'flex',
 | 
				
			||||||
@ -20,18 +21,22 @@ const StyledRoleOption = styled('div')(({ theme }) => ({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
interface IRoleSelectProps
 | 
					interface IRoleSelectProps
 | 
				
			||||||
    extends Partial<AutocompleteProps<IRole, false, false, false>> {
 | 
					    extends Partial<AutocompleteProps<IRole, false, false, false>> {
 | 
				
			||||||
 | 
					    type?: PredefinedRoleType;
 | 
				
			||||||
    value: IRole | null;
 | 
					    value: IRole | null;
 | 
				
			||||||
    setValue: (role: IRole | null) => void;
 | 
					    setValue: (role: IRole | null) => void;
 | 
				
			||||||
    required?: boolean;
 | 
					    required?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const RoleSelect = ({
 | 
					export const RoleSelect = ({
 | 
				
			||||||
 | 
					    type = ROOT_ROLE_TYPE,
 | 
				
			||||||
    value,
 | 
					    value,
 | 
				
			||||||
    setValue,
 | 
					    setValue,
 | 
				
			||||||
    required,
 | 
					    required,
 | 
				
			||||||
    ...rest
 | 
					    ...rest
 | 
				
			||||||
}: IRoleSelectProps) => {
 | 
					}: IRoleSelectProps) => {
 | 
				
			||||||
    const { roles } = useRoles();
 | 
					    const { roles: rootRoles, projectRoles } = useRoles();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const roles = type === ROOT_ROLE_TYPE ? rootRoles : projectRoles;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const renderRoleOption = (
 | 
					    const renderRoleOption = (
 | 
				
			||||||
        props: React.HTMLAttributes<HTMLLIElement>,
 | 
					        props: React.HTMLAttributes<HTMLLIElement>,
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@ import useProjectAccess, {
 | 
				
			|||||||
    ENTITY_TYPE,
 | 
					    ENTITY_TYPE,
 | 
				
			||||||
    IProjectAccess,
 | 
					    IProjectAccess,
 | 
				
			||||||
} from 'hooks/api/getters/useProjectAccess/useProjectAccess';
 | 
					} from 'hooks/api/getters/useProjectAccess/useProjectAccess';
 | 
				
			||||||
import { IProjectRole } from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
 | 
					import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
 | 
				
			||||||
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
 | 
					import FormTemplate from 'component/common/FormTemplate/FormTemplate';
 | 
				
			||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
					import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
				
			||||||
@ -25,7 +25,6 @@ import { formatUnknownError } from 'utils/formatUnknownError';
 | 
				
			|||||||
import { IUser } from 'interfaces/user';
 | 
					import { IUser } from 'interfaces/user';
 | 
				
			||||||
import { IGroup } from 'interfaces/group';
 | 
					import { IGroup } from 'interfaces/group';
 | 
				
			||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
import { ProjectRoleDescription } from './ProjectRoleDescription/ProjectRoleDescription';
 | 
					 | 
				
			||||||
import { useNavigate } from 'react-router-dom';
 | 
					import { useNavigate } from 'react-router-dom';
 | 
				
			||||||
import { GO_BACK } from 'constants/navigate';
 | 
					import { GO_BACK } from 'constants/navigate';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
@ -36,6 +35,8 @@ import {
 | 
				
			|||||||
} from 'utils/testIds';
 | 
					} from 'utils/testIds';
 | 
				
			||||||
import { caseInsensitiveSearch } from 'utils/search';
 | 
					import { caseInsensitiveSearch } from 'utils/search';
 | 
				
			||||||
import { IServiceAccount } from 'interfaces/service-account';
 | 
					import { IServiceAccount } from 'interfaces/service-account';
 | 
				
			||||||
 | 
					import { RoleSelect } from 'component/common/RoleSelect/RoleSelect';
 | 
				
			||||||
 | 
					import { PROJECT_ROLE_TYPE } from '@server/util/constants';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledForm = styled('form')(() => ({
 | 
					const StyledForm = styled('form')(() => ({
 | 
				
			||||||
    display: 'flex',
 | 
					    display: 'flex',
 | 
				
			||||||
@ -82,15 +83,6 @@ const StyledUserOption = styled('div')(({ theme }) => ({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledRoleOption = styled('div')(({ theme }) => ({
 | 
					 | 
				
			||||||
    display: 'flex',
 | 
					 | 
				
			||||||
    flexDirection: 'column',
 | 
					 | 
				
			||||||
    '& > span:last-of-type': {
 | 
					 | 
				
			||||||
        fontSize: theme.fontSizes.smallerBody,
 | 
					 | 
				
			||||||
        color: theme.palette.text.secondary,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface IAccessOption {
 | 
					interface IAccessOption {
 | 
				
			||||||
    id: number;
 | 
					    id: number;
 | 
				
			||||||
    entity: IUser | IGroup;
 | 
					    entity: IUser | IGroup;
 | 
				
			||||||
@ -103,7 +95,7 @@ interface IProjectAccessAssignProps {
 | 
				
			|||||||
    users: IUser[];
 | 
					    users: IUser[];
 | 
				
			||||||
    serviceAccounts: IServiceAccount[];
 | 
					    serviceAccounts: IServiceAccount[];
 | 
				
			||||||
    groups: IGroup[];
 | 
					    groups: IGroup[];
 | 
				
			||||||
    roles: IProjectRole[];
 | 
					    roles: IRole[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ProjectAccessAssign = ({
 | 
					export const ProjectAccessAssign = ({
 | 
				
			||||||
@ -190,7 +182,7 @@ export const ProjectAccessAssign = ({
 | 
				
			|||||||
                    id === selected?.entity.id && type === selected?.type
 | 
					                    id === selected?.entity.id && type === selected?.type
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    const [role, setRole] = useState<IProjectRole | null>(
 | 
					    const [role, setRole] = useState<IRole | null>(
 | 
				
			||||||
        roles.find(({ id }) => id === selected?.entity.roleId) ?? null
 | 
					        roles.find(({ id }) => id === selected?.entity.roleId) ?? null
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -317,18 +309,6 @@ export const ProjectAccessAssign = ({
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const renderRoleOption = (
 | 
					 | 
				
			||||||
        props: React.HTMLAttributes<HTMLLIElement>,
 | 
					 | 
				
			||||||
        option: IProjectRole
 | 
					 | 
				
			||||||
    ) => (
 | 
					 | 
				
			||||||
        <li {...props}>
 | 
					 | 
				
			||||||
            <StyledRoleOption>
 | 
					 | 
				
			||||||
                <span>{option.name}</span>
 | 
					 | 
				
			||||||
                <span>{option.description}</span>
 | 
					 | 
				
			||||||
            </StyledRoleOption>
 | 
					 | 
				
			||||||
        </li>
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const isValid = selectedOptions.length > 0 && role;
 | 
					    const isValid = selectedOptions.length > 0 && role;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
@ -451,29 +431,13 @@ export const ProjectAccessAssign = ({
 | 
				
			|||||||
                            Select the role to assign for this project
 | 
					                            Select the role to assign for this project
 | 
				
			||||||
                        </StyledInputDescription>
 | 
					                        </StyledInputDescription>
 | 
				
			||||||
                        <StyledAutocompleteWrapper>
 | 
					                        <StyledAutocompleteWrapper>
 | 
				
			||||||
                            <Autocomplete
 | 
					                            <RoleSelect
 | 
				
			||||||
                                data-testid={PA_ROLE_ID}
 | 
					                                data-testid={PA_ROLE_ID}
 | 
				
			||||||
                                size="small"
 | 
					                                type={PROJECT_ROLE_TYPE}
 | 
				
			||||||
                                openOnFocus
 | 
					 | 
				
			||||||
                                value={role}
 | 
					                                value={role}
 | 
				
			||||||
                                onChange={(_, newValue) => setRole(newValue)}
 | 
					                                setValue={role => setRole(role || null)}
 | 
				
			||||||
                                options={roles}
 | 
					 | 
				
			||||||
                                renderOption={renderRoleOption}
 | 
					 | 
				
			||||||
                                getOptionLabel={option => option.name}
 | 
					 | 
				
			||||||
                                renderInput={params => (
 | 
					 | 
				
			||||||
                                    <TextField {...params} label="Role" />
 | 
					 | 
				
			||||||
                                )}
 | 
					 | 
				
			||||||
                            />
 | 
					                            />
 | 
				
			||||||
                        </StyledAutocompleteWrapper>
 | 
					                        </StyledAutocompleteWrapper>
 | 
				
			||||||
                        <ConditionallyRender
 | 
					 | 
				
			||||||
                            condition={Boolean(role?.id)}
 | 
					 | 
				
			||||||
                            show={
 | 
					 | 
				
			||||||
                                <ProjectRoleDescription
 | 
					 | 
				
			||||||
                                    roleId={role?.id!}
 | 
					 | 
				
			||||||
                                    projectId={projectId}
 | 
					 | 
				
			||||||
                                />
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        />
 | 
					 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <StyledButtonContainer>
 | 
					                    <StyledButtonContainer>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,163 +0,0 @@
 | 
				
			|||||||
import { styled, SxProps, Theme } from '@mui/material';
 | 
					 | 
				
			||||||
import { ForwardedRef, forwardRef, useMemo, VFC } from 'react';
 | 
					 | 
				
			||||||
import { useRole } from 'hooks/api/getters/useRole/useRole';
 | 
					 | 
				
			||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					 | 
				
			||||||
import useProjectAccess from 'hooks/api/getters/useProjectAccess/useProjectAccess';
 | 
					 | 
				
			||||||
import { ProjectRoleDescriptionProjectPermissions } from './ProjectRoleDescriptionProjectPermissions/ProjectRoleDescriptionProjectPermissions';
 | 
					 | 
				
			||||||
import { ProjectRoleDescriptionEnvironmentPermissions } from './ProjectRoleDescriptionEnvironmentPermissions/ProjectRoleDescriptionEnvironmentPermissions';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const StyledDescription = styled('div', {
 | 
					 | 
				
			||||||
    shouldForwardProp: prop =>
 | 
					 | 
				
			||||||
        prop !== 'roleId' && prop !== 'popover' && prop !== 'sx',
 | 
					 | 
				
			||||||
})<IProjectRoleDescriptionStyleProps>(({ theme, popover }) => ({
 | 
					 | 
				
			||||||
    width: '100%',
 | 
					 | 
				
			||||||
    maxWidth: theme.spacing(50),
 | 
					 | 
				
			||||||
    padding: theme.spacing(3),
 | 
					 | 
				
			||||||
    backgroundColor: popover
 | 
					 | 
				
			||||||
        ? theme.palette.background.paper
 | 
					 | 
				
			||||||
        : theme.palette.neutral.light,
 | 
					 | 
				
			||||||
    color: theme.palette.text.secondary,
 | 
					 | 
				
			||||||
    fontSize: theme.fontSizes.smallBody,
 | 
					 | 
				
			||||||
    borderRadius: theme.shape.borderRadiusMedium,
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const StyledDescriptionBlock = styled('div')(({ theme }) => ({
 | 
					 | 
				
			||||||
    '& p:last-child': {
 | 
					 | 
				
			||||||
        marginBottom: theme.spacing(2),
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const StyledDescriptionHeader = styled('p')(({ theme }) => ({
 | 
					 | 
				
			||||||
    color: theme.palette.text.primary,
 | 
					 | 
				
			||||||
    fontSize: theme.fontSizes.smallBody,
 | 
					 | 
				
			||||||
    fontWeight: theme.fontWeight.bold,
 | 
					 | 
				
			||||||
    marginBottom: theme.spacing(2),
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const StyledDescriptionSubHeader = styled('p')(({ theme }) => ({
 | 
					 | 
				
			||||||
    color: theme.palette.text.primary,
 | 
					 | 
				
			||||||
    fontSize: theme.fontSizes.smallBody,
 | 
					 | 
				
			||||||
    marginBottom: theme.spacing(1),
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface IProjectRoleDescriptionStyleProps {
 | 
					 | 
				
			||||||
    popover?: boolean;
 | 
					 | 
				
			||||||
    className?: string;
 | 
					 | 
				
			||||||
    sx?: SxProps<Theme>;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface IProjectRoleDescriptionProps
 | 
					 | 
				
			||||||
    extends IProjectRoleDescriptionStyleProps {
 | 
					 | 
				
			||||||
    roleId: number;
 | 
					 | 
				
			||||||
    projectId: string;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const ProjectRoleDescription: VFC<IProjectRoleDescriptionProps> =
 | 
					 | 
				
			||||||
    forwardRef(
 | 
					 | 
				
			||||||
        (
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                roleId,
 | 
					 | 
				
			||||||
                projectId,
 | 
					 | 
				
			||||||
                className,
 | 
					 | 
				
			||||||
                sx,
 | 
					 | 
				
			||||||
                ...props
 | 
					 | 
				
			||||||
            }: IProjectRoleDescriptionProps,
 | 
					 | 
				
			||||||
            ref: ForwardedRef<HTMLDivElement>
 | 
					 | 
				
			||||||
        ) => {
 | 
					 | 
				
			||||||
            const { role } = useRole(roleId.toString());
 | 
					 | 
				
			||||||
            const { access } = useProjectAccess(projectId);
 | 
					 | 
				
			||||||
            const accessRole = access?.roles.find(role => role.id === roleId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const environments = useMemo(() => {
 | 
					 | 
				
			||||||
                const environments = new Set<string>();
 | 
					 | 
				
			||||||
                role?.permissions
 | 
					 | 
				
			||||||
                    ?.filter((permission: any) => permission.environment)
 | 
					 | 
				
			||||||
                    .forEach((permission: any) => {
 | 
					 | 
				
			||||||
                        environments.add(permission.environment);
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                return [...environments].sort();
 | 
					 | 
				
			||||||
            }, [role]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const projectPermissions = useMemo(() => {
 | 
					 | 
				
			||||||
                return role?.permissions?.filter(
 | 
					 | 
				
			||||||
                    (permission: any) => !permission.environment
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            }, [role]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return (
 | 
					 | 
				
			||||||
                <StyledDescription
 | 
					 | 
				
			||||||
                    className={className}
 | 
					 | 
				
			||||||
                    sx={sx}
 | 
					 | 
				
			||||||
                    {...props}
 | 
					 | 
				
			||||||
                    ref={ref}
 | 
					 | 
				
			||||||
                >
 | 
					 | 
				
			||||||
                    <ConditionallyRender
 | 
					 | 
				
			||||||
                        condition={Boolean(
 | 
					 | 
				
			||||||
                            role?.permissions && role?.permissions?.length > 0
 | 
					 | 
				
			||||||
                        )}
 | 
					 | 
				
			||||||
                        show={
 | 
					 | 
				
			||||||
                            <>
 | 
					 | 
				
			||||||
                                <ConditionallyRender
 | 
					 | 
				
			||||||
                                    condition={Boolean(
 | 
					 | 
				
			||||||
                                        projectPermissions?.length
 | 
					 | 
				
			||||||
                                    )}
 | 
					 | 
				
			||||||
                                    show={
 | 
					 | 
				
			||||||
                                        <>
 | 
					 | 
				
			||||||
                                            <StyledDescriptionHeader>
 | 
					 | 
				
			||||||
                                                Project permissions
 | 
					 | 
				
			||||||
                                            </StyledDescriptionHeader>
 | 
					 | 
				
			||||||
                                            <StyledDescriptionBlock>
 | 
					 | 
				
			||||||
                                                <ProjectRoleDescriptionProjectPermissions
 | 
					 | 
				
			||||||
                                                    permissions={
 | 
					 | 
				
			||||||
                                                        role?.permissions || []
 | 
					 | 
				
			||||||
                                                    }
 | 
					 | 
				
			||||||
                                                />
 | 
					 | 
				
			||||||
                                            </StyledDescriptionBlock>
 | 
					 | 
				
			||||||
                                        </>
 | 
					 | 
				
			||||||
                                    }
 | 
					 | 
				
			||||||
                                />
 | 
					 | 
				
			||||||
                                <ConditionallyRender
 | 
					 | 
				
			||||||
                                    condition={Boolean(environments.length)}
 | 
					 | 
				
			||||||
                                    show={
 | 
					 | 
				
			||||||
                                        <>
 | 
					 | 
				
			||||||
                                            <StyledDescriptionHeader>
 | 
					 | 
				
			||||||
                                                Environment permissions
 | 
					 | 
				
			||||||
                                            </StyledDescriptionHeader>
 | 
					 | 
				
			||||||
                                            {environments.map(environment => (
 | 
					 | 
				
			||||||
                                                <div key={environment}>
 | 
					 | 
				
			||||||
                                                    <StyledDescriptionSubHeader>
 | 
					 | 
				
			||||||
                                                        {environment}
 | 
					 | 
				
			||||||
                                                    </StyledDescriptionSubHeader>
 | 
					 | 
				
			||||||
                                                    <StyledDescriptionBlock>
 | 
					 | 
				
			||||||
                                                        <ProjectRoleDescriptionEnvironmentPermissions
 | 
					 | 
				
			||||||
                                                            environment={
 | 
					 | 
				
			||||||
                                                                environment
 | 
					 | 
				
			||||||
                                                            }
 | 
					 | 
				
			||||||
                                                            permissions={
 | 
					 | 
				
			||||||
                                                                role?.permissions ||
 | 
					 | 
				
			||||||
                                                                []
 | 
					 | 
				
			||||||
                                                            }
 | 
					 | 
				
			||||||
                                                        />
 | 
					 | 
				
			||||||
                                                    </StyledDescriptionBlock>
 | 
					 | 
				
			||||||
                                                </div>
 | 
					 | 
				
			||||||
                                            ))}
 | 
					 | 
				
			||||||
                                        </>
 | 
					 | 
				
			||||||
                                    }
 | 
					 | 
				
			||||||
                                />
 | 
					 | 
				
			||||||
                            </>
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        elseShow={
 | 
					 | 
				
			||||||
                            <>
 | 
					 | 
				
			||||||
                                <StyledDescriptionSubHeader>
 | 
					 | 
				
			||||||
                                    {accessRole?.name}
 | 
					 | 
				
			||||||
                                </StyledDescriptionSubHeader>
 | 
					 | 
				
			||||||
                                <StyledDescriptionBlock>
 | 
					 | 
				
			||||||
                                    {accessRole?.description}
 | 
					 | 
				
			||||||
                                </StyledDescriptionBlock>
 | 
					 | 
				
			||||||
                            </>
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    />
 | 
					 | 
				
			||||||
                </StyledDescription>
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
@ -1,26 +0,0 @@
 | 
				
			|||||||
interface IProjectRoleDescriptionEnvironmentPermissionsProps {
 | 
					 | 
				
			||||||
    environment: string;
 | 
					 | 
				
			||||||
    permissions: any[];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const ProjectRoleDescriptionEnvironmentPermissions = ({
 | 
					 | 
				
			||||||
    environment,
 | 
					 | 
				
			||||||
    permissions,
 | 
					 | 
				
			||||||
}: IProjectRoleDescriptionEnvironmentPermissionsProps) => (
 | 
					 | 
				
			||||||
    <>
 | 
					 | 
				
			||||||
        {[
 | 
					 | 
				
			||||||
            ...new Set(
 | 
					 | 
				
			||||||
                permissions
 | 
					 | 
				
			||||||
                    .filter(
 | 
					 | 
				
			||||||
                        (permission: any) =>
 | 
					 | 
				
			||||||
                            permission.environment === environment
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                    .map((permission: any) => permission.displayName)
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
            .sort()
 | 
					 | 
				
			||||||
            .map((permission: any) => (
 | 
					 | 
				
			||||||
                <p key={`${environment}-${permission}`}>{permission}</p>
 | 
					 | 
				
			||||||
            ))}
 | 
					 | 
				
			||||||
    </>
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
@ -1,17 +0,0 @@
 | 
				
			|||||||
interface IProjectRoleDescriptionProjectPermissionsProps {
 | 
					 | 
				
			||||||
    permissions: any[];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const ProjectRoleDescriptionProjectPermissions = ({
 | 
					 | 
				
			||||||
    permissions,
 | 
					 | 
				
			||||||
}: IProjectRoleDescriptionProjectPermissionsProps) => (
 | 
					 | 
				
			||||||
    <>
 | 
					 | 
				
			||||||
        {permissions
 | 
					 | 
				
			||||||
            ?.filter((permission: any) => !permission.environment)
 | 
					 | 
				
			||||||
            .map((permission: any) => permission.displayName)
 | 
					 | 
				
			||||||
            .sort()
 | 
					 | 
				
			||||||
            .map((permission: any) => (
 | 
					 | 
				
			||||||
                <p key={permission}>{permission}</p>
 | 
					 | 
				
			||||||
            ))}
 | 
					 | 
				
			||||||
    </>
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
@ -1,40 +0,0 @@
 | 
				
			|||||||
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
 | 
					 | 
				
			||||||
import { VFC } from 'react';
 | 
					 | 
				
			||||||
import { ProjectRoleDescription } from 'component/project/ProjectAccess/ProjectAccessAssign/ProjectRoleDescription/ProjectRoleDescription';
 | 
					 | 
				
			||||||
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface IProjectAccessRoleCellProps {
 | 
					 | 
				
			||||||
    roleId: number;
 | 
					 | 
				
			||||||
    projectId: string;
 | 
					 | 
				
			||||||
    value?: string;
 | 
					 | 
				
			||||||
    emptyText?: string;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const ProjectAccessRoleCell: VFC<IProjectAccessRoleCellProps> = ({
 | 
					 | 
				
			||||||
    roleId,
 | 
					 | 
				
			||||||
    projectId,
 | 
					 | 
				
			||||||
    value,
 | 
					 | 
				
			||||||
    emptyText,
 | 
					 | 
				
			||||||
}) => {
 | 
					 | 
				
			||||||
    if (!value) return <TextCell>{emptyText}</TextCell>;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (
 | 
					 | 
				
			||||||
        <TextCell>
 | 
					 | 
				
			||||||
            <TooltipLink
 | 
					 | 
				
			||||||
                tooltip={
 | 
					 | 
				
			||||||
                    <ProjectRoleDescription
 | 
					 | 
				
			||||||
                        roleId={roleId}
 | 
					 | 
				
			||||||
                        projectId={projectId}
 | 
					 | 
				
			||||||
                        popover
 | 
					 | 
				
			||||||
                    />
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                tooltipProps={{
 | 
					 | 
				
			||||||
                    maxWidth: 500,
 | 
					 | 
				
			||||||
                    maxHeight: 600,
 | 
					 | 
				
			||||||
                }}
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
                {value}
 | 
					 | 
				
			||||||
            </TooltipLink>
 | 
					 | 
				
			||||||
        </TextCell>
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@ -43,7 +43,7 @@ import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton
 | 
				
			|||||||
import { ProjectAccessCreate } from 'component/project/ProjectAccess/ProjectAccessCreate/ProjectAccessCreate';
 | 
					import { ProjectAccessCreate } from 'component/project/ProjectAccess/ProjectAccessCreate/ProjectAccessCreate';
 | 
				
			||||||
import { ProjectAccessEditUser } from 'component/project/ProjectAccess/ProjectAccessEditUser/ProjectAccessEditUser';
 | 
					import { ProjectAccessEditUser } from 'component/project/ProjectAccess/ProjectAccessEditUser/ProjectAccessEditUser';
 | 
				
			||||||
import { ProjectAccessEditGroup } from 'component/project/ProjectAccess/ProjectAccessEditGroup/ProjectAccessEditGroup';
 | 
					import { ProjectAccessEditGroup } from 'component/project/ProjectAccess/ProjectAccessEditGroup/ProjectAccessEditGroup';
 | 
				
			||||||
import { ProjectAccessRoleCell } from './ProjectAccessRoleCell/ProjectAccessRoleCell';
 | 
					import { RoleCell } from 'component/common/Table/cells/RoleCell/RoleCell';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    PA_ASSIGN_BUTTON_ID,
 | 
					    PA_ASSIGN_BUTTON_ID,
 | 
				
			||||||
    PA_EDIT_BUTTON_ID,
 | 
					    PA_EDIT_BUTTON_ID,
 | 
				
			||||||
@ -168,11 +168,7 @@ export const ProjectAccessTable: VFC = () => {
 | 
				
			|||||||
                    access?.roles.find(({ id }) => id === row.entity.roleId)
 | 
					                    access?.roles.find(({ id }) => id === row.entity.roleId)
 | 
				
			||||||
                        ?.name,
 | 
					                        ?.name,
 | 
				
			||||||
                Cell: ({ value, row: { original: row } }: any) => (
 | 
					                Cell: ({ value, row: { original: row } }: any) => (
 | 
				
			||||||
                    <ProjectAccessRoleCell
 | 
					                    <RoleCell roleId={row.entity.roleId} value={value} />
 | 
				
			||||||
                        roleId={row.entity.roleId}
 | 
					 | 
				
			||||||
                        projectId={projectId}
 | 
					 | 
				
			||||||
                        value={value}
 | 
					 | 
				
			||||||
                    />
 | 
					 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                maxWidth: 125,
 | 
					                maxWidth: 125,
 | 
				
			||||||
                filterName: 'role',
 | 
					                filterName: 'role',
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@ import useSWR, { mutate, SWRConfiguration } from 'swr';
 | 
				
			|||||||
import { useState, useEffect, useMemo } from 'react';
 | 
					import { useState, useEffect, useMemo } from 'react';
 | 
				
			||||||
import { formatApiPath } from 'utils/formatPath';
 | 
					import { formatApiPath } from 'utils/formatPath';
 | 
				
			||||||
import handleErrorResponses from '../httpErrorResponseHandler';
 | 
					import handleErrorResponses from '../httpErrorResponseHandler';
 | 
				
			||||||
import { IProjectRole } from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import { IGroup } from 'interfaces/group';
 | 
					import { IGroup } from 'interfaces/group';
 | 
				
			||||||
import { IUser } from 'interfaces/user';
 | 
					import { IUser } from 'interfaces/user';
 | 
				
			||||||
import { mapGroupUsers } from '../useGroup/useGroup';
 | 
					import { mapGroupUsers } from '../useGroup/useGroup';
 | 
				
			||||||
@ -30,7 +30,7 @@ export interface IProjectAccessGroup extends IGroup {
 | 
				
			|||||||
export interface IProjectAccessOutput {
 | 
					export interface IProjectAccessOutput {
 | 
				
			||||||
    users: IProjectAccessUser[];
 | 
					    users: IProjectAccessUser[];
 | 
				
			||||||
    groups: IProjectAccessGroup[];
 | 
					    groups: IProjectAccessGroup[];
 | 
				
			||||||
    roles: IProjectRole[];
 | 
					    roles: IRole[];
 | 
				
			||||||
    rows: IProjectAccess[];
 | 
					    rows: IProjectAccess[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@ import { SWRConfiguration } from 'swr';
 | 
				
			|||||||
import { useMemo } from 'react';
 | 
					import { useMemo } from 'react';
 | 
				
			||||||
import { formatApiPath } from 'utils/formatPath';
 | 
					import { formatApiPath } from 'utils/formatPath';
 | 
				
			||||||
import handleErrorResponses from '../httpErrorResponseHandler';
 | 
					import handleErrorResponses from '../httpErrorResponseHandler';
 | 
				
			||||||
import IRole, { IRoleWithPermissions } from 'interfaces/role';
 | 
					import { IRole, IRoleWithPermissions } from 'interfaces/role';
 | 
				
			||||||
import useUiConfig from '../useUiConfig/useUiConfig';
 | 
					import useUiConfig from '../useUiConfig/useUiConfig';
 | 
				
			||||||
import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR';
 | 
					import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import IRole, { IProjectRole } from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import { useMemo } from 'react';
 | 
					import { useMemo } from 'react';
 | 
				
			||||||
import { formatApiPath } from 'utils/formatPath';
 | 
					import { formatApiPath } from 'utils/formatPath';
 | 
				
			||||||
import handleErrorResponses from '../httpErrorResponseHandler';
 | 
					import handleErrorResponses from '../httpErrorResponseHandler';
 | 
				
			||||||
@ -11,7 +11,15 @@ import {
 | 
				
			|||||||
    PREDEFINED_ROLE_TYPES,
 | 
					    PREDEFINED_ROLE_TYPES,
 | 
				
			||||||
} from '@server/util/constants';
 | 
					} from '@server/util/constants';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useRoles = () => {
 | 
					interface IUseRolesOutput {
 | 
				
			||||||
 | 
					    roles: IRole[];
 | 
				
			||||||
 | 
					    projectRoles: IRole[];
 | 
				
			||||||
 | 
					    loading: boolean;
 | 
				
			||||||
 | 
					    refetch: () => void;
 | 
				
			||||||
 | 
					    error?: Error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useRoles = (): IUseRolesOutput => {
 | 
				
			||||||
    const { isEnterprise, uiConfig } = useUiConfig();
 | 
					    const { isEnterprise, uiConfig } = useUiConfig();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { data, error, mutate } = useConditionalSWR(
 | 
					    const { data, error, mutate } = useConditionalSWR(
 | 
				
			||||||
@ -56,7 +64,7 @@ export const useRoles = () => {
 | 
				
			|||||||
                    .filter(({ type }: IRole) =>
 | 
					                    .filter(({ type }: IRole) =>
 | 
				
			||||||
                        PROJECT_ROLE_TYPES.includes(type)
 | 
					                        PROJECT_ROLE_TYPES.includes(type)
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    .sort(sortRoles) ?? []) as IProjectRole[],
 | 
					                    .sort(sortRoles) ?? []) as IRole[],
 | 
				
			||||||
                loading: !error && !data,
 | 
					                loading: !error && !data,
 | 
				
			||||||
                refetch: () => mutate(),
 | 
					                refetch: () => mutate(),
 | 
				
			||||||
                error,
 | 
					                error,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
import { IServiceAccount } from 'interfaces/service-account';
 | 
					import { IServiceAccount } from 'interfaces/service-account';
 | 
				
			||||||
import { useMemo } from 'react';
 | 
					import { useMemo } from 'react';
 | 
				
			||||||
import { formatApiPath } from 'utils/formatPath';
 | 
					import { formatApiPath } from 'utils/formatPath';
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ import { useMemo } from 'react';
 | 
				
			|||||||
import { formatApiPath } from 'utils/formatPath';
 | 
					import { formatApiPath } from 'utils/formatPath';
 | 
				
			||||||
import handleErrorResponses from '../httpErrorResponseHandler';
 | 
					import handleErrorResponses from '../httpErrorResponseHandler';
 | 
				
			||||||
import { IUser } from 'interfaces/user';
 | 
					import { IUser } from 'interfaces/user';
 | 
				
			||||||
import IRole from 'interfaces/role';
 | 
					import { IRole } from 'interfaces/role';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IUseUsersOutput {
 | 
					interface IUseUsersOutput {
 | 
				
			||||||
    users: IUser[];
 | 
					    users: IUser[];
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import IRole from './role';
 | 
					import { IRole } from './role';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IProfile {
 | 
					export interface IProfile {
 | 
				
			||||||
    rootRole: IRole;
 | 
					    rootRole: IRole;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import IRole from './role';
 | 
					import { IRole } from './role';
 | 
				
			||||||
import { IUser } from './user';
 | 
					import { IUser } from './user';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ICreateInvitedUser {
 | 
					export interface ICreateInvitedUser {
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ export type PredefinedRoleType =
 | 
				
			|||||||
    | typeof ROOT_ROLE_TYPE
 | 
					    | typeof ROOT_ROLE_TYPE
 | 
				
			||||||
    | typeof PROJECT_ROLE_TYPE;
 | 
					    | typeof PROJECT_ROLE_TYPE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IRole {
 | 
					export interface IRole {
 | 
				
			||||||
    id: number;
 | 
					    id: number;
 | 
				
			||||||
    name: string;
 | 
					    name: string;
 | 
				
			||||||
    project: string | null;
 | 
					    project: string | null;
 | 
				
			||||||
@ -16,12 +16,3 @@ interface IRole {
 | 
				
			|||||||
export interface IRoleWithPermissions extends IRole {
 | 
					export interface IRoleWithPermissions extends IRole {
 | 
				
			||||||
    permissions: IPermission[];
 | 
					    permissions: IPermission[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface IProjectRole {
 | 
					 | 
				
			||||||
    id: number;
 | 
					 | 
				
			||||||
    name: string;
 | 
					 | 
				
			||||||
    description: string;
 | 
					 | 
				
			||||||
    type: string;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default IRole;
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user