Skip to content

Commit fdb5d2f

Browse files
Feat 17408 : Add remove option for object permissions rule (#17601)
This PR aims to fix: #17408 Main modification includes adding a new column for dropdown in the object permission rule table (containing options for editing and removal). Removal logic is implemented using existing pattern with hook ```useResetObjectPermission``` (relies on existing hooks ```useUpsertFieldPermissionInDraftRole``` and ```useUpsertObjectPermissionInDraftRole```). Feel free to suggest any necessary changes. Functionality (unrestricted access is allowed when permission removal is applied) is already tested. Demo video: https://drive.google.com/file/d/1M4RYHw-JEhDdJksKkL3MY_VyXAV3aS9I/view?usp=sharing --------- Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
1 parent 5c2c588 commit fdb5d2f

File tree

5 files changed

+168
-14
lines changed

5 files changed

+168
-14
lines changed

packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelTableHeader.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ export const SettingsRolePermissionsObjectLevelTableHeader = ({
1616
<TableHeader>{showPermissionsLabel ? t`See Fields` : ''}</TableHeader>
1717
<TableHeader>{showPermissionsLabel ? t`Edit Fields` : ''}</TableHeader>
1818
<TableHeader></TableHeader>
19+
<TableHeader></TableHeader>
1920
</TableRow>
2021
);

packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelTableRow.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
22
import { SettingsRolePermissionsObjectLevelOverrideCellContainer } from '@/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelOverrideCellContainer';
33
import { SettingsRolePermissionsObjectLevelSeeFieldsValueForObject } from '@/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelSeeFieldsValueForObject';
4+
import { SettingsRolePermissionsObjectLevelTableRowOptionsDropdown } from '@/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelTableRowOptionsDropdown';
45
import { SettingsRolePermissionsObjectLevelUpdateFieldsValueForObject } from '@/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelUpdateFieldsValueForObject';
56
import { OBJECT_LEVEL_PERMISSION_TABLE_GRID_AUTO_COLUMNS } from '@/settings/roles/role-permissions/object-level-permissions/constants/ObjectLevelPermissionTableGridAutoColumns';
67
import { TableCell } from '@/ui/layout/table/components/TableCell';
@@ -9,11 +10,7 @@ import { useTheme } from '@emotion/react';
910
import styled from '@emotion/styled';
1011
import { SettingsPath } from 'twenty-shared/types';
1112
import { getSettingsPath } from 'twenty-shared/utils';
12-
import {
13-
IconChevronRight,
14-
OverflowingTextWithTooltip,
15-
useIcons,
16-
} from 'twenty-ui/display';
13+
import { OverflowingTextWithTooltip, useIcons } from 'twenty-ui/display';
1714

1815
const StyledNameTableCell = styled(TableCell)`
1916
color: ${({ theme }) => theme.font.color.primary};
@@ -26,6 +23,11 @@ const StyledNameLabel = styled.div`
2623
overflow: hidden;
2724
`;
2825

26+
const StyledOptionsTableCell = styled(TableCell)`
27+
justify-content: flex-end;
28+
padding-right: ${({ theme }) => theme.spacing(1)};
29+
`;
30+
2931
type SettingsRolePermissionsObjectLevelTableRowProps = {
3032
objectMetadataItem: ObjectMetadataItem;
3133
roleId: string;
@@ -90,14 +92,15 @@ export const SettingsRolePermissionsObjectLevelTableRow = ({
9092
objectMetadataItem={objectMetadataItem}
9193
/>
9294
</TableCell>
93-
{isEditable && (
94-
<TableCell align="right">
95-
<IconChevronRight
96-
size={theme.icon.size.md}
97-
color={theme.font.color.tertiary}
98-
/>
99-
</TableCell>
100-
)}
95+
<TableCell></TableCell>
96+
<StyledOptionsTableCell>
97+
<SettingsRolePermissionsObjectLevelTableRowOptionsDropdown
98+
roleId={roleId}
99+
objectMetadataId={objectMetadataItem.id}
100+
objectPermissionDetailUrl={navigationUrl}
101+
isEditable={isEditable}
102+
/>
103+
</StyledOptionsTableCell>
101104
</TableRow>
102105
);
103106
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { useResetObjectPermission } from '@/settings/roles/role-permissions/object-level-permissions/hooks/useResetObjectPermission';
2+
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
3+
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
4+
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
5+
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
6+
import { t } from '@lingui/core/macro';
7+
import { IconDotsVertical, IconPencil, IconTrash } from 'twenty-ui/display';
8+
import { IconButton } from 'twenty-ui/input';
9+
import { MenuItem, UndecoratedLink } from 'twenty-ui/navigation';
10+
11+
type SettingsRolePermissionsObjectLevelTableRowOptionsDropdownProps = {
12+
roleId: string;
13+
objectMetadataId: string;
14+
objectPermissionDetailUrl: string;
15+
isEditable: boolean;
16+
};
17+
18+
export const SettingsRolePermissionsObjectLevelTableRowOptionsDropdown = ({
19+
roleId,
20+
objectMetadataId,
21+
objectPermissionDetailUrl,
22+
isEditable,
23+
}: SettingsRolePermissionsObjectLevelTableRowOptionsDropdownProps) => {
24+
const dropdownId = `settings-role-object-level-options-${objectMetadataId}`;
25+
26+
const { closeDropdown } = useCloseDropdown();
27+
28+
const { resetObjectPermission } = useResetObjectPermission(roleId);
29+
30+
const handleRemove = () => {
31+
closeDropdown(dropdownId);
32+
resetObjectPermission(objectMetadataId);
33+
};
34+
35+
return (
36+
<Dropdown
37+
dropdownId={dropdownId}
38+
clickableComponent={
39+
<IconButton
40+
aria-label={t`Object permission options`}
41+
variant="tertiary"
42+
size="small"
43+
Icon={IconDotsVertical}
44+
/>
45+
}
46+
dropdownComponents={
47+
<DropdownContent>
48+
{isEditable && (
49+
<DropdownMenuItemsContainer>
50+
<UndecoratedLink
51+
fullWidth
52+
to={objectPermissionDetailUrl}
53+
onClick={() => closeDropdown(dropdownId)}
54+
>
55+
<MenuItem text={t`Edit`} LeftIcon={IconPencil} />
56+
</UndecoratedLink>
57+
</DropdownMenuItemsContainer>
58+
)}
59+
<DropdownMenuItemsContainer>
60+
<MenuItem
61+
text={t`Remove rule`}
62+
onClick={handleRemove}
63+
LeftIcon={IconTrash}
64+
accent="danger"
65+
/>
66+
</DropdownMenuItemsContainer>
67+
</DropdownContent>
68+
}
69+
dropdownPlacement="bottom-end"
70+
/>
71+
);
72+
};

packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/constants/ObjectLevelPermissionTableGridAutoColumns.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const {
44
} = {
55
OBJECT_LEVEL_PERMISSION_TABLE_GRID_AUTO_COLUMNS_WITHOUT_FIELD_PERMISSIONS:
66
'180px 1fr 1fr',
7-
OBJECT_LEVEL_PERMISSION_TABLE_GRID_AUTO_COLUMNS: '30% 20% 20% 20% 10%',
7+
OBJECT_LEVEL_PERMISSION_TABLE_GRID_AUTO_COLUMNS: '28% 18% 18% 18% 8% 10%',
88
};
99

1010
export {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { useUpsertFieldPermissionInDraftRole } from '@/settings/roles/role-permissions/object-level-permissions/field-permissions/hooks/useUpsertFieldPermissionInDraftRole';
2+
import { useUpsertObjectPermissionInDraftRole } from '@/settings/roles/role-permissions/object-level-permissions/hooks/useUpsertObjectPermissionInDraftRole';
3+
import { type SettingsRoleObjectPermissionKey } from '@/settings/roles/role-permissions/objects-permissions/constants/SettingsRoleObjectPermissionIconConfig';
4+
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
5+
import { useRecoilValue } from 'recoil';
6+
import { isDefined } from 'twenty-shared/utils';
7+
import {
8+
type FieldPermission,
9+
type ObjectPermission,
10+
} from '~/generated-metadata/graphql';
11+
12+
const OBJECT_PERMISSION_KEYS: SettingsRoleObjectPermissionKey[] = [
13+
'canReadObjectRecords',
14+
'canUpdateObjectRecords',
15+
'canSoftDeleteObjectRecords',
16+
'canDestroyObjectRecords',
17+
];
18+
19+
export const useResetObjectPermission = (roleId: string) => {
20+
const settingsDraftRole = useRecoilValue(
21+
settingsDraftRoleFamilyState(roleId),
22+
);
23+
24+
const { upsertObjectPermissionInDraftRole } =
25+
useUpsertObjectPermissionInDraftRole(roleId);
26+
27+
const { upsertFieldPermissionInDraftRole } =
28+
useUpsertFieldPermissionInDraftRole(roleId);
29+
30+
const resetObjectPermission = (objectMetadataItemId: string) => {
31+
const fieldPermissionsForCurrentObject =
32+
settingsDraftRole.fieldPermissions?.filter(
33+
(permission) => permission.objectMetadataId === objectMetadataItemId,
34+
) ?? [];
35+
const existingObjectPermission = settingsDraftRole.objectPermissions?.find(
36+
(objectPermissionToFind) =>
37+
objectPermissionToFind.objectMetadataId === objectMetadataItemId,
38+
);
39+
40+
const resetPermissions = OBJECT_PERMISSION_KEYS.reduce(
41+
(acc, permissionKey) => {
42+
acc[permissionKey] = null;
43+
return acc;
44+
},
45+
{} as Record<SettingsRoleObjectPermissionKey, null>,
46+
);
47+
48+
if (!isDefined(existingObjectPermission)) {
49+
const newObjectPermission = {
50+
objectMetadataId: objectMetadataItemId,
51+
...resetPermissions,
52+
} satisfies ObjectPermission;
53+
54+
upsertObjectPermissionInDraftRole(newObjectPermission);
55+
} else {
56+
const updatedObjectPermission = {
57+
...existingObjectPermission,
58+
...resetPermissions,
59+
};
60+
61+
upsertObjectPermissionInDraftRole(updatedObjectPermission);
62+
}
63+
64+
fieldPermissionsForCurrentObject.forEach(
65+
(fieldPermission: FieldPermission) => {
66+
upsertFieldPermissionInDraftRole({
67+
...fieldPermission,
68+
canUpdateFieldValue: null,
69+
canReadFieldValue: null,
70+
});
71+
},
72+
);
73+
};
74+
75+
return {
76+
resetObjectPermission,
77+
};
78+
};

0 commit comments

Comments
 (0)