Remove current workspace member from role assignment picker (#10482)
## Context Removing the ability to assign yourself from the UI. The backend already checks that. This is because a member can only have one role for the V1 of permissions Took the opportunity to move some roles related components in dedicated folders
This commit is contained in:
@ -14,7 +14,7 @@ export const RecordTableEmptyStateReadOnly = () => {
|
|||||||
return (
|
return (
|
||||||
<RecordTableEmptyStateDisplay
|
<RecordTableEmptyStateDisplay
|
||||||
title={t`No records found`}
|
title={t`No records found`}
|
||||||
subTitle={t`You are not allowed to create records in this object`}
|
subTitle={t`You are not allowed to create records for this object`}
|
||||||
animatedPlaceholderType="noRecord"
|
animatedPlaceholderType="noRecord"
|
||||||
buttonTitle={buttonTitle}
|
buttonTitle={buttonTitle}
|
||||||
ButtonIcon={IconPlus}
|
ButtonIcon={IconPlus}
|
||||||
|
|||||||
@ -17,10 +17,10 @@ import { TabList } from '@/ui/layout/tab/components/TabList';
|
|||||||
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
|
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
|
||||||
import { useGetRolesQuery } from '~/generated/graphql';
|
import { useGetRolesQuery } from '~/generated/graphql';
|
||||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||||
import { RolePermissions } from '~/pages/settings/roles/components/RolePermissions';
|
import { RolePermissions } from '~/pages/settings/roles/role-permissions/components/RolePermissions';
|
||||||
import { RoleSettings } from '~/pages/settings/roles/components/RoleSettings';
|
import { RoleSettings } from '~/pages/settings/roles/role-settings/components/RoleSettings';
|
||||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||||
import { RoleAssignment } from './components/RoleAssignment';
|
import { RoleAssignment } from './role-assignment/components/RoleAssignment';
|
||||||
|
|
||||||
const StyledContentContainer = styled.div`
|
const StyledContentContainer = styled.div`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMembersStates';
|
import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMembersStates';
|
||||||
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { SettingsPath } from '@/types/SettingsPath';
|
import { SettingsPath } from '@/types/SettingsPath';
|
||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
@ -24,11 +25,11 @@ import {
|
|||||||
useUpdateWorkspaceMemberRoleMutation,
|
useUpdateWorkspaceMemberRoleMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||||
import { RoleAssignmentConfirmationModalSelectedWorkspaceMember } from '~/pages/settings/roles/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember';
|
import { RoleAssignmentTableHeader } from '~/pages/settings/roles/role-assignment/components/RoleAssignmentTableHeader';
|
||||||
|
import { RoleAssignmentWorkspaceMemberPickerDropdown } from '~/pages/settings/roles/role-assignment/components/RoleAssignmentWorkspaceMemberPickerDropdown';
|
||||||
|
import { RoleAssignmentConfirmationModalSelectedWorkspaceMember } from '~/pages/settings/roles/role-assignment/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember';
|
||||||
import { RoleAssignmentConfirmationModal } from './RoleAssignmentConfirmationModal';
|
import { RoleAssignmentConfirmationModal } from './RoleAssignmentConfirmationModal';
|
||||||
import { RoleAssignmentTableHeader } from './RoleAssignmentTableHeader';
|
|
||||||
import { RoleAssignmentTableRow } from './RoleAssignmentTableRow';
|
import { RoleAssignmentTableRow } from './RoleAssignmentTableRow';
|
||||||
import { RoleWorkspaceMemberPickerDropdown } from './RoleWorkspaceMemberPickerDropdown';
|
|
||||||
|
|
||||||
const StyledBottomSection = styled(Section)<{ hasRows: boolean }>`
|
const StyledBottomSection = styled(Section)<{ hasRows: boolean }>`
|
||||||
${({ hasRows, theme }) =>
|
${({ hasRows, theme }) =>
|
||||||
@ -82,6 +83,7 @@ export const RoleAssignment = ({ role }: RoleAssignmentProps) => {
|
|||||||
const { closeDropdown } = useDropdown('role-member-select');
|
const { closeDropdown } = useDropdown('role-member-select');
|
||||||
const [searchFilter, setSearchFilter] = useState('');
|
const [searchFilter, setSearchFilter] = useState('');
|
||||||
const currentWorkspaceMembers = useRecoilValue(currentWorkspaceMembersState);
|
const currentWorkspaceMembers = useRecoilValue(currentWorkspaceMembersState);
|
||||||
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
|
|
||||||
const workspaceMemberRoleMap = new Map<
|
const workspaceMemberRoleMap = new Map<
|
||||||
string,
|
string,
|
||||||
@ -108,6 +110,18 @@ export const RoleAssignment = ({ role }: RoleAssignmentProps) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const assignedWorkspaceMemberIds = role.workspaceMembers.map(
|
||||||
|
(workspaceMember) => workspaceMember.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
const assignableWorkspaceMembers = currentWorkspaceMembers.filter(
|
||||||
|
(member) => member.id !== currentWorkspaceMember?.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
const allWorkspaceMembersHaveThisRole = assignableWorkspaceMembers.every(
|
||||||
|
(member) => assignedWorkspaceMemberIds.includes(member.id),
|
||||||
|
);
|
||||||
|
|
||||||
const handleModalClose = () => {
|
const handleModalClose = () => {
|
||||||
setConfirmationModalIsOpen(false);
|
setConfirmationModalIsOpen(false);
|
||||||
setSelectedWorkspaceMember(null);
|
setSelectedWorkspaceMember(null);
|
||||||
@ -147,9 +161,6 @@ export const RoleAssignment = ({ role }: RoleAssignmentProps) => {
|
|||||||
setSearchFilter(text);
|
setSearchFilter(text);
|
||||||
};
|
};
|
||||||
|
|
||||||
const allWorkspaceMembersHaveThisRole =
|
|
||||||
role.workspaceMembers.length === currentWorkspaceMembers.length;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Section>
|
<Section>
|
||||||
@ -201,10 +212,11 @@ export const RoleAssignment = ({ role }: RoleAssignmentProps) => {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
dropdownComponents={
|
dropdownComponents={
|
||||||
<RoleWorkspaceMemberPickerDropdown
|
<RoleAssignmentWorkspaceMemberPickerDropdown
|
||||||
excludedWorkspaceMemberIds={role.workspaceMembers.map(
|
excludedWorkspaceMemberIds={[
|
||||||
(workspaceMember) => workspaceMember.id,
|
...assignedWorkspaceMemberIds,
|
||||||
)}
|
currentWorkspaceMember?.id,
|
||||||
|
]}
|
||||||
onSelect={handleSelectWorkspaceMember}
|
onSelect={handleSelectWorkspaceMember}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { RoleAssignmentConfirmationModalSubtitle } from '~/pages/settings/roles/components/RoleAssignmentConfirmationModalSubtitle';
|
import { RoleAssignmentConfirmationModalSubtitle } from '~/pages/settings/roles/role-assignment/components/RoleAssignmentConfirmationModalSubtitle';
|
||||||
import { RoleAssignmentConfirmationModalSelectedWorkspaceMember } from '~/pages/settings/roles/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember';
|
import { RoleAssignmentConfirmationModalSelectedWorkspaceMember } from '~/pages/settings/roles/role-assignment/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember';
|
||||||
|
|
||||||
type RoleAssignmentConfirmationModalProps = {
|
type RoleAssignmentConfirmationModalProps = {
|
||||||
selectedWorkspaceMember: RoleAssignmentConfirmationModalSelectedWorkspaceMember;
|
selectedWorkspaceMember: RoleAssignmentConfirmationModalSelectedWorkspaceMember;
|
||||||
@ -2,7 +2,7 @@ import { SettingsCard } from '@/settings/components/SettingsCard';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { IconUser } from 'twenty-ui';
|
import { IconUser } from 'twenty-ui';
|
||||||
import { RoleAssignmentConfirmationModalSelectedWorkspaceMember } from '~/pages/settings/roles/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember';
|
import { RoleAssignmentConfirmationModalSelectedWorkspaceMember } from '~/pages/settings/roles/role-assignment/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember';
|
||||||
|
|
||||||
const StyledSettingsCardContainer = styled.div`
|
const StyledSettingsCardContainer = styled.div`
|
||||||
margin-top: ${({ theme }) => theme.spacing(2)};
|
margin-top: ${({ theme }) => theme.spacing(2)};
|
||||||
@ -8,14 +8,8 @@ const StyledTableHeaderRow = styled(Table)`
|
|||||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type RoleAssignmentTableHeaderProps = {
|
export const RoleAssignmentTableHeader = () => (
|
||||||
className?: string;
|
<StyledTableHeaderRow>
|
||||||
};
|
|
||||||
|
|
||||||
export const RoleAssignmentTableHeader = ({
|
|
||||||
className,
|
|
||||||
}: RoleAssignmentTableHeaderProps) => (
|
|
||||||
<StyledTableHeaderRow className={className}>
|
|
||||||
<TableRow gridAutoColumns="150px 1fr 1fr">
|
<TableRow gridAutoColumns="150px 1fr 1fr">
|
||||||
<TableHeader>{t`Name`}</TableHeader>
|
<TableHeader>{t`Name`}</TableHeader>
|
||||||
<TableHeader>{t`Email`}</TableHeader>
|
<TableHeader>{t`Email`}</TableHeader>
|
||||||
@ -6,17 +6,17 @@ import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/Dropdow
|
|||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||||
import { ChangeEvent, useState } from 'react';
|
import { ChangeEvent, useState } from 'react';
|
||||||
import { WorkspaceMember } from '~/generated-metadata/graphql';
|
import { WorkspaceMember } from '~/generated-metadata/graphql';
|
||||||
import { RoleWorkspaceMemberPickerDropdownContent } from './RoleWorkspaceMemberPickerDropdownContent';
|
import { RoleAssignmentWorkspaceMemberPickerDropdownContent } from '~/pages/settings/roles/role-assignment/components/RoleAssignmentWorkspaceMemberPickerDropdownContent';
|
||||||
|
|
||||||
type RoleWorkspaceMemberPickerDropdownProps = {
|
type RoleAssignmentWorkspaceMemberPickerDropdownProps = {
|
||||||
excludedWorkspaceMemberIds: string[];
|
excludedWorkspaceMemberIds: string[];
|
||||||
onSelect: (workspaceMember: WorkspaceMember) => void;
|
onSelect: (workspaceMember: WorkspaceMember) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RoleWorkspaceMemberPickerDropdown = ({
|
export const RoleAssignmentWorkspaceMemberPickerDropdown = ({
|
||||||
excludedWorkspaceMemberIds,
|
excludedWorkspaceMemberIds,
|
||||||
onSelect,
|
onSelect,
|
||||||
}: RoleWorkspaceMemberPickerDropdownProps) => {
|
}: RoleAssignmentWorkspaceMemberPickerDropdownProps) => {
|
||||||
const [searchFilter, setSearchFilter] = useState('');
|
const [searchFilter, setSearchFilter] = useState('');
|
||||||
|
|
||||||
const { loading, records: workspaceMembers } = useSearchRecords({
|
const { loading, records: workspaceMembers } = useSearchRecords({
|
||||||
@ -42,7 +42,7 @@ export const RoleWorkspaceMemberPickerDropdown = ({
|
|||||||
/>
|
/>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
<RoleWorkspaceMemberPickerDropdownContent
|
<RoleAssignmentWorkspaceMemberPickerDropdownContent
|
||||||
loading={loading}
|
loading={loading}
|
||||||
searchFilter={searchFilter}
|
searchFilter={searchFilter}
|
||||||
filteredWorkspaceMembers={filteredWorkspaceMembers}
|
filteredWorkspaceMembers={filteredWorkspaceMembers}
|
||||||
@ -2,19 +2,19 @@ import { t } from '@lingui/core/macro';
|
|||||||
import { MenuItem, MenuItemAvatar } from 'twenty-ui';
|
import { MenuItem, MenuItemAvatar } from 'twenty-ui';
|
||||||
import { WorkspaceMember } from '~/generated-metadata/graphql';
|
import { WorkspaceMember } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
type RoleWorkspaceMemberPickerDropdownContentProps = {
|
type RoleAssignmentWorkspaceMemberPickerDropdownContentProps = {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
searchFilter: string;
|
searchFilter: string;
|
||||||
filteredWorkspaceMembers: WorkspaceMember[];
|
filteredWorkspaceMembers: WorkspaceMember[];
|
||||||
onSelect: (workspaceMember: WorkspaceMember) => void;
|
onSelect: (workspaceMember: WorkspaceMember) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RoleWorkspaceMemberPickerDropdownContent = ({
|
export const RoleAssignmentWorkspaceMemberPickerDropdownContent = ({
|
||||||
loading,
|
loading,
|
||||||
searchFilter,
|
searchFilter,
|
||||||
filteredWorkspaceMembers,
|
filteredWorkspaceMembers,
|
||||||
onSelect,
|
onSelect,
|
||||||
}: RoleWorkspaceMemberPickerDropdownContentProps) => {
|
}: RoleAssignmentWorkspaceMemberPickerDropdownContentProps) => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -10,9 +10,9 @@ import {
|
|||||||
} from 'twenty-ui';
|
} from 'twenty-ui';
|
||||||
import { Role } from '~/generated-metadata/graphql';
|
import { Role } from '~/generated-metadata/graphql';
|
||||||
import { SettingsPermissions } from '~/generated/graphql';
|
import { SettingsPermissions } from '~/generated/graphql';
|
||||||
import { RolePermissionsObjectsTableHeader } from '~/pages/settings/roles/components/RolePermissionsObjectsTableHeader';
|
import { RolePermissionsObjectsTableHeader } from '~/pages/settings/roles/role-permissions/components/RolePermissionsObjectsTableHeader';
|
||||||
import { RolePermissionsSettingsTableHeader } from '~/pages/settings/roles/components/RolePermissionsSettingsTableHeader';
|
import { RolePermissionsSettingsTableHeader } from '~/pages/settings/roles/role-permissions/components/RolePermissionsSettingsTableHeader';
|
||||||
import { RolePermissionsSettingsTableRow } from '~/pages/settings/roles/components/RolePermissionsSettingsTableRow';
|
import { RolePermissionsSettingsTableRow } from '~/pages/settings/roles/role-permissions/components/RolePermissionsSettingsTableRow';
|
||||||
import { RolePermissionsObjectPermission } from '~/pages/settings/roles/types/RolePermissionsObjectPermission';
|
import { RolePermissionsObjectPermission } from '~/pages/settings/roles/types/RolePermissionsObjectPermission';
|
||||||
import { RolePermissionsObjectsTableRow } from './RolePermissionsObjectsTableRow';
|
import { RolePermissionsObjectsTableRow } from './RolePermissionsObjectsTableRow';
|
||||||
|
|
||||||
Reference in New Issue
Block a user